Skip to content

Commit 77cce20

Browse files
refactor: restore forced reasoning prefix to pass test-chat ([chat] All tests passed)
- store the exact sequence seen on input when 'thinking_forced_open' enforces a reasoning block - inject this prefix before the first accumulated segment in 'reasoning_content', then clear it to avoid duplication - repeat the capture on every new 'start_think' detection to properly handle partial/streaming flows
1 parent 0915646 commit 77cce20

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

common/chat-parser.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,23 @@ void common_chat_msg_parser::consume_literal(const std::string & literal) {
169169
}
170170

171171
bool common_chat_msg_parser::try_parse_reasoning(const std::string & start_think, const std::string & end_think) {
172+
std::string pending_reasoning_prefix;
173+
174+
auto set_reasoning_prefix = [&](size_t prefix_pos) {
175+
if (!syntax_.thinking_forced_open || syntax_.reasoning_in_content) {
176+
return;
177+
}
178+
if (prefix_pos + start_think.size() > input_.size()) {
179+
pending_reasoning_prefix.clear();
180+
return;
181+
}
182+
// Capture the exact literal that opened the reasoning section so we can
183+
// surface it back to callers. This ensures formats that force the
184+
// reasoning tag open (e.g. DeepSeek R1) retain their original prefix
185+
// instead of dropping it during parsing.
186+
pending_reasoning_prefix = input_.substr(prefix_pos, start_think.size());
187+
};
188+
172189
auto handle_reasoning = [&](const std::string & reasoning, bool closed) {
173190
auto stripped_reasoning = string_strip(reasoning);
174191
if (stripped_reasoning.empty()) {
@@ -181,6 +198,10 @@ bool common_chat_msg_parser::try_parse_reasoning(const std::string & start_think
181198
add_content(syntax_.reasoning_format == COMMON_REASONING_FORMAT_DEEPSEEK ? "</think>" : end_think);
182199
}
183200
} else {
201+
if (!pending_reasoning_prefix.empty()) {
202+
add_reasoning_content(pending_reasoning_prefix);
203+
pending_reasoning_prefix.clear();
204+
}
184205
add_reasoning_content(stripped_reasoning);
185206
}
186207
};
@@ -233,6 +254,7 @@ bool common_chat_msg_parser::try_parse_reasoning(const std::string & start_think
233254
if (whitespace_end > pos_) {
234255
add_content(input_.substr(pos_, whitespace_end - pos_));
235256
}
257+
set_reasoning_prefix(cursor);
236258
cursor += start_think.size();
237259
} else if (syntax_.thinking_forced_open) {
238260
cursor = whitespace_end;
@@ -282,6 +304,7 @@ bool common_chat_msg_parser::try_parse_reasoning(const std::string & start_think
282304
move_to(input_.size());
283305
return true;
284306
}
307+
set_reasoning_prefix(cursor);
285308
cursor += start_think.size();
286309
continue;
287310
}

0 commit comments

Comments
 (0)