fix: strip only leading user-asking wrapper line

Refs #2215 Fix B: remove the mid-response stripping hazard without losing leading multi-line wrapper cleanup.

The pattern now strips only a leading 'the user is asking' wrapper line and preserves the visible answer that follows. Add regression coverage for both the leading-wrapper and mid-response prose cases.
This commit is contained in:
Frank Song committed 2026-05-14 09:14:28 +08:00
1 parent d8798ab355
commit 28ec3af697
2 files changed
+15 -1

No files matched your search

+1 -1
View File
@@ -695,7 +695,7 @@ def _strip_thinking_markup(text: str) -> str:
s = re.sub(r'^\s*<think>.*?</think>\s*', ' ', s, flags=re.IGNORECASE | re.DOTALL)
s = re.sub(r'^\s*<\|channel\|?>thought\n?.*?<channel\|>\s*', ' ', s, flags=re.IGNORECASE | re.DOTALL)
s = re.sub(r'^\s*<\|turn\|>thinking\n.*?<turn\|>\s*', ' ', s, flags=re.IGNORECASE | re.DOTALL) # Gemma 4
s = re.sub(r'^\s*(the|ther)\s+user\s+is\s+asking.*$', ' ', s, flags=re.IGNORECASE | re.MULTILINE)
s = re.sub(r'^\s*(the|ther)\s+user\s+is\s+asking[^\n]*(?:\n|$)', ' ', s, flags=re.IGNORECASE)
# Strip plain-text thinking preambles from models that don't use <think> tags (e.g. Qwen3).
# These appear as the very first sentence of the assistant response and are not useful as titles.
s = re.sub(
+14
View File
@@ -88,6 +88,20 @@ class TestGemma4ThinkingTokenStrip:
result = _strip_thinking_markup(raw)
assert result == raw
def test_leading_the_user_is_asking_wrapper_line_is_stripped(self):
"""A leading title-wrapper line is metadata; the visible answer should remain."""
raw = "The user is asking about Python imports.\nUse importlib for dynamic imports."
result = _strip_thinking_markup(raw)
assert result == "Use importlib for dynamic imports."
def test_mid_response_the_user_is_asking_line_is_preserved(self):
"""Only the leading wrapper line is stripped; normal mid-response prose survives."""
raw = "First, define the context.\nThe user is asking us to be patient.\nThen answer."
result = _strip_thinking_markup(raw)
assert "First, define the context." in result
assert "The user is asking us to be patient." in result
assert "Then answer." in result
def test_minimax_channel_without_second_pipe_still_stripped_at_start(self):
"""The client-facing MiniMax <|channel>thought shape is stripped when leading."""
raw = "<|channel>thought\nSome reasoning<channel|>Answer"