@@ -279,6 +279,7 @@ static common_chat_data common_chat_init_generic_tool_call(const common_chat_tem
279279 }
280280 : tool_call;
281281
282+ data.grammar_lazy = false ;
282283 data.grammar = build_grammar ([&](const common_grammar_builder & builder) {
283284 builder.add_schema (" root" , schema);
284285 }, grammar_options);
@@ -319,6 +320,7 @@ static common_chat_data common_chat_init_generic_tool_call(const common_chat_tem
319320static common_chat_data common_chat_init_mistral_nemo_tool_call (const common_chat_template & tmpl, const struct common_chat_params & params) {
320321 fprintf (stderr, " [%s]\n " , __func__);
321322 common_chat_data data;
323+ data.grammar_lazy = params.tool_choice != " required" ;
322324 data.grammar = build_grammar ([&](const common_grammar_builder & builder) {
323325 auto schemas = json::array ();
324326 foreach_function (params.tools , [&](const json & tool) {
@@ -352,9 +354,7 @@ static common_chat_data common_chat_init_mistral_nemo_tool_call(const common_cha
352354 }
353355 builder.add_rule (" root" , " \" [TOOL_CALLS]\" " + builder.add_schema (" tool_calls" , schema));
354356 }, grammar_options);
355- if (params.tool_choice != " required" ) {
356- data.grammar_triggers .push_back ({" [TOOL_CALLS]" , /* .at_start = */ true });
357- }
357+ data.grammar_triggers .push_back ({" [TOOL_CALLS]" , /* .at_start = */ true });
358358 data.prompt = tmpl.apply (params.messages , params.tools .empty () ? json () : params.tools , params.add_generation_prompt );
359359 data.format = " mistral nemo tool calls" ;
360360 data.parser = std::make_unique<monolithic_chat_parser>([](const std::string & input) {
@@ -369,6 +369,7 @@ static common_chat_data common_chat_init_llama_3_1_python_tag_tool_calls(const c
369369 auto builtin_tools = json {" wolfram_alpha" , " brave_search" };
370370 common_chat_data data;
371371
372+ data.grammar_lazy = params.tool_choice != " required" ;
372373 data.grammar = build_grammar ([&](const common_grammar_builder & builder) {
373374 std::vector<std::string> tool_rules;
374375
@@ -385,14 +386,10 @@ static common_chat_data common_chat_init_llama_3_1_python_tag_tool_calls(const c
385386 " \"\\\" name\\\" : \\\" " + name + " \\\" , \\\" parameters\\\" : \" " +
386387 builder.add_schema (name + " -args" , parameters) +
387388 " \" }\" " ));
388- if (params.tool_choice != " required" ) {
389- data.grammar_triggers .push_back ({" {\" name\" : \" " + name + " \" " , /* .at_start = */ true });
390- }
389+ data.grammar_triggers .push_back ({" {\" name\" : \" " + name + " \" " , /* .at_start = */ true });
391390 });
392391 tool_rules.push_back (builder.add_rule (" builtin-tool-call" , " \" <|python_tag|>\" .*" ));
393- if (params.tool_choice != " required" ) {
394- data.grammar_triggers .push_back ({" <|python_tag|>" , /* .at_start = */ false });
395- }
392+ data.grammar_triggers .push_back ({" <|python_tag|>" , /* .at_start = */ false });
396393 builder.add_rule (" root" , string_join (tool_rules, " | " ));
397394 }, grammar_options);
398395 data.additional_stops .push_back (" <|eom_id|>" );
@@ -429,6 +426,7 @@ static common_chat_data common_chat_init_llama_3_2_tool_calls(const common_chat_
429426 fprintf (stderr, " [%s]\n " , __func__);
430427 common_chat_data data;
431428
429+ data.grammar_lazy = params.tool_choice != " required" ;
432430 data.grammar = build_grammar ([&](const common_grammar_builder & builder) {
433431 std::vector<std::string> tool_rules;
434432
@@ -446,9 +444,7 @@ static common_chat_data common_chat_init_llama_3_2_tool_calls(const common_chat_
446444 " \"\\\" name\\\" : \\\" " + name + " \\\" , \\\" parameters\\\" : \" " +
447445 builder.add_schema (name + " -args" , parameters) +
448446 " \" }\" " ));
449- if (params.tool_choice != " required" ) {
450- data.grammar_triggers .push_back ({" {\" name\" : \" " + name + " \" " , /* .at_start = */ true });
451- }
447+ data.grammar_triggers .push_back ({" {\" name\" : \" " + name + " \" " , /* .at_start = */ true });
452448 });
453449
454450 builder.add_rule (" root" , string_join (tool_rules, " | " ));
@@ -468,8 +464,7 @@ static common_chat_data common_chat_init_llama_3_2_tool_calls(const common_chat_
468464static common_chat_data common_chat_init_deepseek_r1_tool_call (const common_chat_template & tmpl, const struct common_chat_params & params) {
469465 fprintf (stderr, " [%s]\n " , __func__);
470466 common_chat_data data;
471- data.grammar = " root ::= .*" ;
472- // data.grammar = "root ::= .*";
467+ data.grammar_lazy = params.tool_choice != " required" ;
473468 data.grammar = build_grammar ([&](const common_grammar_builder & builder) {
474469 std::vector<std::string> tool_rules;
475470 foreach_function (params.tools , [&](const json & tool) {
@@ -480,9 +475,7 @@ static common_chat_data common_chat_init_deepseek_r1_tool_call(const common_chat
480475 tool_rules.push_back (builder.add_rule (name + " -call" ,
481476 " \" <|tool▁call▁begin|>function<|tool▁sep|>" + name + " \\ n```json\\ n\" " + args_rule + " \" ```<|tool▁call▁end|>\" " ));
482477 });
483- if (params.tool_choice != " required" ) {
484- data.grammar_triggers .push_back ({" <|tool▁calls▁begin|>" , /* .at_start = */ false });
485- }
478+ data.grammar_triggers .push_back ({" <|tool▁calls▁begin|>" , /* .at_start = */ false });
486479 builder.add_rule (" root" , " \" <|tool▁calls▁begin|>\" (" + string_join (tool_rules, " | " ) + " )" + (params.parallel_tool_calls ? " *" : " " ) + " space" );
487480 }, grammar_options);
488481 data.prompt = tmpl.apply (params.messages , params.tools .empty () ? json () : params.tools , params.add_generation_prompt );
@@ -499,6 +492,7 @@ static common_chat_data common_chat_init_deepseek_r1_tool_call(const common_chat
499492static common_chat_data common_chat_init_firefunction_v2_tool_call (const common_chat_template & tmpl, const struct common_chat_params & params) {
500493 fprintf (stderr, " [%s]\n " , __func__);
501494 common_chat_data data;
495+ data.grammar_lazy = params.tool_choice != " required" ;
502496 data.grammar = build_grammar ([&](const common_grammar_builder & builder) {
503497 auto schemas = json::array ();
504498 foreach_function (params.tools , [&](const json & tool) {
@@ -525,9 +519,7 @@ static common_chat_data common_chat_init_firefunction_v2_tool_call(const common_
525519 }
526520 builder.add_rule (" root" , " \" functools\" ? " + builder.add_schema (" tool_calls" , schema));
527521 }, grammar_options);
528- if (params.tool_choice != " required" ) {
529- data.grammar_triggers .push_back ({" functools[" , /* .at_start = */ false });
530- }
522+ data.grammar_triggers .push_back ({" functools[" , /* .at_start = */ false });
531523 data.prompt = tmpl.apply (params.messages , params.tools .empty () ? json () : params.tools , params.add_generation_prompt );
532524 data.format = " firefunction v2 tool calls" ;
533525 data.parser = std::make_unique<monolithic_chat_parser>([](const std::string & input) {
@@ -542,6 +534,7 @@ static common_chat_data common_chat_init_functionary_v3_2_tool_call(const common
542534 // Using ">>>f1\n", ">>>f2\n"... as trigger words for the grammar
543535 common_chat_data data;
544536
537+ data.grammar_lazy = params.tool_choice != " required" ;
545538 data.grammar = build_grammar ([&](const common_grammar_builder & builder) {
546539 std::vector<std::string> first_tool_rules;
547540 std::vector<std::string> subsequent_tool_rules;
@@ -552,10 +545,8 @@ static common_chat_data common_chat_init_functionary_v3_2_tool_call(const common
552545 auto args_rule = builder.add_schema (name + " -args" , parameters);
553546 first_tool_rules.push_back (builder.add_rule (name + " -call" , " \" " + name + " \\ n\" " + args_rule));
554547 subsequent_tool_rules.push_back (builder.add_rule (name + " -call2" , " \" >>>" + name + " \\ n\" " + args_rule));
555- if (params.tool_choice != " required" ) {
556- data.grammar_triggers .push_back ({name, /* .at_start = */ true });
557- data.grammar_triggers .push_back ({" >>>" + name, /* .at_start = */ false });
558- }
548+ data.grammar_triggers .push_back ({name, /* .at_start = */ true });
549+ data.grammar_triggers .push_back ({" >>>" + name, /* .at_start = */ false });
559550 });
560551 auto first_rule = first_tool_rules.empty () ? " " : builder.add_rule (" first_tool_call" , string_join (first_tool_rules, " | " )) + " space" ;
561552 if (params.parallel_tool_calls ) {
@@ -591,6 +582,7 @@ static common_chat_data common_chat_init_functionary_v3_llama_3_1_tool_call(cons
591582 std::string python_code_argument_name;
592583 auto has_raw_python = false ;
593584
585+ data.grammar_lazy = params.tool_choice != " required" ;
594586 data.grammar = build_grammar ([&](const common_grammar_builder & builder) {
595587 std::vector<std::string> tool_rules;
596588 foreach_function (params.tools , [&](const json & tool) {
@@ -624,15 +616,11 @@ static common_chat_data common_chat_init_functionary_v3_llama_3_1_tool_call(cons
624616 });
625617 if (has_raw_python) {
626618 tool_rules.push_back (builder.add_rule (" python-call" , " \" <|python_tag|>\" .*" ));
627- if (params.tool_choice != " required" ) {
628- data.grammar_triggers .push_back ({" <|python_tag|>" , /* .at_start = */ false });
629- }
619+ data.grammar_triggers .push_back ({" <|python_tag|>" , /* .at_start = */ false });
630620 }
631621 auto tool_call = builder.add_rule (" tool_call" , string_join (tool_rules, " | " )) + " space" ;
632622 builder.add_rule (" root" , params.parallel_tool_calls ? " (" + tool_call + " )+" : tool_call);
633- if (params.tool_choice != " required" ) {
634- data.grammar_triggers .push_back ({" <function=" , /* .at_start = */ false });
635- }
623+ data.grammar_triggers .push_back ({" <function=" , /* .at_start = */ false });
636624 }, grammar_options);
637625
638626 data.prompt = tmpl.apply (params.messages , params.tools .empty () ? json () : params.tools , params.add_generation_prompt );
@@ -666,6 +654,7 @@ static common_chat_data common_chat_init_hermes_2_pro_tool_call(const common_cha
666654 fprintf (stderr, " [%s]\n " , __func__);
667655 common_chat_data data;
668656 // (content)?(<tool_call>{"name": "foo", "arguments": {"a": 1}}</tool_call>)*
657+ data.grammar_lazy = params.tool_choice != " required" ;
669658 data.grammar = build_grammar ([&](const common_grammar_builder & builder) {
670659 std::vector<std::string> tool_rules;
671660 foreach_function (params.tools , [&](const json & tool) {
@@ -684,9 +673,7 @@ static common_chat_data common_chat_init_hermes_2_pro_tool_call(const common_cha
684673 });
685674 auto tool_call = " \" <tool_call>\" space " + builder.add_rule (" tool_call" , string_join (tool_rules, " | " )) + " \" </tool_call>\" space" ;
686675 builder.add_rule (" root" , params.parallel_tool_calls ? " (" + tool_call + " )+" : tool_call);
687- if (params.tool_choice != " required" ) {
688- data.grammar_triggers .push_back ({" <tool_call>" , /* .at_start = */ false });
689- }
676+ data.grammar_triggers .push_back ({" <tool_call>" , /* .at_start = */ false });
690677 }, grammar_options);
691678
692679 data.prompt = tmpl.apply (params.messages , params.tools .empty () ? json () : params.tools , params.add_generation_prompt );
@@ -701,7 +688,11 @@ static common_chat_data common_chat_init_hermes_2_pro_tool_call(const common_cha
701688 std::sregex_iterator rend;
702689 std::sregex_iterator rit (input.begin (), end, start_pattern);
703690 if (rit == rend) {
704- return {" assistant" , input, {}};
691+ return {
692+ /* .role = */ " assistant" ,
693+ /* .content = */ input,
694+ /* .tool_calls = */ {},
695+ };
705696 }
706697
707698 common_chat_msg result;
@@ -732,7 +723,11 @@ static common_chat_data common_chat_init_hermes_2_pro_tool_call(const common_cha
732723 }
733724 return result;
734725 } catch (const std::exception & e) {
735- return {" assistant" , input, {}};
726+ return {
727+ /* .role = */ " assistant" ,
728+ /* .content = */ input,
729+ /* .tool_calls = */ {},
730+ };
736731 }
737732 });
738733 return data;
@@ -744,6 +739,7 @@ static common_chat_data common_chat_init_without_tools(const common_chat_templat
744739 data.prompt = tmpl.apply (params.messages , params.tools .empty () ? json () : params.tools , params.add_generation_prompt );
745740 data.format = " content-only" ;
746741 data.parser = std::make_unique<text_chat_parser>();
742+ data.grammar_lazy = false ;
747743 if (!params.json_schema .is_null ()) {
748744 if (!params.grammar .empty ()) {
749745 throw std::runtime_error (" Either \" json_schema\" or \" grammar\" can be specified, but not both" );
0 commit comments