From 8a81f640d2db175837091fae40af48a428a16e8a Mon Sep 17 00:00:00 2001
From: digital-garbage <133010426+digital-garbage@users.noreply.github.com>
Date: Sat, 16 May 2026 15:34:40 +0300
Subject: [PATCH] Fix thinking bleed: decode with skip_special_tokens=False to
preserve delimiters
Qwen3 encodes and as special token IDs (151648/151649).
With skip_special_tokens=True they are stripped silently before the regex
runs, leaving raw reasoning content concatenated with the response and no
way to separate them. The thinking content then bleeds into the repaired
prompt.
Fix: always decode with skip_special_tokens=False so the thinking delimiters
are present in the string. Strip complete ... blocks first,
then truncated blocks (no closing tag, model ran out of budget), then clean
remaining special tokens like <|im_end|> with a separate pattern.
Co-Authored-By: Claude Sonnet 4.6
---
conditioning.py | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/conditioning.py b/conditioning.py
index cbfe8524..ed0b69d8 100644
--- a/conditioning.py
+++ b/conditioning.py
@@ -11248,10 +11248,17 @@ class _FunPackAdvisorLLMWrapper:
output_ids = generated["output_ids"]
prompt_length = generated.get("prompt_length", 0)
new_tokens = output_ids[0][prompt_length:]
- text = self._tokenizer.decode(new_tokens, skip_special_tokens=skip_special_tokens)
- # Strip chain-of-thought thinking blocks emitted by models like Qwen3.
- text = re.sub(r"[\s\S]*?", "", text, flags=re.IGNORECASE).strip()
- return text
+ # Decode with special tokens preserved so thinking delimiters are visible
+ # for stripping. Models like Qwen3 encode / think> as special token
+ # IDs - with skip_special_tokens=True they vanish silently and the raw
+ # reasoning content bleeds into the output as if it were the response.
+ text = self._tokenizer.decode(new_tokens, skip_special_tokens=False)
+ # Strip complete thinking blocks first, then any truncated one (no closing tag).
+ text = re.sub(r"[\s\S]*?", "", text, flags=re.IGNORECASE)
+ text = re.sub(r"[\s\S]*", "", text, flags=re.IGNORECASE)
+ # Strip remaining special tokens: <|im_end|>, <|endoftext|>, etc.
+ text = re.sub(r"<\|[^|]*\|>", "", text)
+ return text.strip()
_FUNPACK_ADVISOR_LLM_CACHE = {}