Merge Q/A (CRT)
Slotting the LLM's answer back into the JSON
- qa_string
Merge Q/A (CRT) is the closing half of CRT-Nodes' Q/A data pipeline, and it does the unglamorous job the whole loop depends on: take a JSON Q/A pair with one field missing, take the text an LLM just generated, and insert that text into the missing field. The output is a complete, valid JSON pair you can log to disk or feed into a fine-tuning run.
Think of the loop this way: Extract Q/A (CRT) pulls one side out of the pair and builds an instruction, the LLM (via the pack's Unsloth Studio Bridge node) writes the other side, and then Merge Q/A is where the generated text goes back in. Without it you'd be doing that insert by hand or with a kludgy string-concat node, and every workflow that assembles Q/A rows ends up needing it.
Mechanically it's tiny and transparent: it parses your qa_string with json.loads, writes phrase into the chosen field, and re-serializes. Three inputs, and only one of them is interesting:
qa_string- the incomplete pair, e.g.{"user":"...","assistant":""}. Like its sibling it'sforceInput, so wire it in rather than typing.phrase- the text to insert. That's the LLM's response, straight out of your bridge node.target-auto(default),user, orassistant. Leave it onautoand let the node figure out which field is empty; that's the whole point. It checks each field with astrip()so a whitespace-only field still counts as empty, which is a nicer touch than most.
The single output, also named qa_string, is the completed pair as compact JSON (no pretty-printing, non-ASCII preserved). From there it usually feeds Text Add Rows (CRT) to append the finished row to a dataset file.
The one real gotcha is what happens when the auto-detection finds both fields filled - or both empty. Either way it logs a [WARN] to the console and defaults to writing the assistant field. So if you feed it a pair you thought was missing a question and your answer field gets silently overwritten, that's why. In practice: start from a genuinely incomplete pair and you'll never hit it, but it's worth knowing the node has opinions about ambiguity.
It's also worth saying what it isn't: it doesn't validate that your input is a well-formed Q/A pair beyond "is a JSON object." Give it a JSON array and it returns your input untouched, again with a console error. Same failure signature as Extract Q/A (CRT) - no crash, just no output change, so when the pipeline seems to stop doing anything, read the terminal.
Installation is the pack install, nothing extra for this node:
cd ComfyUI/custom_nodes
git clone https://github.com/PGCRT/CRT-Nodes
Restart ComfyUI after. Manager users can search "CRT-Nodes" instead. A fair warning if you let Manager install: the pack's requirements pull in heavy audio/ML dependencies (transformers, whisper, librosa, opencv) that this JSON helper - which is pure stdlib - will never touch. Cloning manually and skipping pip install -r requirements.txt is fine if the CRT/Text nodes are all you want.
It's a narrow node, and that's a compliment. In a pipeline whose entire purpose is turning LLM output into structured training data, the piece that keeps the structure valid is the one you want boring and predictable. This is exactly that.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| qa_string | STRING | Incomplete JSON Q/A pair, e.g. {"user":"...","assistant":""} | |
| phrase | STRING | Generated phrase to insert into the missing Q/A field. | |
| target | COMBO | auto | Field to fill. 'auto' fills the empty field based on the original string. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| qa_string | STRING | — |