@@ -1647,11 +1647,12 @@ static common_chat_params common_chat_params_init_lfm2(const common_chat_templat
16471647 data.thinking_start_tag = THINK_START ;
16481648 data.thinking_end_tag = THINK_END ;
16491649
1650- auto has_tools = inputs.tools .is_array () && !inputs.tools .empty ();
1650+ auto has_tools = inputs.tools .is_array () && !inputs.tools .empty ();
1651+ auto has_response_format = !inputs.json_schema .is_null () && inputs.json_schema .is_object ();
16511652 // Gate by reasoning format and whether the template supports <think>
16521653 auto extract_reasoning = inputs.reasoning_format != COMMON_REASONING_FORMAT_NONE &&
16531654 tmpl.source ().find (THINK_START ) != std::string::npos;
1654- auto include_grammar = has_tools && inputs.tool_choice != COMMON_CHAT_TOOL_CHOICE_NONE ;
1655+ auto include_grammar = has_response_format || ( has_tools && inputs.tool_choice != COMMON_CHAT_TOOL_CHOICE_NONE ) ;
16551656
16561657 if (inputs.has_continuation ()) {
16571658 const auto & msg = inputs.continue_msg ;
@@ -1674,6 +1675,10 @@ static common_chat_params common_chat_params_init_lfm2(const common_chat_templat
16741675 }
16751676
16761677 if (!has_tools || inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_NONE ) {
1678+ if (has_response_format) {
1679+ auto response_format = p.content (p.schema (p.json (), " response-format-schema" , inputs.json_schema ));
1680+ return generation_prompt + reasoning + response_format + end;
1681+ }
16771682 return generation_prompt + reasoning + p.content (p.rest ()) + end;
16781683 }
16791684 auto tool_calls = p.rule (" tool-calls" ,
@@ -1692,13 +1697,17 @@ static common_chat_params common_chat_params_init_lfm2(const common_chat_templat
16921697 data.parser = parser.save ();
16931698
16941699 if (include_grammar) {
1695- data.grammar_lazy = inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_AUTO ;
1700+ data.grammar_lazy = !(has_response_format || (has_tools && inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_REQUIRED )) ;
16961701 data.grammar = build_grammar ([&](const common_grammar_builder & builder) {
16971702 foreach_function (inputs.tools , [&](const json & tool) {
16981703 const auto & function = tool.at (" function" );
16991704 auto schema = function.at (" parameters" );
17001705 builder.resolve_refs (schema);
17011706 });
1707+ if (has_response_format) {
1708+ auto schema = inputs.json_schema ;
1709+ builder.resolve_refs (schema);
1710+ }
17021711 parser.build_grammar (builder, data.grammar_lazy );
17031712 });
17041713
0 commit comments