This commit is contained in:
Xuan Son Nguyen
2026-08-21 22:43:39 +02:00
parent 039426a696
commit 03eb25f393
18 changed files with 70 additions and 57 deletions
+2 -2
View File
@@ -311,7 +311,7 @@ common_peg_parser analyze_tools::build_tool_parser_tag_json(parser_build_context
foreach_function(inputs.tools, [&](const json & tool) {
const auto & func = tool.at("function");
std::string name = func.at("name").get<std::string>();
std::string name = func.at("name");
const auto & schema = func.contains("parameters") ? func.at("parameters") : json::object();
// Build call_id parser based on position (if supported)
@@ -384,7 +384,7 @@ common_peg_parser analyze_tools::build_tool_parser_tag_tagged(parser_build_conte
foreach_function(inputs.tools, [&](const json & tool) {
const auto & func = tool.at("function");
std::string name = func.at("name").get<std::string>();
std::string name = func.at("name");
auto params = func.contains("parameters") ? func.at("parameters") : json::object();
const auto & properties = params.contains("properties") ? params.at("properties") : json::object();
+5 -5
View File
@@ -488,7 +488,7 @@ common_peg_parser common_chat_peg_builder::standard_constructed_tools(
continue;
}
const auto & function = tool_def.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
ordered_json params = function.contains("parameters") ? function.at("parameters") : ordered_json::object();
// Build argument parsers
@@ -565,7 +565,7 @@ common_peg_parser common_chat_peg_builder::python_style_tool_calls(
continue;
}
const auto & function = tool_def.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
ordered_json params = function.contains("parameters") ? function.at("parameters") : ordered_json::object();
auto args = eps();
@@ -640,7 +640,7 @@ common_peg_parser common_chat_peg_builder::build_json_tools_function_is_key(
continue;
}
const auto & function = tool_def.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
ordered_json params = function.contains("parameters") ? function.at("parameters") : ordered_json::object();
// Build inner object fields
@@ -726,7 +726,7 @@ common_peg_parser common_chat_peg_builder::build_json_tools_nested_keys(
continue;
}
const auto & function = tool_def.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
ordered_json params = function.contains("parameters") ? function.at("parameters") : ordered_json::object();
auto nested_name = literal("\"" + nested_name_field + "\"") + space() + literal(":") + space() +
@@ -795,7 +795,7 @@ common_peg_parser common_chat_peg_builder::build_json_tools_flat_keys(
continue;
}
const auto & function = tool_def.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
ordered_json params = function.contains("parameters") ? function.at("parameters") : ordered_json::object();
auto tool_name_ = name_key_parser + space() + literal(":") + space() +
+14 -14
View File
@@ -968,7 +968,7 @@ static std::string common_chat_template_direct_apply_impl(
jinja::caps_apply_preserve_reasoning(ctx, enabled);
}
if (inp.contains("reasoning_effort") && inp["reasoning_effort"].is_string() && !inp["reasoning_effort"].empty()) {
std::string reasoning_effort = inp["reasoning_effort"].get<std::string>();
std::string reasoning_effort = inp["reasoning_effort"];
jinja::caps_apply_reasoning_effort(ctx, reasoning_effort);
}
@@ -1113,7 +1113,7 @@ static common_chat_params common_chat_params_init_ministral_3(const common_chat_
auto tool_choice = p.choice();
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
const auto & schema = function.at("parameters");
tool_choice |=
@@ -1221,7 +1221,7 @@ static common_chat_params common_chat_params_init_qwen3_coder(const common_chat_
// starting <tool_call>. The model may hallucinate a tool name, but it is preferable over
// constraining on <function which may occur in valid content generation, e.g. #include <functional>
foreach_function(inputs.tools, [&](const json & tool) {
const std::string name = tool.at("function").at("name").get<std::string>();
const std::string name = tool.at("function").at("name");
tool_call_starts.push_back("<function=" + name + ">");
});
@@ -1249,7 +1249,7 @@ static common_chat_params common_chat_params_init_qwen3_coder(const common_chat_
auto tool_choice = p.choice();
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
auto parameters = function.contains("parameters") ? function.at("parameters") : json::object();
auto schema_info = common_schema_info();
@@ -1440,7 +1440,7 @@ static common_chat_params common_chat_params_init_gpt_oss(const common_chat_temp
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
const auto & params = function.at("parameters");
auto func_name = p.literal(" to=functions.") + p.tool_name(p.literal(name));
@@ -1606,7 +1606,7 @@ static common_chat_params common_chat_params_init_gemma4(const common_chat_templ
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
// TODO @aldehir : need to extend json-schema-to-grammar to produce more than JSON rules
// const auto & params = function.at("parameters");
@@ -1705,7 +1705,7 @@ static common_chat_params common_chat_params_init_functionary_v3_2(const common_
auto tool_choice = p.choice();
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
const auto & schema = function.at("parameters");
// Tool format: >>>function_name\n{json_args}
@@ -1842,7 +1842,7 @@ static common_chat_params common_chat_params_init_kimi_k2(const common_chat_temp
auto tool_choice = p.choice();
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
const auto & schema = function.at("parameters");
// Match: functions.<name>:<digits>
@@ -2036,7 +2036,7 @@ static common_chat_params common_chat_params_init_gigachat_v3(
auto tool_choice = p.choice();
for (const auto & tool : inputs.tools) {
const auto & function = tool.at("function");
std::string name = function.at("name").get<std::string>();
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)) + "\"");
@@ -2232,7 +2232,7 @@ static common_chat_params common_chat_params_init_deepseek_v3_2(const common_cha
if (has_tool_calls) {
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
auto params = function.contains("parameters") ? function.at("parameters") : json::object();
const auto & props = params.contains("properties") ? params.at("properties") : json::object();
@@ -2467,7 +2467,7 @@ static common_chat_params common_chat_params_init_kimi_k3(const common_chat_temp
auto tool_choices = p.choice();
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
const json schema = function.contains("parameters") ? function.at("parameters") : json::object();
// arguments come one tag per key, with the JSON type in a type="..."
@@ -2788,7 +2788,7 @@ static common_chat_params common_chat_params_init_minimax_m3(const common_chat_t
auto tool_choice = p.choice();
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
auto params = function.contains("parameters") ? function.at("parameters") : json::object();
auto schema_info = common_schema_info();
@@ -3242,7 +3242,7 @@ static common_chat_params common_chat_params_init_minicpm5(const common_chat_tem
auto tool_choice = p.choice();
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
const std::string name = function.at("name").get<std::string>();
const std::string name = function.at("name");
auto params = function.contains("parameters") ? function.at("parameters") : json::object();
auto args = p.eps();
@@ -3388,7 +3388,7 @@ static common_chat_params common_chat_params_init_muse_glimmer(const common_chat
auto tool_choice = p.choice();
foreach_function(inputs.tools, [&](const json & tool) {
const auto & function = tool.at("function");
const std::string name = function.at("name").get<std::string>();
const std::string name = function.at("name");
auto params = function.contains("parameters") ? function.at("parameters") : json::object();
auto args = p.eps();
+1 -1
View File
@@ -921,7 +921,7 @@ std::string common_docker_resolve_model(const std::string & docker) {
if (manifest.contains("layers")) {
for (const auto & layer : manifest["layers"]) {
if (layer.contains("mediaType")) {
std::string media_type = layer["mediaType"].get<std::string>();
std::string media_type = layer["mediaType"];
if (media_type == "application/vnd.docker.ai.gguf.v3" ||
media_type.find("gguf") != std::string::npos) {
gguf_digest = layer["digest"].get<std::string>();
+2 -2
View File
@@ -244,8 +244,8 @@ static std::string get_repo_commit(const std::string & repo_id,
!branch.contains("targetCommit") || !branch["targetCommit"].is_string()) {
continue;
}
std::string _name = branch["name"].get<std::string>();
std::string _commit = branch["targetCommit"].get<std::string>();
std::string _name = branch["name"];
std::string _commit = branch["targetCommit"];
if (!is_valid_subpath(refs_path, _name)) {
LOG_WRN("%s: skip invalid branch: %s\n", __func__, _name.c_str());
+4 -4
View File
@@ -845,7 +845,7 @@ public:
}
} else if (n.is_object()) {
if (n.contains("$ref")) {
std::string ref = n["$ref"].get<std::string>();
std::string ref = n["$ref"];
if (_refs.find(ref) == _refs.end()) {
json target;
if (ref.find("https://") == 0) {
@@ -947,7 +947,7 @@ public:
}
if ((schema_type.is_null() || schema_type == "object")
&& (schema.contains("properties") ||
(schema.contains("additionalProperties") && schema["additionalProperties"] != true))) {
(schema.contains("additionalProperties") && !schema["additionalProperties"].get<bool>()))) {
std::unordered_set<std::string> required;
if (schema.contains("required") && schema["required"].is_array()) {
for (const auto & item : schema["required"]) {
@@ -1135,7 +1135,7 @@ bool common_schema_info::resolves_to_string(const common_json & schema) {
// Handle $ref
if (s.contains("$ref")) {
const std::string ref = s["$ref"].get<std::string>();
const std::string ref = s["$ref"];
if (visited_refs.find(ref) != visited_refs.end()) {
// Circular reference, assume not a string to be safe
return false;
@@ -1218,7 +1218,7 @@ bool common_schema_info::resolves_to_string(const common_json & schema) {
// Check format - many formats imply string
if (s.contains("format")) {
const std::string fmt = s["format"].get<std::string>();
const std::string fmt = s["format"];
if (fmt == "date" || fmt == "time" || fmt == "date-time" ||
fmt == "uri" || fmt == "email" || fmt == "hostname" ||
fmt == "ipv4" || fmt == "ipv6" || fmt == "uuid" ||
+13
View File
@@ -148,6 +148,10 @@ class common_json {
common_json & operator[](const std::string & key);
const common_json & operator[](const std::string & key) const;
common_json & operator[](const char * key) { return (*this)[std::string(key)]; }
const common_json & operator[](const char * key) const { return (*this)[std::string(key)]; }
common_json & operator[](int idx) { return (*this)[(size_t) idx]; }
const common_json & operator[](int idx) const { return (*this)[(size_t) idx]; }
common_json & operator[](size_t idx);
const common_json & operator[](size_t idx) const;
@@ -164,6 +168,15 @@ class common_json {
// only for the types instantiated in json.cpp, the rest fails at link time
template <typename T> T get() const;
// implicit get<T>() for plain values, so they can be assigned to their C++ type directly
// note: kept to this short list on purpose, a wider one makes j["key"] ambiguous
operator std::string() const { return get<std::string>(); }
operator bool() const { return get<bool>(); }
operator int() const { return get<int>(); }
operator int64_t() const { return get<int64_t>(); }
operator float() const { return get<float>(); }
operator double() const { return get<double>(); }
template <typename T>
T value(const std::string & key, T def) const {
return contains(key) ? at(key).get<T>() : def;
+1 -1
View File
@@ -475,7 +475,7 @@ static std::string detect_gguf_filename(const std::string & repo, const std::str
for (const auto & sibling : j["siblings"]) {
if (!sibling.contains("rfilename")) { continue; }
std::string fname = sibling["rfilename"].get<std::string>();
std::string fname = sibling["rfilename"];
if (fname.size() < 5 || fname.substr(fname.size() - 5) != ".gguf") {
continue;
}
+1 -1
View File
@@ -2157,7 +2157,7 @@ static void test_tagged_args_with_embedded_quotes(testing & t) {
for (const auto & tool_def : tools) {
if (!tool_def.contains("function")) { continue; }
const auto & function = tool_def.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
const auto & params = function.at("parameters");
if (!params.contains("properties") || !params.at("properties").is_object()) { continue; }
+4 -4
View File
@@ -114,9 +114,9 @@ static json create_tools() {
{ "default", 5 } } },
{ "category",
{ { "type", "string" },
{ "enum", { "api", "troubleshooting", "billing", "general" } },
{ "enum", json::array({ "api", "troubleshooting", "billing", "general" }) },
{ "description", "Filter search by specific category." } } } } },
{ "required", { "query", "category" } },
{ "required", json::array({ "query", "category" }) },
{ "additionalProperties", false } } },
{ "strict", true } } }
};
@@ -400,13 +400,13 @@ static void test_example_qwen3_coder(testing & t) {
std::vector<common_peg_parser> tool_parsers;
for (const auto & def : tools) {
auto function = def.at("function");
std::string name = function.at("name").get<std::string>();
std::string name = function.at("name");
auto parameters = function.at("parameters");
auto properties = parameters.at("properties");
std::set<std::string> required_properties;
if (function.contains("required")) {
required_properties = function.at("required").get<std::vector<std::string>>();
required_properties = function.at("required").get<std::set<std::string>>();
}
std::vector<common_peg_parser> arg_parsers;
+1 -1
View File
@@ -7052,7 +7052,7 @@ static void test_reasoning_budget_message_per_request() {
if (!llama_params.contains("reasoning_budget_message")) {
throw std::runtime_error("reasoning_budget_message missing from llama_params (thinking_end_tag may be empty for this template)");
}
std::string got = llama_params["reasoning_budget_message"].get<std::string>();
std::string got = llama_params["reasoning_budget_message"];
if (got != per_request_message) {
throw std::runtime_error("Expected reasoning_budget_message='" + per_request_message + "', got '" + got + "'");
}
+3 -3
View File
@@ -218,7 +218,7 @@ bool cli_context::list_and_ask_models() {
if (!m.contains("id") || !m.at("id").is_string()) {
continue;
}
std::string name = m.at("id").get<std::string>();
std::string name = m.at("id");
std::string display = name;
if (m.contains("aliases") && m.at("aliases").is_array()) {
std::vector<std::string> aliases;
@@ -387,14 +387,14 @@ bool cli_context::generate_completion(generated_content & content_out, cli_timin
}
const auto & delta = choice.at("delta");
if (delta.contains("reasoning_content") && delta.at("reasoning_content").is_string()) {
const std::string text = delta.at("reasoning_content").get<std::string>();
const std::string text = delta.at("reasoning_content");
if (!text.empty()) {
content_out.reasoning += text;
a.push(ui::ASSISTANT_DISPLAY_MODE_REASONING, text);
}
}
if (delta.contains("content") && delta.at("content").is_string()) {
const std::string text = delta.at("content").get<std::string>();
const std::string text = delta.at("content");
if (!text.empty()) {
content_out.content += text;
a.push(ui::ASSISTANT_DISPLAY_MODE_CONTENT, text);
+2 -2
View File
@@ -679,12 +679,12 @@ json convert_transcriptions_to_chatcmpl(
chatcmpl_body["stream"] = stream == "true";
if (inp_body.contains("max_tokens")) {
std::string inp = inp_body["max_tokens"].get<std::string>();
std::string inp = inp_body["max_tokens"];
chatcmpl_body["max_tokens"] = std::stoul(inp);
}
if (inp_body.contains("temperature")) {
std::string inp = inp_body["temperature"].get<std::string>();
std::string inp = inp_body["temperature"];
chatcmpl_body["temperature"] = std::stof(inp);
}
+3 -3
View File
@@ -5207,7 +5207,7 @@ void server_routes::init_routes() {
std::unique_ptr<server_res_generator> server_routes::handle_slots_save(const server_http_req & req, int id_slot) {
auto res = create_response();
const json request_data = json::parse(req.body);
std::string filename = request_data.at("filename").get<std::string>();
std::string filename = request_data.at("filename");
if (!fs_validate_filename(filename)) {
res->error(format_error_response("Invalid filename", ERROR_TYPE_INVALID_REQUEST));
return res;
@@ -5243,7 +5243,7 @@ std::unique_ptr<server_res_generator> server_routes::handle_slots_save(const ser
std::unique_ptr<server_res_generator> server_routes::handle_slots_restore(const server_http_req & req, int id_slot) {
auto res = create_response();
const json request_data = json::parse(req.body);
std::string filename = request_data.at("filename").get<std::string>();
std::string filename = request_data.at("filename");
if (!fs_validate_filename(filename)) {
res->error(format_error_response("Invalid filename", ERROR_TYPE_INVALID_REQUEST));
return res;
@@ -5332,7 +5332,7 @@ std::unique_ptr<server_res_generator> server_routes::handle_embeddings_impl(cons
bool use_base64 = false;
if (body.count("encoding_format") != 0) {
const std::string format = body.at("encoding_format").get<std::string>();
const std::string format = body.at("encoding_format");
if (format == "base64") {
use_base64 = true;
} else if (format != "float") {
+1 -1
View File
@@ -785,7 +785,7 @@ void server_http_context::register_gcp_compat() const {
try {
json payload = instance;
const std::string format = payload.at("@requestFormat").get<std::string>();
const std::string format = payload.at("@requestFormat");
payload.erase("@requestFormat");
if (payload.contains("stream")) {
+3 -3
View File
@@ -306,7 +306,7 @@ std::vector<std::unique_ptr<field>> make_llama_cmpl_schema(const common_params &
add((new field_str("generation_prompt"))
->set_desc("Generation prompt appended to the chat template output")
->set_handler([&](field_eval_context & ctx, const json & data) {
std::string s = data.at("generation_prompt").get<std::string>();
std::string s = data.at("generation_prompt");
ctx.params.chat_parser_params.generation_prompt = s;
ctx.params.sampling.generation_prompt = s;
}));
@@ -399,13 +399,13 @@ std::vector<std::unique_ptr<field>> make_llama_cmpl_schema(const common_params &
ctx.params.sampling.reasoning_budget_end.clear();
if (data.contains("reasoning_budget_end_tags")) {
for (const auto & t : data.at("reasoning_budget_end_tags")) {
std::string tag = t.get<std::string>();
std::string tag = t;
if (!tag.empty()) {
ctx.params.sampling.reasoning_budget_end.push_back(common_tokenize(ctx.vocab, tag, false, true));
}
}
} else if (data.contains("reasoning_budget_end_tag")) {
std::string tag = data.at("reasoning_budget_end_tag").get<std::string>();
std::string tag = data.at("reasoning_budget_end_tag");
if (!tag.empty()) {
ctx.params.sampling.reasoning_budget_end.push_back(common_tokenize(ctx.vocab, tag, false, true));
}
+1 -1
View File
@@ -510,7 +510,7 @@ server_http_context::handler_t server_stream_make_lookup_handler() {
if (body.contains("conversation_ids") && body["conversation_ids"].is_array()) {
for (const auto & v : body["conversation_ids"]) {
if (v.is_string()) {
std::string id = v.get<std::string>();
std::string id = v;
if (!id.empty()) {
requested.push_back(std::move(id));
}
+9 -9
View File
@@ -896,7 +896,7 @@ struct server_tool_read_file : server_tool {
}
json invoke(json params, server_tool::stream *) const override {
std::string path = params.at("path").get<std::string>();
std::string path = params.at("path");
int start_line = json_value(params, "start_line", 1);
int end_line = json_value(params, "end_line", -1); // -1 = no limit
bool append_loc = json_value(params, "append_loc", false);
@@ -1015,7 +1015,7 @@ struct server_tool_file_glob_search : server_tool {
json invoke(json params, server_tool::stream *) const override {
auto io = make_tools_io(params);
const std::string path = params.at("path").get<std::string>();
const std::string path = params.at("path");
std::string base = io->resolve(path);
std::string include = json_value(params, "include", std::string("**"));
@@ -1128,8 +1128,8 @@ struct server_tool_grep_search : server_tool {
}
json invoke(json params, server_tool::stream *) const override {
std::string path = params.at("path").get<std::string>();
std::string pat_str = params.at("pattern").get<std::string>();
std::string path = params.at("path");
std::string pat_str = params.at("pattern");
std::string include = json_value(params, "include", std::string("**"));
std::string exclude = json_value(params, "exclude", std::string(""));
bool show_lineno = json_value(params, "return_line_numbers", false);
@@ -1271,7 +1271,7 @@ struct server_tool_exec_shell_command : server_tool {
}
json invoke(json params, server_tool::stream * st) const override {
std::string command = params.at("command").get<std::string>();
std::string command = params.at("command");
int timeout = json_value(params, "timeout", 10);
size_t max_output = (size_t) json_value(params, "max_output_size", (int) SERVER_TOOL_EXEC_SHELL_COMMAND_MAX_OUTPUT_SIZE);
@@ -1348,8 +1348,8 @@ struct server_tool_write_file : server_tool {
}
json invoke(json params, server_tool::stream *) const override {
std::string path = params.at("path").get<std::string>();
std::string content = params.at("content").get<std::string>();
std::string path = params.at("path");
std::string content = params.at("content");
auto io = make_tools_io(params);
if (!io->write_file(path, content)) {
@@ -1405,7 +1405,7 @@ struct server_tool_edit_file : server_tool {
}
json invoke(json params, server_tool::stream *) const override {
std::string path = params.at("path").get<std::string>();
std::string path = params.at("path");
const json & edits_json = params.at("edits");
if (!edits_json.is_array() || edits_json.empty()) {
@@ -2078,7 +2078,7 @@ void server_tools::setup(const std::vector<std::string> & enabled_tools,
auto res = std::make_unique<server_tools_res>();
try {
json body = json::parse(req.body);
std::string tool_name = body.at("tool").get<std::string>();
std::string tool_name = body.at("tool");
json params = body.value("params", json::object());
bool stream = body.value("stream", false);