ComfyUI-TypedDecision
Having a multimodal LLM make a decision instead of writing text is sometimes called "Typed Decision". Jev is the well-known one, but several models can do the same thing locally, so I built them into a ComfyUI custom node.
Since the shape of the answer is fixed, it may come in handy for branching or for processing datasets. And above all, it's fast.
Let's look at what Typed Decision can do, and what you can do with it in ComfyUI.
Install
nomadoor/ComfyUI-TypedDecision
- Search for
TypedDecisioninComfyUI Managerand install it.
Supported models
| Model | Base | int8 size | Images | Video |
|---|---|---|---|---|
| d3-flash | Qwen3.5-9B | 9.88 GB | any number | ○ |
| d3-mini | Qwen3.5-4B | 5.52 GB | any number | ○ |
| d3-nano | Qwen3.5-2B | 3.06 GB | any number | ○ |
| d3-lite | Qwen3.5-0.8B | 1.21 GB | any number | ○ |
| Clef-flash | Qwen3.5-9B | 12.2 GB | any number | ○ |
| imajev-4b | Qwen3.5-4B + LoRA | 5.76 GB + 490 MB | up to 2 | × |
Everything in this article uses d3-mini. It performs well and is light on top of that, so I recommend it.
Downloading the models
d3 / Clef-flash
Put the ones you use in text_encoders.
- text_encoders
- d3_mini_int8_convrot.safetensors (5.52 GB)
- d3_flash_int8_convrot.safetensors (9.88 GB)
- d3_nano_int8_convrot.safetensors (3.06 GB)
- d3_lite_int8_convrot.safetensors (1.21 GB)
- clef_flash_int8_convrot.safetensors (12.2 GB)
📂ComfyUI/
└── 📂models/
└── 📂text_encoders/
└── d3_mini_int8_convrot.safetensors
imajev
imajev combines Qwen3.5-4B with the imajev-4b files.
- text_encoders
- qwen3.5_4b_int8_convrot.safetensors (5.76 GB)
- typed_decision
- mohit67890/imajev-4b (490 MB for the files below)
- Put these files in an
imajev-4bfolder. Downloading the whole repository also works.
- Put these files in an
- mohit67890/imajev-4b (490 MB for the files below)
📂ComfyUI/
└── 📂models/
├── 📂text_encoders/
│ └── qwen3.5_4b_int8_convrot.safetensors
└── 📂typed_decision/
└── 📂imajev-4b/
├── adapter_config.json
├── adapter_model.safetensors
├── calibration-rot4-modality.json
├── decision_readout.json
└── decision_readout.safetensors
Load Typed Decision Model
Pick the model file in backbone, and the kind of model in adapter.
| Model | backbone |
adapter |
|---|---|---|
| d3 | a d3 file | d3 |
| Clef-flash | a Clef-flash file | clef |
| imajev | a Qwen3.5-4B file | imajev-4b |
Once you pick an adapter, the settings that model supports appear.
debias(d3, imajev): judges with the options in different orders and averages the results. Less bias from the order, but slower- d3 also judges in reverse order, for choice only
- imajev judges up to four orders, in every mode
fps(d3, Clef-flash): how many video frames to read per second (default 2)calibration(imajev): applies temperature calibration
The three modes
There are three shapes a question can take. The one you pick changes both the input fields and the type of the answer. Write the questions and options in English.
The output sockets are the same across all three modes, but what they mean changes with the mode.
noul (Yes or No)
Answers a question with true or false.

Input
instructionstakes the claim to judge, or a question that can be answered yes / nocriteria_true/criteria_falseare optional. Use them to say when the answer should be yes or no
Output
valueis the probability of truelabelisyes/nopassis aBoolean:value >= threshold
Here the claim is "many people are in the image", judged true or false.
How many counts as "many" is vague, though. So the criteria spell it out: yes for five or more, no for four or fewer.
choice
Picks one of the options you supply.

Input
criteriatakes the options, one per line- When the name alone is not enough, add a description after
:, as inlandscape: scenery with no clear main subject
- When the name alone is not enough, add a description after
Output
valueis the probability of the chosen optionlabelis the chosen optionindexis the line it came from- The third line counts as
index2, since counting starts at 0
- The third line counts as
score
Rates something on the scale you define.

Input
criteriatakes the levels, one per line, lowest first
Output
valueis the expected level- The first line counts as
0, so five levels give a range of0.0to4.0
- The first line counts as
Here it rates how usable a photo is for a training dataset, on five levels.
value is an average weighted by the probability of each level, so it lands between levels, like 1.35. That reads as "between poor and acceptable, closer to poor".
Any number of images
d3 and Clef-flash take any number of images, so you can ask questions that compare several of them.
imajev takes up to two, and the first is the reference, the second is the one being judged.

Ask "are the first and second images the same person?" and you have a same-person check.
Video works too
With d3 and Clef-flash, connect a video to videos and it answers questions about the video.

The whole video is read at the fps set in Load Typed Decision Model, and all the frames are judged together in one go. A one-minute video at 2 fps is 120 frames.
At 2 fps it only looks every 0.5 seconds, so something that appears for just an instant may be missed.
Passing context with state
If instructions is the question, state is the context for answering it. Anything the image cannot tell you goes here as text.
Say you want to judge whether the product in a photo matches the color in a listing. Nothing in the question says which color is correct.
Put the listing in state and the model has something to compare against.
state:The listing says: red suede boat shoes.instructions:The shoes in the photo match the color in the listing.
statecan be JSON. Theninstructionscan name a field directly, as inlisting.color.
Typed Decision Moment Search
A node that finds the stretches of a video where a condition holds. It suits conditions a single frame can show, such as "a dog is visible" or "this person is visible". By design, it cannot judge the direction of a motion, such as "walking to the right".

Here it finds where the person in the reference image appears, and joins those stretches into one video.
Input
instructions/criteria_true/criteria_false/statework as in Typed Decision's noul- Connect a reference image to
imagesto find that person or thing in the video windowis how many frames are judged together at first (default 8, which is 4 seconds at 2 fps)thresholdis the probability a frame needs to pass
Output
intervalsis JSON with the start and end time of each stretch found, and morevideosholds the video cut out for each stretch- When nothing is found, the video nodes after it do not run

Writing the question
With a reference image, ask about the video.
- ○
The video shows the same person as the image. - ×
The person in the image is visible.
The second one is true of the reference image itself, so every frame passes.
Stretches are cut exactly where the model says. Someone half out of frame may already count as "not visible", so write the question for what you want to count.
In practice
Picking a resolution from the prompt
The examples above took images or video, but text alone works too.
Let's have it read the prompt and decide which shape to generate — portrait, landscape or square.

Three resolutions are prepared as a List, and the index output of choice switches between them.
- Put the prompt into
state - Have
choicepickportrait/landscape/squareindexis anINT, so portrait = 0, landscape = 1, square = 2
- Pass
indextoGet Item From Listto pull a width and a height - Feed both into
Empty Latent Imageand generate
This prompt chose square, and sure enough the image came out 1024 × 1024.

Sorting a dataset
Sorting a large pile of images seems like a good way to put that speed to use.

This sorts a folder of images into the ones that match a condition and the ones that do not.
Load Image (from Folder)reads the folder as a Listnouljudges whether a person is visiblepassgoes toIf/Else Switch, which switches the save path- There should now be a
typed_decisionfolder in ComfyUI's output folder, withacceptedandrejectedinside it
- There should now be a
Let's feed it a folder holding two photos of people and three of something else.



The images with a person land in accepted, the rest in rejected.




