Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions common/chat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1846,6 +1846,78 @@ static common_chat_params common_chat_params_init_deepseek_v3_1(const common_cha
return data;
}

static common_chat_params common_chat_params_init_gigachat_v3(
const common_chat_template & tmpl,
const struct templates_params & inputs) {

common_chat_params data;

auto prompt = apply(tmpl, inputs);
data.prompt = prompt;
data.format = COMMON_CHAT_FORMAT_PEG_NATIVE;

data.preserved_tokens = {
"<|message_sep|>\n\n",
"<|role_sep|>\n",
};

auto has_tools = inputs.tools.is_array() && !inputs.tools.empty();
auto include_grammar = true;
auto tool_call_start_prefix = "<|message_sep|>\n\nfunction call<|role_sep|>\n";

auto parser = build_chat_peg_native_parser([&](common_chat_peg_native_builder & p) {
if (has_tools && inputs.tool_choice != COMMON_CHAT_TOOL_CHOICE_NONE) {
// Build a choice of all available tools
auto tool_choice = p.choice();
for (const auto & tool : inputs.tools) {
const auto & function = tool.at("function");
std::string name = function.at("name");
const auto & schema = function.at("parameters");

auto tool_name = p.json_member("name", "\"" + p.tool_name(p.literal(name)) + "\"");
auto tool_args = p.json_member("arguments", p.tool_args(p.schema(p.json(), "tool-" + name + "-schema", schema)));

auto tool_open = p.tool_open(p.literal("{") << tool_name);

tool_choice |= p.rule("tool-" + name, tool_open << "," << tool_args << "}");
}

// Define the tool call structure
auto min_calls = inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_REQUIRED ? 1 : 0;
auto max_calls = 1; // parallel toolcalls are not supported
auto tool_call = p.rule("tool-call", p.literal(tool_call_start_prefix) + tool_choice);
auto tool_calls = p.trigger_rule("tool-call-root", p.repeat(tool_call, /* min = */ min_calls, /* max = */ max_calls));

return p.content(p.until("<|message_sep|>\n\n")) << tool_calls;
}

// Content only parser
include_grammar = false;
return p.content(p.rest());

});

data.parser = parser.save();

if (include_grammar) {
data.grammar_lazy = has_tools && inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_AUTO;

data.grammar = build_grammar([&](const common_grammar_builder & builder) {
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
auto schema = function.at("parameters");
builder.resolve_refs(schema);
});
parser.build_grammar(builder, data.grammar_lazy);
});

data.grammar_triggers = {
{COMMON_GRAMMAR_TRIGGER_TYPE_WORD, tool_call_start_prefix}
};
}
return data;
}

static common_chat_params common_chat_params_init_minimax_m2(const common_chat_template & tmpl, const struct templates_params & params) {
common_chat_params data;
data.grammar_lazy = params.tools.is_array() && !params.tools.empty() && params.tool_choice != COMMON_CHAT_TOOL_CHOICE_REQUIRED;
Expand Down Expand Up @@ -3236,6 +3308,11 @@ static common_chat_params common_chat_templates_apply_jinja(
return common_chat_params_init_solar_open(tmpl, params);
}

// GigaChatV3 format detection
if (src.find("<|role_sep|>") != std::string::npos && src.find("<|message_sep|>") != std::string::npos) {
return common_chat_params_init_gigachat_v3(tmpl, params);
}

// Use generic handler when mixing tools + JSON schema.
// TODO: support that mix in handlers below.
if ((params.tools.is_array() && params.json_schema.is_object())) {
Expand Down
Loading
Loading