Jev Interpret
Let a model judge your text instead of rewriting it
- candidates
- result
- details
- response_json
What it actually does
Almost every LLM node in ComfyUI does the same trick: take your rough idea, hand back a longer version, feed that to the encoder. You still accept whatever comes out.
Jev Interpret does the opposite half of the job. It doesn't write - it decides. Give it a pile of candidate prompts and an instruction like "choose the one that best fits a warm, approachable luxury brand" and it hands one of your candidates back. Or ask a yes/no question about a string, score something from 0 to 1, or pull the number out of "we shot at 7.5 stops". Not "make my prompt better" but "pick between these four", or "branch if the caption mentions a cat". Diffusion hands you options cheaply; something still has to choose.
How it works
You don't write a JSON schema. The node compiles state, instructions and task into a private question set and posts it to TypeSafe's SystemOne endpoint - Jev isn't a chat model, it's a judgment model that answers structured questions with choices and probabilities. provider defaults to typesafe; switch it to openrouter and the same request goes to OpenRouter's Jev decisions path instead (literally an /alpha/ URL, so don't build a business on it).
The neat part is the binding. For choice, your candidates become the criteria, the API picks one, and the node returns the original text of that candidate, byte for byte - not a paraphrase, not a JSON wrapper, your string. That's why result drops straight into a CLIP Text Encode. Same idea for JSON candidates: the model compares description, and you get the value back.
The inputs that matter
state- what's being judged. It doesn't take images; caption an image first and paste that in.instructions- the judgment itself, in plain language. Write it as a test, not a vibe.task- picks the mode.choicereturns one candidate's full text;multi_choicereturns every candidate that passes, as a JSON array;booleanreturns the stringtrueorfalseand needs no candidates;scoretreats your candidates as an ordered low-to-high scale and returns0–1;extractpulls a number out ofstateand returns its original text;suggestis the two-pass mode below.candidates- an autogrow input, one candidate per connection, up to 100. Each candidate is a link, not a text box: STRING outputs from Text nodes.candidates_json- the fast path. Connect OpenRouter Text's candidates-modetexthere, or paste a JSON array ofdescription/content/valuerecords. Wired candidates come first, then generated ones.threshold(0.5),refresh,model,provider,api_key. The advanced knobs matter only forsuggest:shortlist_size(3) is how many candidates get their full content read,max_selections(1) caps what comes back, andgate_threshold(0.3) filters out requests that never needed guidance.suggestcan legitimately return[], and that's a feature.
Outputs
result is the STRING you'll wire - into CLIP Text Encode, Preview as Text, Compare Text, a Switch, or a Convert Number node when task is score or extract. details carries the judgment plus model and usage, and response_json is the raw API response. Both are inspection outputs; nothing downstream consumes them in a normal graph.
Installing it
Search ComfyUI-Jev in ComfyUI Manager and restart. By hand:
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/hndrr/ComfyUI-Jev.git
The pack needs ComfyUI 0.36.0 or later and Python 3.10+. Its dependencies, aiohttp and PyYAML, ship with a standard ComfyUI install, but if the import fails:
python -m pip install "aiohttp>=3.11.8" PyYAML
Windows portable users, use the bundled interpreter:
.\python_embeded\python.exe -m pip install "aiohttp>=3.11.8" PyYAML
Then set a TypeSafe key and start ComfyUI from that terminal, so it inherits the variable:
export TYPESAFE_API_KEY="your-typesafe-key"
$env:TYPESAFE_API_KEY="your-typesafe-key"
Leave api_key empty to use it. Pasting the key into the node works too, but node values are saved into the workflow JSON and the execution history, so strip it before sharing a file.
Common issues
- The nodes don't show up. Usually an older ComfyUI - this pack uses the current node API. Restart and check the startup log for
import failed. - "Provide at least one candidate". You set
task = choicewith nothing connected. Candidates arrive over links: Text nodes, or acandidates_jsonarray. extracterrors instead of returning empty. By design - nothing instateanswering the instruction is an error, not a blank.- Running again gives the same answer. ComfyUI cached it. Changing the seed or resolution doesn't invalidate text nodes; bump
refreshfor a fresh judgment. jev-previewfails over OpenRouter. There's no verified alias for it there (onlyjev-latestandjev-1.13.0are mapped). Use TypeSafe, orcustomwith a real model ID.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| state | STRING | I want a sense of luxury that feels warm and approachable. | — |
| instructions | STRING | Choose the candidate that best meets the creative intent. | — |
| task | COMBO | choice | 6 options: choice, multi_choice, boolean, score, extract, suggest |
| candidates | COMFY_AUTOGROW_V3 | — | |
| model | COMBO | 4 options: [object Object], [object Object], [object Object], [object Object] | |
| provider | COMBO | typesafe | 2 options: typesafe, openrouter |
| api_key | STRING | Empty uses the provider's environment variable. Entered keys are saved in workflows; remove before sharing. | |
| refresh | INT | 0 | Keep fixed to reuse results. Change to request a new judgment. |
| candidates_jsonopt | STRING | Connect OpenRouter Text in candidates mode, or supply a JSON array of text strings or description/content/value records. | |
| thresholdopt | FLOAT | 0.500–1 | Minimum yes probability for boolean/multi_choice or candidate fit in suggest mode. |
| shortlist_sizeopt | INT | 3 | Suggest mode: how many candidates receive full-content verification. |
| max_selectionsopt | INT | 1 | Suggest mode: maximum accepted candidates. May return none. |
| gate_thresholdopt | FLOAT | 0.300–1 | Suggest mode: minimum need for specialized guidance before full-content verification. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| result | STRING | — |
| details | DICT | — |
| response_json | STRING | — |