Skip to content

Commit 22fc731

Browse files
authored
fix crashes for --reasoning-format=none
1 parent 5a2ac74 commit 22fc731

File tree

1 file changed

+33
-44
lines changed

1 file changed

+33
-44
lines changed

common/chat.cpp

Lines changed: 33 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,40 +1572,51 @@ inline void parse_msg_with_xml_tool_calls(common_chat_msg_parser & builder, cons
15721572
return out;
15731573
};
15741574

1575-
//builder.consume_spaces();
1576-
//builder.try_parse_reasoning(start_think, end_think);
1577-
15781575
const common_regex tool_call_start_regex(escape_regex(form.scope_start) + "\\s*" + escape_regex(form.tool_start));
15791576
LOG_DBG("Regex for tool start: %s\n", (escape_regex(form.scope_start) + "\\s*" + escape_regex(form.tool_start)).c_str());
15801577

1581-
// GLM 4.5 uses format: <tool_call>function_name\n<arg_key>key</arg_key>\n<arg_value>value</arg_value>\n</tool_call>
1578+
// Parse content
15821579
bool reasoning_unclosed = builder.syntax().thinking_forced_open;
15831580
std::string unclosed_reasoning_content("");
1584-
while (auto tc = builder.try_find_regex(tool_call_start_regex, std::string::npos, false)) {
1585-
auto &content = tc->prelude;
1586-
auto tool_call_start = builder.str(tc->groups[0]);
1587-
LOG_DBG("Matched tool start: %s\n", gbnf_format_literal(tool_call_start).c_str());
1581+
for (;;) {
1582+
auto tc = builder.try_find_regex(tool_call_start_regex, std::string::npos, false);
1583+
std::string content;
1584+
std::string tool_call_start;
1585+
1586+
if (tc) {
1587+
content = std::move(tc->prelude);
1588+
tool_call_start = builder.str(tc->groups[0]);
1589+
LOG_DBG("Matched tool start: %s\n", gbnf_format_literal(tool_call_start).c_str());
1590+
} else {
1591+
content = builder.consume_rest();
1592+
}
15881593

1594+
// Handle unclosed think block
15891595
if (reasoning_unclosed) {
1590-
if (auto pos = content.find(end_think); pos == std::string::npos) {
1596+
if (auto pos = content.find(end_think); pos == std::string::npos && builder.pos() != builder.input().size()) {
15911597
unclosed_reasoning_content += content + tool_call_start;
15921598
continue;
15931599
} else {
1594-
auto reasoning_content = content.substr(0, pos);
1595-
rstrip(reasoning_content);
1600+
std::string reasoning_content;
1601+
if (pos == std::string::npos) {
1602+
reasoning_content = std::move(content);
1603+
} else {
1604+
reasoning_content = content.substr(0, pos);
1605+
content.erase(0, pos + end_think.size());
1606+
}
15961607
if (builder.syntax().reasoning_format == COMMON_REASONING_FORMAT_NONE || builder.syntax().reasoning_in_content) {
15971608
if (builder.result().content.size() != 0) {
15981609
builder.add_content("\n\n");
15991610
}
16001611
builder.add_content(start_think);
16011612
builder.add_content(unclosed_reasoning_content);
16021613
builder.add_content(reasoning_content);
1603-
builder.add_content(end_think);
1614+
if (builder.pos() != builder.input().size() || std::any_of(content.begin(), content.end(), [](unsigned char c) { return !std::isspace(c); }))
1615+
builder.add_content(end_think);
16041616
} else {
16051617
builder.add_reasoning_content(unclosed_reasoning_content);
16061618
builder.add_reasoning_content(reasoning_content);
16071619
}
1608-
content.erase(0, pos + end_think.size());
16091620
unclosed_reasoning_content.clear();
16101621
reasoning_unclosed = false;
16111622
}
@@ -1616,14 +1627,13 @@ inline void parse_msg_with_xml_tool_calls(common_chat_msg_parser & builder, cons
16161627
for (auto think_start = content.rfind(start_think); think_start != std::string::npos; think_start = content.rfind(start_think, think_start - 1)) {
16171628
if (auto think_end = content.find(end_think, think_start + start_think.size()); think_end != std::string::npos) {
16181629
if (builder.syntax().reasoning_format != COMMON_REASONING_FORMAT_NONE && !builder.syntax().reasoning_in_content) {
1619-
auto reasoning_content = string_strip(content.substr(think_start + start_think.size(), think_end - think_start - start_think.size()));
1630+
auto reasoning_content = content.substr(think_start + start_think.size(), think_end - think_start - start_think.size());
16201631
builder.add_reasoning_content(reasoning_content);
16211632
think_start = erase_spaces(content, think_start, think_end + end_think.size() - 1);
16221633
}
16231634
} else {
16241635
// This <tool_call> start is in thinking block, skip this tool call
16251636
auto pos = think_start + start_think.size();
1626-
while (pos < content.size() && std::isspace(static_cast<unsigned char>(content[pos++])));
16271637
unclosed_reasoning_content = content.substr(pos) + tool_call_start;
16281638
reasoning_unclosed = true;
16291639
content.resize(think_start);
@@ -1654,6 +1664,14 @@ inline void parse_msg_with_xml_tool_calls(common_chat_msg_parser & builder, cons
16541664
continue;
16551665
}
16561666

1667+
// There is no tool call and all content is parsed
1668+
if (!tc) {
1669+
GGML_ASSERT(builder.pos() == builder.input().size());
1670+
GGML_ASSERT(unclosed_reasoning_content.empty());
1671+
GGML_ASSERT(!reasoning_unclosed);
1672+
break;
1673+
}
1674+
16571675
builder.move_to(tc->groups[0].begin);
16581676
if (!parse_xml_tool_calls(builder, form)) {
16591677
static const common_regex next_char_regex(".");
@@ -1662,35 +1680,6 @@ inline void parse_msg_with_xml_tool_calls(common_chat_msg_parser & builder, cons
16621680
builder.add_content(c);
16631681
}
16641682
}
1665-
1666-
builder.consume_spaces();
1667-
while (builder.pos() != builder.input().size()) {
1668-
builder.try_parse_reasoning(start_think, end_think);
1669-
builder.consume_spaces();
1670-
std::string content;
1671-
if (builder.syntax().reasoning_format == COMMON_REASONING_FORMAT_NONE || builder.syntax().reasoning_in_content) {
1672-
content = builder.consume_rest();
1673-
} else {
1674-
if (auto rsn = builder.try_find_literal(start_think)) {
1675-
builder.move_to(rsn->groups[0].begin);
1676-
content = std::move(rsn->prelude);
1677-
} else {
1678-
content = builder.consume_rest();
1679-
}
1680-
filter_unclosed_think(content, builder, end_think);
1681-
}
1682-
rstrip(content);
1683-
if (content.size() != 0) {
1684-
if (builder.result().content.size() != 0) {
1685-
builder.add_content("\n\n");
1686-
}
1687-
builder.add_content(content);
1688-
}
1689-
if (!builder.try_consume_literal(start_think)) {
1690-
break;
1691-
}
1692-
builder.move_to(builder.pos() - start_think.size());
1693-
}
16941683
}
16951684

16961685
static common_chat_params common_chat_params_init_generic(const common_chat_template & tmpl, const struct templates_params & inputs) {

0 commit comments

Comments
 (0)