StringReplaceFunction
Strip the think tags before your LLM's rambling reaches the sampler
- STRING
You wire a reasoning model like DeepSeek R1 into your prompt chain, and the first image has the model's inner monologue written all over it. R1 wraps its chain-of-thought in <think>...</think> tags, and when you feed the raw output to a text encoder, that deliberation goes straight into the conditioning. People put it bluntly in the community: DeepSeek seemed useless in ComfyUI because of "all the thinking stuff messing up my prompting workflows."
StringReplaceFunction is the scrubber. It's a plain find-and-replace node for strings, and out of the box it's configured to delete the think block - the default match is the regex \<think\>.*\<\/think\>\n+ with an empty value, which is the node's way of saying "find that and remove it."
How it works, from the source: a match_type dropdown picks between literal text mode and regex mode. In regex mode it compiles your pattern with re.DOTALL - the flag that makes . match newlines, which is exactly why the default pattern can span a multi-line reasoning block - then runs a standard re.sub. In text mode it's a dumb str.replace, which is what you want when your pattern would otherwise be a regex-escape nightmare. Either way, an empty value means deletion, so one node can remove tags, strip a "Here is your enhanced prompt:" preamble, or swap one tag block for another.
All four inputs are required, but only two matter most of the time:
- text - the string to scrub. It's marked as a default input, so it happily takes a wire from your LLM node.
- match - what to find. Defaults to the think-tag regex.
- value - the replacement; leave it empty to delete.
- match_type -
regex(default) ortext.
The output is a single STRING, which feeds into your CLIP Text Encode, prompt generator, or wherever the clean text is supposed to go.
Where people get burned, and this is the one worth remembering: the default regex ends in \n+, so it only matches when a newline follows </think>. Most models format output that way, but if yours puts the answer on the same line as the closing tag, nothing gets stripped - silently, because there's no error to stare at. Widen it to \<think\>.*\<\/think\>\s* and you're covered. Also note the .* is greedy and DOTALL-flavored, so it matches all the way to the last </think> in the text. That's fine for one thinking block; if your model thinks, answers, then thinks again, you'll delete the answer too. And remember this is real regex - a literal [ or . in your match needs escaping.
To install it, clone the pack and restart:
cd ComfyUI/custom_nodes
git clone https://github.com/sleechengn/ComfyUI-TypeAux
Or search "ComfyUI-TypeAux" in ComfyUI Manager's Install Custom Nodes. The pack has zero dependencies and downloads no models - pure stdlib - so it won't fight your environment the way the big LLM suites do.
That's the appeal. Fancier LLM packs build a regex cleaner in, but if yours doesn't scrub its own output, this is the dependency-free thing you reach for instead of dragging in a whole text-tools suite. One node, four inputs, get your prompt clean.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| text | STRING | — | |
| match | STRING | \<think\>.*\<\/think\>\n+ | — |
| value | STRING | — | |
| match_type | COMBO | regex | 2 options: text, regex |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| STRING | STRING | — |