Add workaround for templates requiring non-null content
This commit is contained in:
parent
22cae83218
commit
27f21d4d13
|
|
@ -2929,6 +2929,15 @@ static void system_message_not_supported(json & messages) {
|
|||
}
|
||||
}
|
||||
|
||||
static void requires_non_null_content(json & messages) {
|
||||
GGML_ASSERT(messages.is_array());
|
||||
for (auto & message : messages) {
|
||||
if (message.contains("tool_calls") && !messages.contains("content")) {
|
||||
messages["content"] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void func_args_not_string(json & messages) {
|
||||
GGML_ASSERT(messages.is_array());
|
||||
for (auto & message : messages) {
|
||||
|
|
@ -3034,6 +3043,10 @@ static common_chat_params common_chat_templates_apply_jinja(
|
|||
workaround::system_message_not_supported(params.messages);
|
||||
}
|
||||
|
||||
if (!tmpl.original_caps().requires_non_null_content) {
|
||||
workaround::requires_non_null_content(params.messages);
|
||||
}
|
||||
|
||||
params.extra_context = json::object();
|
||||
for (auto el : inputs.chat_template_kwargs) {
|
||||
params.extra_context[el.first] = json::parse(el.second);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ static void caps_print_stats(value & v, const std::string & path) {
|
|||
std::map<std::string, bool> caps::to_map() const {
|
||||
return {
|
||||
{"requires_typed_content", requires_typed_content},
|
||||
{"requires_non_null_content", requires_non_null_content},
|
||||
{"supports_tools", supports_tools},
|
||||
{"supports_tool_calls", supports_tool_calls},
|
||||
{"supports_parallel_tool_calls", supports_parallel_tool_calls},
|
||||
|
|
@ -160,7 +161,7 @@ caps caps_get(jinja::program & prog) {
|
|||
{"content", "Assistant message"},
|
||||
{"tool_calls", json::array({
|
||||
{
|
||||
{"id", "call1"},
|
||||
{"id", "call0001"},
|
||||
{"type", "function"},
|
||||
{"function", {
|
||||
{"name", "tool1"},
|
||||
|
|
@ -170,10 +171,10 @@ caps caps_get(jinja::program & prog) {
|
|||
}}
|
||||
},
|
||||
{
|
||||
{"id", "call2"},
|
||||
{"id", "call0002"},
|
||||
{"type", "function"},
|
||||
{"function", {
|
||||
{"name", "tool2"},
|
||||
{"name", "tool1"},
|
||||
{"arguments", {
|
||||
{"arg", "value"}
|
||||
}}
|
||||
|
|
@ -194,7 +195,7 @@ caps caps_get(jinja::program & prog) {
|
|||
{"name", "tool"},
|
||||
{"type", "function"},
|
||||
{"function", {
|
||||
{"name", "tool"},
|
||||
{"name", "tool1"},
|
||||
{"description", "Tool description"},
|
||||
{"parameters", {
|
||||
{"type", "object"},
|
||||
|
|
@ -238,6 +239,67 @@ caps caps_get(jinja::program & prog) {
|
|||
}
|
||||
);
|
||||
|
||||
// case: requires non-null content in tool calls
|
||||
caps_try_execute(
|
||||
prog,
|
||||
[&]() {
|
||||
// messages
|
||||
return json::array({
|
||||
{
|
||||
{"role", "user"},
|
||||
{"content", "User message"},
|
||||
},
|
||||
{
|
||||
{"role", "assistant"},
|
||||
{"tool_calls", json::array({
|
||||
{
|
||||
{"id", "call0001"},
|
||||
{"type", "function"},
|
||||
{"function", {
|
||||
{"name", "tool1"},
|
||||
{"arguments", {
|
||||
{"arg", "value"}
|
||||
}}
|
||||
}}
|
||||
},
|
||||
})}
|
||||
},
|
||||
{
|
||||
{"role", "user"},
|
||||
{"content", "User message"},
|
||||
},
|
||||
});
|
||||
},
|
||||
[&]() {
|
||||
// tools
|
||||
return json::array({
|
||||
{
|
||||
{"name", "tool"},
|
||||
{"type", "function"},
|
||||
{"function", {
|
||||
{"name", "tool1"},
|
||||
{"description", "Tool description"},
|
||||
{"parameters", {
|
||||
{"type", "object"},
|
||||
{"properties", {
|
||||
{"arg", {
|
||||
{"type", "string"},
|
||||
{"description", "Arg description"},
|
||||
}},
|
||||
}},
|
||||
{"required", json::array({ "arg" })},
|
||||
}},
|
||||
}},
|
||||
},
|
||||
});
|
||||
},
|
||||
[&](bool success, value & messages, value & tools) {
|
||||
if (!success) {
|
||||
result.requires_non_null_content = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// case: preserve reasoning content in chat history
|
||||
caps_try_execute(
|
||||
prog,
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ struct caps {
|
|||
bool supports_preserve_reasoning = false; // support assistant message with reasoning_content
|
||||
|
||||
bool requires_typed_content = false; // default: use string content
|
||||
bool requires_non_null_content = false; // requires "" instead of null for content in tool calls
|
||||
|
||||
// for reporting on server
|
||||
std::map<std::string, bool> to_map() const;
|
||||
|
|
|
|||
Loading…
Reference in New Issue