mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-07-23 11:10:55 -05:00
chat : fix LFM2 tool-call parsing double-escaping (#24667)
* Add escape test cases * chat : fix LFM2 tool-call parsing double-escaping
This commit is contained in:
@@ -540,10 +540,11 @@ common_peg_parser common_chat_peg_builder::python_style_tool_calls(
|
|||||||
auto arg_name_parser = literal(prop_name);
|
auto arg_name_parser = literal(prop_name);
|
||||||
|
|
||||||
common_peg_parser arg_value_parser = eps();
|
common_peg_parser arg_value_parser = eps();
|
||||||
auto string_value_parser = choice({
|
// Quoted literal as a value: normalize_quotes_to_json preserves escapes.
|
||||||
literal("\"") + tool_arg_string_value(string_content('"')) + literal("\""),
|
auto string_value_parser = tool_arg_value(choice({
|
||||||
literal("'") + tool_arg_string_value(string_content('\'')) + literal("'")
|
literal("\"") + string_content('"') + literal("\""),
|
||||||
});
|
literal("'") + string_content('\'') + literal("'")
|
||||||
|
}));
|
||||||
|
|
||||||
if (is_string_type) {
|
if (is_string_type) {
|
||||||
arg_value_parser = string_value_parser;
|
arg_value_parser = string_value_parser;
|
||||||
|
|||||||
@@ -1882,11 +1882,29 @@ static void test_lfm2_parser(const std::string & template_path, bool detailed_de
|
|||||||
.expect(simple_assist_msg("Use this format: [link text](url). Example: [Wikipedia](https://www.wikipedia.org)."))
|
.expect(simple_assist_msg("Use this format: [link text](url). Example: [Wikipedia](https://www.wikipedia.org)."))
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
// Python tool with multiline code in string
|
// Python tool with multiline code in string: the \n in the literal decodes to a real
|
||||||
|
// newline, emitted as a JSON \n escape (not a doubled backslash).
|
||||||
tst.test("<|tool_call_start|>[python(code=\"def hello():\\n print('hey')\")]<|tool_call_end|>")
|
tst.test("<|tool_call_start|>[python(code=\"def hello():\\n print('hey')\")]<|tool_call_end|>")
|
||||||
.tools({ python_tool })
|
.tools({ python_tool })
|
||||||
.expect_tool_calls({
|
.expect_tool_calls({
|
||||||
{ "python", R"#({"code": "def hello():\\n print('hey')"})#", "" }
|
{ "python", R"#({"code": "def hello():\n print('hey')"})#", "" }
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
|
||||||
|
// String escape sequences decode to their actual characters (newline + tab here),
|
||||||
|
// so a "write a two line file" style call produces real line breaks, not literal "\n".
|
||||||
|
tst.test("<|tool_call_start|>[python(code=\"First line\\nSecond line\\tindented\")]<|tool_call_end|>")
|
||||||
|
.tools({ python_tool })
|
||||||
|
.expect_tool_calls({
|
||||||
|
{ "python", R"#({"code": "First line\nSecond line\tindented"})#", "" }
|
||||||
|
})
|
||||||
|
.run();
|
||||||
|
|
||||||
|
// Escaped quotes inside a string argument survive the round-trip.
|
||||||
|
tst.test("<|tool_call_start|>[python(code=\"print(\\\"hi\\\")\")]<|tool_call_end|>")
|
||||||
|
.tools({ python_tool })
|
||||||
|
.expect_tool_calls({
|
||||||
|
{ "python", R"#({"code": "print(\"hi\")"})#", "" }
|
||||||
})
|
})
|
||||||
.run();
|
.run();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user