chat: fix LFM2/LFM2.5 ignoring json_schema (#24377)
The LFM2 specialized template handler only built a grammar for tool-calling, silently ignoring json_schema from response_format.
This commit is contained in:
+11
-2
@@ -1648,10 +1648,11 @@ static common_chat_params common_chat_params_init_lfm2(const common_chat_templat
|
|||||||
data.thinking_end_tag = THINK_END;
|
data.thinking_end_tag = THINK_END;
|
||||||
|
|
||||||
auto has_tools = inputs.tools.is_array() && !inputs.tools.empty();
|
auto has_tools = inputs.tools.is_array() && !inputs.tools.empty();
|
||||||
|
auto has_response_format = !inputs.json_schema.is_null() && inputs.json_schema.is_object();
|
||||||
// Gate by reasoning format and whether the template supports <think>
|
// Gate by reasoning format and whether the template supports <think>
|
||||||
auto extract_reasoning = inputs.reasoning_format != COMMON_REASONING_FORMAT_NONE &&
|
auto extract_reasoning = inputs.reasoning_format != COMMON_REASONING_FORMAT_NONE &&
|
||||||
tmpl.source().find(THINK_START) != std::string::npos;
|
tmpl.source().find(THINK_START) != std::string::npos;
|
||||||
auto include_grammar = has_tools && inputs.tool_choice != COMMON_CHAT_TOOL_CHOICE_NONE;
|
auto include_grammar = has_response_format || (has_tools && inputs.tool_choice != COMMON_CHAT_TOOL_CHOICE_NONE);
|
||||||
|
|
||||||
if (inputs.has_continuation()) {
|
if (inputs.has_continuation()) {
|
||||||
const auto & msg = inputs.continue_msg;
|
const auto & msg = inputs.continue_msg;
|
||||||
@@ -1674,6 +1675,10 @@ static common_chat_params common_chat_params_init_lfm2(const common_chat_templat
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!has_tools || inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_NONE) {
|
if (!has_tools || inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_NONE) {
|
||||||
|
if (has_response_format) {
|
||||||
|
auto response_format = p.content(p.schema(p.json(), "response-format-schema", inputs.json_schema));
|
||||||
|
return generation_prompt + reasoning + response_format + end;
|
||||||
|
}
|
||||||
return generation_prompt + reasoning + p.content(p.rest()) + end;
|
return generation_prompt + reasoning + p.content(p.rest()) + end;
|
||||||
}
|
}
|
||||||
auto tool_calls = p.rule("tool-calls",
|
auto tool_calls = p.rule("tool-calls",
|
||||||
@@ -1692,13 +1697,17 @@ static common_chat_params common_chat_params_init_lfm2(const common_chat_templat
|
|||||||
data.parser = parser.save();
|
data.parser = parser.save();
|
||||||
|
|
||||||
if (include_grammar) {
|
if (include_grammar) {
|
||||||
data.grammar_lazy = inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_AUTO;
|
data.grammar_lazy = !(has_response_format || (has_tools && inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_REQUIRED));
|
||||||
data.grammar = build_grammar([&](const common_grammar_builder & builder) {
|
data.grammar = build_grammar([&](const common_grammar_builder & builder) {
|
||||||
foreach_function(inputs.tools, [&](const json & tool) {
|
foreach_function(inputs.tools, [&](const json & tool) {
|
||||||
const auto & function = tool.at("function");
|
const auto & function = tool.at("function");
|
||||||
auto schema = function.at("parameters");
|
auto schema = function.at("parameters");
|
||||||
builder.resolve_refs(schema);
|
builder.resolve_refs(schema);
|
||||||
});
|
});
|
||||||
|
if (has_response_format) {
|
||||||
|
auto schema = inputs.json_schema;
|
||||||
|
builder.resolve_refs(schema);
|
||||||
|
}
|
||||||
parser.build_grammar(builder, data.grammar_lazy);
|
parser.build_grammar(builder, data.grammar_lazy);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user