diff --git a/common/chat.cpp b/common/chat.cpp index 84f7ac8587..aa21aa14bb 100644 --- a/common/chat.cpp +++ b/common/chat.cpp @@ -386,14 +386,14 @@ std::vector common_chat_msgs_parse_oaicompat(const json & messa if (!message.contains("role")) { throw std::invalid_argument("Missing 'role' in message: " + message.dump()); } - msg.role = message.at("role").get(); + msg.role = message.at("role"); auto has_content = message.contains("content"); auto has_tool_calls = message.contains("tool_calls"); if (has_content) { const auto & content = message.at("content"); if (content.is_string()) { - msg.content = content.get(); + msg.content = content; } else if (content.is_array()) { for (const auto & part : content) { if (!part.contains("type")) { @@ -404,8 +404,8 @@ std::vector common_chat_msgs_parse_oaicompat(const json & messa throw std::invalid_argument("Unsupported content part type: " + type.dump()); } common_chat_msg_content_part msg_part; - msg_part.type = type.get(); - msg_part.text = part.at("text").get(); + msg_part.type = type; + msg_part.text = part.at("text"); msg.content_parts.push_back(msg_part); } } else if (!content.is_null()) { @@ -431,15 +431,15 @@ std::vector common_chat_msgs_parse_oaicompat(const json & messa if (!fc.contains("name")) { throw std::invalid_argument("Missing tool call name: " + tool_call.dump()); } - tc.name = fc.at("name").get(); + tc.name = fc.at("name"); const auto & args = fc.at("arguments"); if (args.is_string()) { - tc.arguments = args.get(); + tc.arguments = args; } else { tc.arguments = args.dump(); } if (tool_call.contains("id")) { - tc.id = tool_call.at("id").get(); + tc.id = tool_call.at("id"); } msg.tool_calls.push_back(tc); } @@ -450,13 +450,13 @@ std::vector common_chat_msgs_parse_oaicompat(const json & messa "https://github.com/ggml-org/llama.cpp/issues/12279)"); } if (message.contains("reasoning_content")) { - msg.reasoning_content = message.at("reasoning_content").get(); + msg.reasoning_content = message.at("reasoning_content"); } if (message.contains("name")) { - msg.tool_name = message.at("name").get(); + msg.tool_name = message.at("name"); } if (message.contains("tool_call_id")) { - msg.tool_call_id = message.at("tool_call_id").get(); + msg.tool_call_id = message.at("tool_call_id"); } msgs.push_back(msg); @@ -937,7 +937,7 @@ static std::string common_chat_template_direct_apply_impl( jinja::context ctx(tmpl.source()); // messages_override is already built for this template, do not touch its content parts - common_json inp = common_json{ + json inp = json{ {"messages", messages_override.has_value() ? *messages_override : messages_inp_normalizer(tmpl.original_caps()).normalize(inputs.messages)}, @@ -2482,7 +2482,7 @@ static common_chat_params common_chat_params_init_kimi_k3(const common_chat_temp std::string type = "string"; if (prop.value().is_object() && prop.value().contains("type") && prop.value().at("type").is_string()) { - type = prop.value().at("type").get(); + type = prop.value().at("type"); } auto value = type == "string" ? p.tool_arg_string_value(p.until(ARG_END)) : @@ -3799,7 +3799,7 @@ static common_chat_params common_chat_templates_apply_legacy(const struct common common_chat_params params; params.prompt = std::string(buf.data(), res); if (!inputs.json_schema.empty()) { - params.grammar = json_schema_to_grammar(common_json::parse(inputs.json_schema)); + params.grammar = json_schema_to_grammar(json::parse(inputs.json_schema)); } else { params.grammar = inputs.grammar; } diff --git a/common/download.cpp b/common/download.cpp index 4b28a708c8..a7513974b0 100644 --- a/common/download.cpp +++ b/common/download.cpp @@ -924,7 +924,7 @@ std::string common_docker_resolve_model(const std::string & docker) { std::string media_type = layer["mediaType"].get(); if (media_type == "application/vnd.docker.ai.gguf.v3" || media_type.find("gguf") != std::string::npos) { - gguf_digest = layer["digest"].get(); + gguf_digest = layer["digest"]; break; } } diff --git a/common/hf-cache.cpp b/common/hf-cache.cpp index 50d6dd6105..55c4d3b9b3 100644 --- a/common/hf-cache.cpp +++ b/common/hf-cache.cpp @@ -213,7 +213,7 @@ static common_json api_get(const std::string & url, return common_json::parse(res->body); } try { - body = common_json::parse(res->body)["error"].get(); + body = common_json::parse(res->body)["error"]; } catch (...) { } throw std::runtime_error("GET failed (" + std::to_string(res->status) + "): " + body); @@ -320,7 +320,7 @@ hf_files get_repo_files(const std::string & repo_id, hf_file file; file.repo_id = repo_id; - file.path = item["path"].get(); + file.path = item["path"]; if (!is_valid_subpath(commit_path, file.path)) { LOG_WRN("%s: skip invalid path: %s\n", __func__, file.path.c_str()); @@ -329,10 +329,10 @@ hf_files get_repo_files(const std::string & repo_id, if (item.contains("lfs") && item["lfs"].is_object()) { if (item["lfs"].contains("oid") && item["lfs"]["oid"].is_string()) { - file.oid = item["lfs"]["oid"].get(); + file.oid = item["lfs"]["oid"]; } } else if (item.contains("oid") && item["oid"].is_string()) { - file.oid = item["oid"].get(); + file.oid = item["oid"]; } if (!file.oid.empty() && !is_valid_oid(file.oid)) { diff --git a/common/json.h b/common/json.h index 9415d57b36..4ad517f3a7 100644 --- a/common/json.h +++ b/common/json.h @@ -170,12 +170,9 @@ class common_json { // implicit get() 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 + // note: only std::string. adding a numeric one makes "str = json;" ambiguous, + // because a number can also convert to char, which std::string accepts operator std::string() const { return get(); } - operator bool() const { return get(); } - operator int() const { return get(); } - operator int64_t() const { return get(); } - operator float() const { return get(); } - operator double() const { return get(); } template T value(const std::string & key, T def) const { @@ -291,6 +288,8 @@ class common_json { private: // the backing value is built here, json.cpp checks that it fits + // it cannot be a pointer: a value inside a tree would then not be a common_json, + // so at() could only give back a copy instead of a real reference alignas(8) unsigned char storage[32]; }; diff --git a/tests/test-chat-template.cpp b/tests/test-chat-template.cpp index bcc574afe9..5255155af3 100644 --- a/tests/test-chat-template.cpp +++ b/tests/test-chat-template.cpp @@ -299,10 +299,10 @@ void run_single(const std::string& contents, json input, bool use_common, bool d std::string bos_token = ""; std::string eos_token = ""; if (input.contains("bos_token")) { - bos_token = input["bos_token"].get(); + bos_token = input["bos_token"]; } if (input.contains("eos_token")) { - eos_token = input["eos_token"].get(); + eos_token = input["eos_token"]; } common_json msgs_json = input["messages"]; common_json tools_json = input["tools"]; diff --git a/tools/server/server-chat.cpp b/tools/server/server-chat.cpp index a6fe3c6ba6..17e4e2d098 100644 --- a/tools/server/server-chat.cpp +++ b/tools/server/server-chat.cpp @@ -341,7 +341,7 @@ json server_chat_convert_anthropic_to_oai(const json & body) { std::string system_content; if (system_param.is_string()) { - system_content = system_param.get(); + system_content = system_param; normalize_anthropic_billing_header(system_content); } else if (system_param.is_array()) { for (const auto & block : system_param) { diff --git a/tools/server/server-mcp.cpp b/tools/server/server-mcp.cpp index 93db6164d3..fcac5061c8 100644 --- a/tools/server/server-mcp.cpp +++ b/tools/server/server-mcp.cpp @@ -157,7 +157,7 @@ std::vector server_mcp_server_config::parse_cursor_for } if (cfg.contains("env") && cfg.at("env").is_object()) { for (const auto & [k, v] : cfg.at("env").items()) { - sc.env[k] = v.get(); + sc.env[k] = v; } } diff --git a/tools/server/server-tools.cpp b/tools/server/server-tools.cpp index 12e9dbb8cf..9861809d11 100644 --- a/tools/server/server-tools.cpp +++ b/tools/server/server-tools.cpp @@ -1420,8 +1420,8 @@ struct server_tool_edit_file : server_tool { edits.reserve(edits_json.size()); for (const auto & e : edits_json) { edit_req er; - er.old_text = e.at("old_text").get(); - er.new_text = e.at("new_text").get(); + er.old_text = e.at("old_text"); + er.new_text = e.at("new_text"); if (er.old_text.empty()) { return {{"error", string_format("edits[%zu].old_text must not be empty", edits.size())}}; }