mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-20 01:31:31 +02:00
big wip
This commit is contained in:
@@ -81,6 +81,7 @@ add_library(${TARGET}
|
||||
imatrix-loader.cpp
|
||||
imatrix-loader.h
|
||||
json-schema-to-grammar.cpp
|
||||
json-shim.h
|
||||
json.cpp
|
||||
json.h
|
||||
llguidance.cpp
|
||||
|
||||
@@ -5,13 +5,12 @@
|
||||
#include "common.h"
|
||||
#include "json-schema-to-grammar.h"
|
||||
#include "log.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "peg-parser.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
using json = nlohmann::ordered_json;
|
||||
using json = common_json;
|
||||
|
||||
// Helper to iterate over tools/functions
|
||||
static void foreach_function(const json & tools, const std::function<void(const json &)> & fn) {
|
||||
@@ -312,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");
|
||||
std::string name = func.at("name").get<std::string>();
|
||||
const auto & schema = func.contains("parameters") ? func.at("parameters") : json::object();
|
||||
|
||||
// Build call_id parser based on position (if supported)
|
||||
@@ -385,13 +384,13 @@ 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");
|
||||
std::string name = func.at("name").get<std::string>();
|
||||
auto params = func.contains("parameters") ? func.at("parameters") : json::object();
|
||||
const auto & properties = params.contains("properties") ? params.at("properties") : json::object();
|
||||
|
||||
std::set<std::string> required;
|
||||
if (params.contains("required")) {
|
||||
params.at("required").get_to(required);
|
||||
required = params.at("required").get<std::set<std::string>>();
|
||||
}
|
||||
|
||||
auto schema_info = common_schema_info();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "common.h"
|
||||
#include "jinja/caps.h"
|
||||
#include "peg-parser.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "json.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <optional>
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using json = nlohmann::ordered_json;
|
||||
using json = common_json;
|
||||
|
||||
class common_chat_peg_builder;
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include "chat.h"
|
||||
#include "common.h"
|
||||
#include "log.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "peg-parser.h"
|
||||
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <ostream>
|
||||
@@ -17,7 +17,7 @@
|
||||
#define ANSI_ORANGE "\033[1m\x1b[38;5;214m"
|
||||
#define ANSI_RED "\033[1m\x1b[38;5;196m"
|
||||
|
||||
using json = nlohmann::ordered_json;
|
||||
using json = common_json;
|
||||
|
||||
namespace autoparser {
|
||||
|
||||
@@ -929,10 +929,10 @@ void analyze_tools::analyze_tool_call_format_json_native(const std::string & cle
|
||||
int json_end = clean_haystack.find_last_of('}');
|
||||
std::string cut = clean_haystack.substr(json_start, json_end - json_start + 1);
|
||||
json call_struct = json::parse(cut);
|
||||
auto register_field = [&](const std::string & prefix, const nlohmann::detail::iteration_proxy_value<json::iterator> & subel) {
|
||||
if (subel.value().is_string() && std::string(subel.value()).find("call0000") != std::string::npos) {
|
||||
auto register_field = [&](const std::string & prefix, const common_json_entry & subel) {
|
||||
if (subel.value().is_string() && subel.value().get<std::string>().find("call0000") != std::string::npos) {
|
||||
format.id_field = !prefix.empty() ? prefix + "." + subel.key() : subel.key();
|
||||
} else if (subel.value().is_string() && std::string(subel.value()) == fun_name_needle) {
|
||||
} else if (subel.value().is_string() && subel.value().get<std::string>() == fun_name_needle) {
|
||||
format.name_field = !prefix.empty() ? prefix + "." + subel.key() : subel.key();
|
||||
} else if (subel.value().dump().find(arg_name_needle) !=
|
||||
std::string::npos) { // handle both string and JSON obj variants
|
||||
|
||||
@@ -4,12 +4,11 @@
|
||||
#include "ggml.h"
|
||||
#include "peg-parser.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
using ordered_json = nlohmann::ordered_json;
|
||||
using ordered_json = common_json;
|
||||
|
||||
static std::string_view trim_trailing_space(std::string_view sv, int max = -1) {
|
||||
int count = 0;
|
||||
@@ -489,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
ordered_json params = function.contains("parameters") ? function.at("parameters") : ordered_json::object();
|
||||
|
||||
// Build argument parsers
|
||||
@@ -566,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
ordered_json params = function.contains("parameters") ? function.at("parameters") : ordered_json::object();
|
||||
|
||||
auto args = eps();
|
||||
@@ -641,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
ordered_json params = function.contains("parameters") ? function.at("parameters") : ordered_json::object();
|
||||
|
||||
// Build inner object fields
|
||||
@@ -727,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
ordered_json params = function.contains("parameters") ? function.at("parameters") : ordered_json::object();
|
||||
|
||||
auto nested_name = literal("\"" + nested_name_field + "\"") + space() + literal(":") + space() +
|
||||
@@ -796,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
ordered_json params = function.contains("parameters") ? function.at("parameters") : ordered_json::object();
|
||||
|
||||
auto tool_name_ = name_key_parser + space() + literal(":") + space() +
|
||||
|
||||
@@ -128,7 +128,7 @@ class common_chat_peg_builder : public common_peg_parser_builder {
|
||||
// parameters_order: order in which JSON fields should be parsed
|
||||
common_peg_parser standard_json_tools(const std::string & section_start,
|
||||
const std::string & section_end,
|
||||
const nlohmann::ordered_json & tools,
|
||||
const common_json & tools,
|
||||
bool parallel_tool_calls,
|
||||
bool force_tool_calls,
|
||||
const std::string & name_key = "",
|
||||
@@ -143,13 +143,13 @@ class common_chat_peg_builder : public common_peg_parser_builder {
|
||||
// Legacy-compatible helper for building XML/tagged style tool calls
|
||||
// Used by tests and manual parsers
|
||||
common_peg_parser standard_constructed_tools(const std::map<std::string, std::string> & markers,
|
||||
const nlohmann::ordered_json & tools,
|
||||
const common_json & tools,
|
||||
bool parallel_tool_calls,
|
||||
bool force_tool_calls);
|
||||
|
||||
// Helper for Python-style function call format: name(arg1="value1", arg2=123)
|
||||
// Used by LFM2 and similar templates
|
||||
common_peg_parser python_style_tool_calls(const nlohmann::ordered_json & tools,
|
||||
common_peg_parser python_style_tool_calls(const common_json & tools,
|
||||
bool parallel_tool_calls,
|
||||
bool allow_json_literals);
|
||||
|
||||
@@ -158,19 +158,19 @@ class common_chat_peg_builder : public common_peg_parser_builder {
|
||||
common_peg_parser python_or_json_value();
|
||||
|
||||
// Implementation helpers for standard_json_tools — one per JSON tool call layout mode
|
||||
common_peg_parser build_json_tools_function_is_key(const nlohmann::ordered_json & tools,
|
||||
common_peg_parser build_json_tools_function_is_key(const common_json & tools,
|
||||
const std::string & args_key,
|
||||
const std::string & effective_args_key,
|
||||
const std::string & call_id_key,
|
||||
const std::string & gen_call_id_key);
|
||||
|
||||
common_peg_parser build_json_tools_nested_keys(const nlohmann::ordered_json & tools,
|
||||
common_peg_parser build_json_tools_nested_keys(const common_json & tools,
|
||||
const std::string & effective_name_key,
|
||||
const std::string & effective_args_key,
|
||||
const std::string & call_id_key,
|
||||
const std::string & gen_call_id_key);
|
||||
|
||||
common_peg_parser build_json_tools_flat_keys(const nlohmann::ordered_json & tools,
|
||||
common_peg_parser build_json_tools_flat_keys(const common_json & tools,
|
||||
const std::string & effective_name_key,
|
||||
const std::string & effective_args_key,
|
||||
const std::string & call_id_key,
|
||||
|
||||
+42
-43
@@ -14,7 +14,6 @@
|
||||
#include "jinja/caps.h"
|
||||
#include "peg-parser.h"
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
@@ -31,7 +30,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using json = nlohmann::ordered_json;
|
||||
using json = common_json;
|
||||
|
||||
static std::string format_time(const std::chrono::system_clock::time_point & now, const std::string & format) {
|
||||
auto time = std::chrono::system_clock::to_time_t(now);
|
||||
@@ -49,7 +48,7 @@ static json safe_args_parse(const std::string & to_parse) {
|
||||
}
|
||||
try {
|
||||
return json::parse(stripped);
|
||||
} catch (json::exception & e) {
|
||||
} catch (const common_json_error & e) {
|
||||
return stripped;
|
||||
}
|
||||
}
|
||||
@@ -387,14 +386,14 @@ std::vector<common_chat_msg> 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");
|
||||
msg.role = message.at("role").get<std::string>();
|
||||
|
||||
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;
|
||||
msg.content = content.get<std::string>();
|
||||
} else if (content.is_array()) {
|
||||
for (const auto & part : content) {
|
||||
if (!part.contains("type")) {
|
||||
@@ -405,8 +404,8 @@ std::vector<common_chat_msg> 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;
|
||||
msg_part.text = part.at("text");
|
||||
msg_part.type = type.get<std::string>();
|
||||
msg_part.text = part.at("text").get<std::string>();
|
||||
msg.content_parts.push_back(msg_part);
|
||||
}
|
||||
} else if (!content.is_null()) {
|
||||
@@ -432,15 +431,15 @@ std::vector<common_chat_msg> 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");
|
||||
tc.name = fc.at("name").get<std::string>();
|
||||
const auto & args = fc.at("arguments");
|
||||
if (args.is_string()) {
|
||||
tc.arguments = args;
|
||||
tc.arguments = args.get<std::string>();
|
||||
} else {
|
||||
tc.arguments = args.dump();
|
||||
}
|
||||
if (tool_call.contains("id")) {
|
||||
tc.id = tool_call.at("id");
|
||||
tc.id = tool_call.at("id").get<std::string>();
|
||||
}
|
||||
msg.tool_calls.push_back(tc);
|
||||
}
|
||||
@@ -451,13 +450,13 @@ std::vector<common_chat_msg> 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");
|
||||
msg.reasoning_content = message.at("reasoning_content").get<std::string>();
|
||||
}
|
||||
if (message.contains("name")) {
|
||||
msg.tool_name = message.at("name");
|
||||
msg.tool_name = message.at("name").get<std::string>();
|
||||
}
|
||||
if (message.contains("tool_call_id")) {
|
||||
msg.tool_call_id = message.at("tool_call_id");
|
||||
msg.tool_call_id = message.at("tool_call_id").get<std::string>();
|
||||
}
|
||||
|
||||
msgs.push_back(msg);
|
||||
@@ -489,17 +488,17 @@ struct messages_inp_normalizer {
|
||||
json normalized = json::array();
|
||||
for (const auto & msg : messages) {
|
||||
json copy = msg;
|
||||
auto it = copy.find("content");
|
||||
if (it != copy.end()) {
|
||||
if (only_typed && it->is_string()) {
|
||||
*it = json::array({
|
||||
if (copy.contains("content")) {
|
||||
json & it = copy.at("content");
|
||||
if (only_typed && it.is_string()) {
|
||||
it = json::array({
|
||||
json{
|
||||
{"type", "text"},
|
||||
{"text", it->get<std::string>()},
|
||||
{"text", it.get<std::string>()},
|
||||
}
|
||||
});
|
||||
} else if (only_string && it->is_array()) {
|
||||
*it = concat_content_parts(*it);
|
||||
} else if (only_string && it.is_array()) {
|
||||
it = concat_content_parts(it);
|
||||
}
|
||||
}
|
||||
normalized.push_back(std::move(copy));
|
||||
@@ -596,7 +595,7 @@ std::vector<common_chat_tool> common_chat_tools_parse_oaicompat(const json & too
|
||||
|
||||
const auto & function = tool.at("function");
|
||||
result.push_back({
|
||||
/* .name = */ function.at("name"),
|
||||
/* .name = */ function.at("name").get<std::string>(),
|
||||
/* .description = */ function.value("description", ""),
|
||||
/* .parameters = */ function.value("parameters", json::object()).dump(),
|
||||
});
|
||||
@@ -609,7 +608,7 @@ std::vector<common_chat_tool> common_chat_tools_parse_oaicompat(const json & too
|
||||
return result;
|
||||
}
|
||||
|
||||
common_chat_continuation common_chat_continuation_parse(const nlohmann::ordered_json & value) {
|
||||
common_chat_continuation common_chat_continuation_parse(const common_json & value) {
|
||||
if (value.is_boolean() && value.get<bool>()) {
|
||||
return COMMON_CHAT_CONTINUATION_AUTO;
|
||||
}
|
||||
@@ -921,7 +920,7 @@ static void foreach_parameter(const json &
|
||||
const auto & props = params.at("properties");
|
||||
std::set<std::string> required;
|
||||
if (params.contains("required") && params.at("required").is_array()) {
|
||||
params.at("required").get_to(required);
|
||||
required = params.at("required").get<std::set<std::string>>();
|
||||
}
|
||||
for (const auto & [name, prop] : props.items()) {
|
||||
bool is_required = (required.find(name) != required.end());
|
||||
@@ -938,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
|
||||
nlohmann::ordered_json inp = nlohmann::ordered_json{
|
||||
common_json inp = common_json{
|
||||
{"messages", messages_override.has_value()
|
||||
? *messages_override
|
||||
: messages_inp_normalizer(tmpl.original_caps()).normalize(inputs.messages)},
|
||||
@@ -973,7 +972,7 @@ static std::string common_chat_template_direct_apply_impl(
|
||||
jinja::caps_apply_reasoning_effort(ctx, reasoning_effort);
|
||||
}
|
||||
|
||||
jinja::global_from_json(ctx, common_json_from_raw(inp), inputs.mark_input);
|
||||
jinja::global_from_json(ctx, inp, inputs.mark_input);
|
||||
|
||||
// render
|
||||
jinja::runtime runtime(ctx);
|
||||
@@ -1059,7 +1058,7 @@ static common_chat_params common_chat_params_init_ministral_3(const common_chat_
|
||||
});
|
||||
} else if (msg.at("content").is_array()) {
|
||||
auto blocks = msg.at("content");
|
||||
content.insert(content.end(), blocks.begin(), blocks.end());
|
||||
content.insert(blocks);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1114,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
const auto & schema = function.at("parameters");
|
||||
|
||||
tool_choice |=
|
||||
@@ -1222,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");
|
||||
const std::string name = tool.at("function").at("name").get<std::string>();
|
||||
tool_call_starts.push_back("<function=" + name + ">");
|
||||
});
|
||||
|
||||
@@ -1250,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
auto parameters = function.contains("parameters") ? function.at("parameters") : json::object();
|
||||
|
||||
auto schema_info = common_schema_info();
|
||||
@@ -1441,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
const auto & params = function.at("parameters");
|
||||
|
||||
auto func_name = p.literal(" to=functions.") + p.tool_name(p.literal(name));
|
||||
@@ -1607,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
// TODO @aldehir : need to extend json-schema-to-grammar to produce more than JSON rules
|
||||
// const auto & params = function.at("parameters");
|
||||
|
||||
@@ -1706,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
const auto & schema = function.at("parameters");
|
||||
|
||||
// Tool format: >>>function_name\n{json_args}
|
||||
@@ -1843,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
const auto & schema = function.at("parameters");
|
||||
|
||||
// Match: functions.<name>:<digits>
|
||||
@@ -2037,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
const auto & schema = function.at("parameters");
|
||||
|
||||
auto tool_name = p.json_member("name", "\"" + p.tool_name(p.literal(name)) + "\"");
|
||||
@@ -2233,13 +2232,13 @@ 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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
auto params = function.contains("parameters") ? function.at("parameters") : json::object();
|
||||
const auto & props = params.contains("properties") ? params.at("properties") : json::object();
|
||||
|
||||
std::set<std::string> required;
|
||||
if (params.contains("required")) {
|
||||
params.at("required").get_to(required);
|
||||
required = params.at("required").get<std::set<std::string>>();
|
||||
}
|
||||
|
||||
auto schema_info = common_schema_info();
|
||||
@@ -2468,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
const json schema = function.contains("parameters") ? function.at("parameters") : json::object();
|
||||
|
||||
// arguments come one tag per key, with the JSON type in a type="..."
|
||||
@@ -2789,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");
|
||||
std::string name = function.at("name").get<std::string>();
|
||||
auto params = function.contains("parameters") ? function.at("parameters") : json::object();
|
||||
|
||||
auto schema_info = common_schema_info();
|
||||
@@ -2861,7 +2860,7 @@ static common_chat_params common_chat_params_init_minimax_m3(const common_chat_t
|
||||
|
||||
std::set<std::string> required;
|
||||
if (schema.contains("required")) {
|
||||
schema.at("required").get_to(required);
|
||||
required = schema.at("required").get<std::set<std::string>>();
|
||||
}
|
||||
|
||||
std::vector<common_peg_parser> required_elements;
|
||||
@@ -2973,10 +2972,10 @@ static void system_message_not_supported(json & messages) {
|
||||
auto & second_msg = messages[1];
|
||||
second_msg["content"] = first_msg.at("content").get<std::string>()
|
||||
+ "\n" + second_msg.at("content").get<std::string>();
|
||||
messages.erase(messages.begin());
|
||||
messages.erase(0);
|
||||
} else {
|
||||
LOG_WRN("Removing system prompt due to template not supporting system role\n");
|
||||
messages.erase(messages.begin());
|
||||
messages.erase(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3243,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");
|
||||
const std::string name = function.at("name").get<std::string>();
|
||||
auto params = function.contains("parameters") ? function.at("parameters") : json::object();
|
||||
|
||||
auto args = p.eps();
|
||||
@@ -3389,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");
|
||||
const std::string name = function.at("name").get<std::string>();
|
||||
auto params = function.contains("parameters") ? function.at("parameters") : json::object();
|
||||
|
||||
auto args = p.eps();
|
||||
|
||||
+9
-9
@@ -8,7 +8,7 @@
|
||||
#include "jinja/runtime.h"
|
||||
#include "jinja/caps.h"
|
||||
|
||||
#include "nlohmann/json_fwd.hpp"
|
||||
#include "json.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
@@ -86,7 +86,7 @@ struct common_chat_msg {
|
||||
std::string tool_name;
|
||||
std::string tool_call_id;
|
||||
|
||||
nlohmann::ordered_json to_json_oaicompat(bool concat_typed_text = false) const;
|
||||
common_json to_json_oaicompat(bool concat_typed_text = false) const;
|
||||
|
||||
std::string render_content(const std::string & delimiter = "\n\n") const;
|
||||
|
||||
@@ -210,7 +210,7 @@ struct common_chat_msg_delimiters {
|
||||
// split tokens into message spans. skips maps a start index to a length of a region to jump over without matching
|
||||
common_chat_msg_spans split(const llama_tokens & tokens, const std::map<size_t, size_t> & skips = {}) const;
|
||||
|
||||
nlohmann::ordered_json to_json() const;
|
||||
common_json to_json() const;
|
||||
};
|
||||
|
||||
struct common_chat_tool {
|
||||
@@ -349,16 +349,16 @@ common_chat_tool_choice common_chat_tool_choice_parse_oaicompat(const std::strin
|
||||
bool common_chat_templates_support_enable_thinking(const common_chat_templates * chat_templates);
|
||||
|
||||
// Parses a JSON array of messages in OpenAI's chat completion API format.
|
||||
std::vector<common_chat_msg> common_chat_msgs_parse_oaicompat(const nlohmann::ordered_json & messages);
|
||||
std::vector<common_chat_msg> common_chat_msgs_parse_oaicompat(const common_json & messages);
|
||||
|
||||
std::vector<common_chat_tool> common_chat_tools_parse_oaicompat(const nlohmann::ordered_json & tools);
|
||||
std::vector<common_chat_tool> common_chat_tools_parse_oaicompat(const common_json & tools);
|
||||
|
||||
common_chat_continuation common_chat_continuation_parse(const nlohmann::ordered_json & value);
|
||||
common_chat_continuation common_chat_continuation_parse(const common_json & value);
|
||||
|
||||
// DEPRECATED: only used in tests
|
||||
nlohmann::ordered_json common_chat_msgs_to_json_oaicompat(const std::vector<common_chat_msg> & msgs, bool concat_typed_text = false);
|
||||
common_json common_chat_msgs_to_json_oaicompat(const std::vector<common_chat_msg> & msgs, bool concat_typed_text = false);
|
||||
|
||||
nlohmann::ordered_json common_chat_tools_to_json_oaicompat(const std::vector<common_chat_tool> & tools);
|
||||
common_json common_chat_tools_to_json_oaicompat(const std::vector<common_chat_tool> & tools);
|
||||
|
||||
// get template caps, useful for reporting to server /props endpoint
|
||||
std::map<std::string, bool> common_chat_templates_get_caps(const common_chat_templates * chat_templates);
|
||||
@@ -385,4 +385,4 @@ struct common_chat_prompt_preset {
|
||||
|
||||
common_chat_prompt_preset common_chat_get_asr_prompt(const common_chat_templates * chat_templates);
|
||||
|
||||
common_chat_msg_delimiters common_chat_msg_delimiters_parse(const nlohmann::ordered_json & delimiters);
|
||||
common_chat_msg_delimiters common_chat_msg_delimiters_parse(const common_json & delimiters);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "json-schema-to-grammar.h"
|
||||
// the grammar builder walks the schema with the library API
|
||||
#include "json-shim.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
@@ -12,7 +14,7 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
using json = nlohmann::ordered_json;
|
||||
using json = common_json;
|
||||
|
||||
static std::string build_repetition(const std::string & item_rule, int min_items, int max_items, const std::string & separator_rule = "") {
|
||||
auto has_max = max_items != std::numeric_limits<int>::max();
|
||||
@@ -843,7 +845,7 @@ public:
|
||||
}
|
||||
} else if (n.is_object()) {
|
||||
if (n.contains("$ref")) {
|
||||
std::string ref = n["$ref"];
|
||||
std::string ref = n["$ref"].get<std::string>();
|
||||
if (_refs.find(ref) == _refs.end()) {
|
||||
json target;
|
||||
if (ref.find("https://") == 0) {
|
||||
@@ -914,7 +916,7 @@ public:
|
||||
std::string rule_name = is_reserved_name(name) ? name + "-" : name.empty() ? "root" : name;
|
||||
|
||||
if (schema.contains("$ref")) {
|
||||
return _add_rule(rule_name, _resolve_ref(schema["$ref"]));
|
||||
return _add_rule(rule_name, _resolve_ref(schema["$ref"].get<std::string>()));
|
||||
}
|
||||
if (schema.contains("oneOf") || schema.contains("anyOf")) {
|
||||
std::vector<json> alt_schemas = schema.contains("oneOf") ? schema["oneOf"].get<std::vector<json>>() : schema["anyOf"].get<std::vector<json>>();
|
||||
@@ -968,7 +970,7 @@ public:
|
||||
const std::string& hybrid_name = name;
|
||||
std::function<void(const json &, bool)> add_component = [&](const json & comp_schema, bool is_required) {
|
||||
if (comp_schema.contains("$ref")) {
|
||||
add_component(_refs[comp_schema["$ref"]], is_required);
|
||||
add_component(_refs[comp_schema["$ref"].get<std::string>()], is_required);
|
||||
} else if (comp_schema.contains("properties")) {
|
||||
for (const auto & prop : comp_schema["properties"].items()) {
|
||||
properties.emplace_back(prop.key(), prop.value());
|
||||
@@ -1031,7 +1033,7 @@ public:
|
||||
return _add_rule(rule_name, "\"[\" space " + build_repetition(item_rule_name, min_items, max_items, "\",\" space") + " space \"]\"");
|
||||
}
|
||||
if ((schema_type.is_null() || schema_type == "string") && schema.contains("pattern")) {
|
||||
return _visit_pattern(schema["pattern"], rule_name);
|
||||
return _visit_pattern(schema["pattern"].get<std::string>(), rule_name);
|
||||
}
|
||||
if ((schema_type.is_null() || schema_type == "string") && std::regex_match(schema_format, std::regex("^uuid[1-5]?$"))) {
|
||||
return _add_primitive(rule_name == "root" ? "root" : schema_format, PRIMITIVE_RULES.at("uuid"));
|
||||
@@ -1111,7 +1113,7 @@ common_schema_info::~common_schema_info() = default;
|
||||
common_schema_info::common_schema_info(common_schema_info &&) noexcept = default;
|
||||
common_schema_info & common_schema_info::operator=(common_schema_info &&) noexcept = default;
|
||||
|
||||
void common_schema_info::resolve_refs(nlohmann::ordered_json & schema) {
|
||||
void common_schema_info::resolve_refs(common_json & schema) {
|
||||
impl_->resolve_refs(schema, "");
|
||||
}
|
||||
|
||||
@@ -1119,7 +1121,7 @@ void common_schema_info::resolve_refs(nlohmann::ordered_json & schema) {
|
||||
// Some models emit raw string values rather than JSON-encoded strings for string parameters.
|
||||
// If any branch of the schema (via oneOf, anyOf, $ref, etc.) permits a string, this returns
|
||||
// true, allowing callers to handle the value as a raw string for simplicity.
|
||||
bool common_schema_info::resolves_to_string(const nlohmann::ordered_json & schema) {
|
||||
bool common_schema_info::resolves_to_string(const common_json & schema) {
|
||||
std::unordered_set<std::string> visited_refs;
|
||||
|
||||
std::function<bool(const json &)> check = [&](const json & s) -> bool {
|
||||
@@ -1129,7 +1131,7 @@ bool common_schema_info::resolves_to_string(const nlohmann::ordered_json & schem
|
||||
|
||||
// Handle $ref
|
||||
if (s.contains("$ref")) {
|
||||
const std::string & ref = s["$ref"];
|
||||
const std::string ref = s["$ref"].get<std::string>();
|
||||
if (visited_refs.find(ref) != visited_refs.end()) {
|
||||
// Circular reference, assume not a string to be safe
|
||||
return false;
|
||||
@@ -1212,7 +1214,7 @@ bool common_schema_info::resolves_to_string(const nlohmann::ordered_json & schem
|
||||
|
||||
// Check format - many formats imply string
|
||||
if (s.contains("format")) {
|
||||
const std::string & fmt = s["format"];
|
||||
const std::string fmt = s["format"].get<std::string>();
|
||||
if (fmt == "date" || fmt == "time" || fmt == "date-time" ||
|
||||
fmt == "uri" || fmt == "email" || fmt == "hostname" ||
|
||||
fmt == "ipv4" || fmt == "ipv6" || fmt == "uuid" ||
|
||||
@@ -1236,7 +1238,7 @@ std::string json_schema_to_grammar(const common_json & schema, bool force_gbnf)
|
||||
(void)force_gbnf;
|
||||
#endif // LLAMA_USE_LLGUIDANCE
|
||||
return build_grammar([&](const common_grammar_builder & callbacks) {
|
||||
auto copy = common_json_raw<nlohmann::ordered_json>(schema);
|
||||
auto copy = common_json_raw<common_json>(schema);
|
||||
callbacks.resolve_refs(copy);
|
||||
callbacks.add_schema("", copy);
|
||||
});
|
||||
@@ -1248,10 +1250,10 @@ std::string build_grammar(const std::function<void(const common_grammar_builder
|
||||
/* .add_rule = */ [&](const std::string & name, const std::string & rule) {
|
||||
return converter._add_rule(name, rule);
|
||||
},
|
||||
/* .add_schema = */ [&](const std::string & name, const nlohmann::ordered_json & schema) {
|
||||
/* .add_schema = */ [&](const std::string & name, const common_json & schema) {
|
||||
return converter.visit(schema, name == "root" ? "" : name);
|
||||
},
|
||||
/* .resolve_refs = */ [&](nlohmann::ordered_json & schema) {
|
||||
/* .resolve_refs = */ [&](common_json & schema) {
|
||||
converter.resolve_refs(schema, "");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#include "json.h"
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
@@ -26,14 +25,14 @@ class common_schema_info {
|
||||
common_schema_info(common_schema_info &&) noexcept;
|
||||
common_schema_info & operator=(common_schema_info &&) noexcept;
|
||||
|
||||
void resolve_refs(nlohmann::ordered_json & schema);
|
||||
bool resolves_to_string(const nlohmann::ordered_json & schema);
|
||||
void resolve_refs(common_json & schema);
|
||||
bool resolves_to_string(const common_json & schema);
|
||||
};
|
||||
|
||||
struct common_grammar_builder {
|
||||
std::function<std::string(const std::string &, const std::string &)> add_rule;
|
||||
std::function<std::string(const std::string &, const nlohmann::ordered_json &)> add_schema;
|
||||
std::function<void(nlohmann::ordered_json &)> resolve_refs;
|
||||
std::function<std::string(const std::string &, const common_json &)> add_schema;
|
||||
std::function<void(common_json &)> resolve_refs;
|
||||
};
|
||||
|
||||
struct common_grammar_options {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
// converts between common_json and the backing JSON library
|
||||
//
|
||||
// include this only in a cpp file that touches an internal component of the library,
|
||||
// never in a header. every use here is a place to fix if the library changes.
|
||||
|
||||
#include "json.h"
|
||||
|
||||
template <typename T> T & common_json_raw(common_json & json);
|
||||
template <typename T> const T & common_json_raw(const common_json & json);
|
||||
|
||||
template <typename T> common_json common_json_from_raw(const T & json);
|
||||
|
||||
// view over a value of the backing library, it does not copy
|
||||
template <typename T> common_json & common_json_ref_from_raw(T & json);
|
||||
+54
-1
@@ -1,4 +1,6 @@
|
||||
#include "json.h"
|
||||
// defines the shim
|
||||
#include "json-shim.h"
|
||||
|
||||
#include "ggml.h"
|
||||
|
||||
@@ -80,7 +82,8 @@ common_json_value::common_json_value(const char * val) {
|
||||
common_json_value::common_json_value(const common_json & val) :
|
||||
type(VAL_JSON), val_json(std::make_shared<common_json>(val)) {}
|
||||
|
||||
common_json_value::common_json_value(const std::vector<std::string> & vals) : type(VAL_JSON) {
|
||||
template <typename T>
|
||||
common_json_value::common_json_value(const std::vector<T> & vals) : type(VAL_JSON) {
|
||||
common_json out = common_json::array();
|
||||
|
||||
for (const auto & val : vals) {
|
||||
@@ -90,6 +93,23 @@ common_json_value::common_json_value(const std::vector<std::string> & vals) : ty
|
||||
val_json = std::make_shared<common_json>(std::move(out));
|
||||
}
|
||||
|
||||
// a vector value is usable only for the types below
|
||||
// note: std::vector<bool> is not here, its proxy reference does not convert
|
||||
#define COMMON_JSON_VEC(...) template common_json_value::common_json_value(const std::vector<__VA_ARGS__> &);
|
||||
|
||||
COMMON_JSON_VEC(int)
|
||||
COMMON_JSON_VEC(unsigned int)
|
||||
COMMON_JSON_VEC(long)
|
||||
COMMON_JSON_VEC(unsigned long)
|
||||
COMMON_JSON_VEC(long long)
|
||||
COMMON_JSON_VEC(unsigned long long)
|
||||
COMMON_JSON_VEC(float)
|
||||
COMMON_JSON_VEC(double)
|
||||
COMMON_JSON_VEC(std::string)
|
||||
COMMON_JSON_VEC(common_json)
|
||||
|
||||
#undef COMMON_JSON_VEC
|
||||
|
||||
common_json_value::common_json_value(std::initializer_list<common_json_item> items) :
|
||||
type(VAL_JSON), val_json(std::make_shared<common_json>(items)) {}
|
||||
|
||||
@@ -143,6 +163,14 @@ common_json common_json::parse(const std::string & text) {
|
||||
}
|
||||
}
|
||||
|
||||
common_json common_json::parse_no_throw(const std::string & text) {
|
||||
return common_json_from_raw(ordered_json::parse(text, nullptr, false));
|
||||
}
|
||||
|
||||
bool common_json::is_discarded() const {
|
||||
return as_json(this).is_discarded();
|
||||
}
|
||||
|
||||
common_json common_json::array() {
|
||||
return common_json_from_raw(ordered_json::array());
|
||||
}
|
||||
@@ -161,6 +189,10 @@ common_json common_json::object() {
|
||||
return common_json();
|
||||
}
|
||||
|
||||
common_json common_json::object(std::initializer_list<common_json_item> items) {
|
||||
return common_json(items);
|
||||
}
|
||||
|
||||
common_json common_json::make(const common_json_value & val) {
|
||||
return common_json(val);
|
||||
}
|
||||
@@ -204,6 +236,10 @@ const common_json & common_json::front() const { return as_common(as_json(this).
|
||||
common_json & common_json::back() { return as_common(as_json(this).back()); }
|
||||
const common_json & common_json::back() const { return as_common(as_json(this).back()); }
|
||||
|
||||
void common_json::clear() {
|
||||
as_json(this).clear();
|
||||
}
|
||||
|
||||
void common_json::erase(const std::string & key) {
|
||||
as_json(this).erase(key);
|
||||
}
|
||||
@@ -224,6 +260,22 @@ void common_json::push_back(const common_json_value & val) {
|
||||
as_json(this).push_back(to_json(val));
|
||||
}
|
||||
|
||||
void common_json::push_back(std::initializer_list<common_json_item> items) {
|
||||
common_json val(items);
|
||||
|
||||
as_json(this).push_back(as_json(&val));
|
||||
}
|
||||
|
||||
size_t common_json::count(const std::string & key) const {
|
||||
return as_json(this).count(key);
|
||||
}
|
||||
|
||||
void common_json::insert(const common_json & vals) {
|
||||
ordered_json & self = as_json(this);
|
||||
|
||||
self.insert(self.end(), as_json(&vals).begin(), as_json(&vals).end());
|
||||
}
|
||||
|
||||
std::string common_json::dump(int indent) const {
|
||||
return as_json(this).dump(indent);
|
||||
}
|
||||
@@ -283,5 +335,6 @@ COMMON_JSON_GET(double)
|
||||
COMMON_JSON_GET(std::string)
|
||||
COMMON_JSON_GET(std::vector<std::string>)
|
||||
COMMON_JSON_GET(std::set<std::string>)
|
||||
COMMON_JSON_GET(std::vector<int>)
|
||||
|
||||
#undef COMMON_JSON_GET
|
||||
|
||||
+31
-13
@@ -8,6 +8,7 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
@@ -53,7 +54,8 @@ struct common_json_value {
|
||||
common_json_value(std::string val) : type(VAL_STRING), val_string(std::move(val)) {}
|
||||
common_json_value(const char * val);
|
||||
common_json_value(const common_json & val);
|
||||
common_json_value(const std::vector<std::string> & vals);
|
||||
// only for the types instantiated in json.cpp, the rest fails at link time
|
||||
template <typename T> common_json_value(const std::vector<T> & vals);
|
||||
|
||||
// nested object, e.g. {"fn", {{"name", "x"}}}
|
||||
common_json_value(std::initializer_list<common_json_item> items);
|
||||
@@ -95,6 +97,11 @@ class common_json {
|
||||
// direct, a value would need two conversions in a row
|
||||
common_json(std::nullptr_t);
|
||||
|
||||
// one step, so that "abc" or a vector can go straight into a common_json
|
||||
template <typename T, typename std::enable_if<!std::is_same<typename std::decay<T>::type, common_json>::value &&
|
||||
!std::is_same<typename std::decay<T>::type, common_json_value>::value, int>::type = 0>
|
||||
common_json(T && val) : common_json(common_json_value(std::forward<T>(val))) {}
|
||||
|
||||
common_json & operator=(const common_json & other);
|
||||
common_json & operator=(common_json && other) noexcept;
|
||||
|
||||
@@ -103,9 +110,15 @@ class common_json {
|
||||
// throws common_json_error if the text is not valid JSON
|
||||
static common_json parse(const std::string & text);
|
||||
|
||||
// gives a discarded value instead of throwing, check it with is_discarded()
|
||||
static common_json parse_no_throw(const std::string & text);
|
||||
|
||||
bool is_discarded() const;
|
||||
|
||||
static common_json array();
|
||||
static common_json array(std::initializer_list<common_json_value> vals);
|
||||
static common_json object();
|
||||
static common_json object(std::initializer_list<common_json_item> items);
|
||||
|
||||
// holds a single value, e.g. make("abc").dump() gives "\"abc\""
|
||||
static common_json make(const common_json_value & val);
|
||||
@@ -143,6 +156,8 @@ class common_json {
|
||||
common_json & back();
|
||||
const common_json & back() const;
|
||||
|
||||
void clear();
|
||||
|
||||
void erase(const std::string & key);
|
||||
void erase(size_t idx);
|
||||
|
||||
@@ -162,6 +177,15 @@ class common_json {
|
||||
void set(const common_json_item & item);
|
||||
void push_back(const common_json_value & val);
|
||||
|
||||
// appends one object, e.g. push_back({{"a", 1}})
|
||||
void push_back(std::initializer_list<common_json_item> items);
|
||||
|
||||
// 1 if the key is there, 0 if not
|
||||
size_t count(const std::string & key) const;
|
||||
|
||||
// appends every value of another array
|
||||
void insert(const common_json & vals);
|
||||
|
||||
// a common_json goes through the copy assignment above, everything else becomes a value
|
||||
template <typename T, typename std::enable_if<!std::is_same<typename std::decay<T>::type, common_json>::value, int>::type = 0>
|
||||
common_json & operator=(T && val) {
|
||||
@@ -177,6 +201,12 @@ class common_json {
|
||||
// walks an array by index, or an object in insertion order
|
||||
class iterator {
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = common_json;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = common_json *;
|
||||
using reference = common_json &;
|
||||
|
||||
iterator(common_json * node, size_t idx) : node(node), idx(idx) {}
|
||||
|
||||
common_json & operator*() const;
|
||||
@@ -247,15 +277,3 @@ class common_json {
|
||||
};
|
||||
|
||||
using common_json_entry = common_json::items_view::entry;
|
||||
|
||||
// bridge for code that still uses internal component from nlohmann::json
|
||||
// usage: common_json_raw<nlohmann::ordered_json>(j)
|
||||
// TODO: maybe completely remove this in the future
|
||||
|
||||
template <typename T> T & common_json_raw(common_json & json);
|
||||
template <typename T> const T & common_json_raw(const common_json & json);
|
||||
|
||||
template <typename T> common_json common_json_from_raw(const T & json);
|
||||
|
||||
// view over a value of the backing library, it does not copy
|
||||
template <typename T> common_json & common_json_ref_from_raw(T & json);
|
||||
|
||||
+16
-13
@@ -1,4 +1,6 @@
|
||||
#include "peg-parser.h"
|
||||
// the interface takes common_json, the parser internals stay on the library
|
||||
#include "json-shim.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "json-schema-to-grammar.h"
|
||||
@@ -1120,8 +1122,8 @@ common_peg_parser common_peg_parser_builder::chars(const std::string & classes,
|
||||
return wrap(arena_.add_parser(common_peg_chars_parser{classes, ranges, negated, min, max}));
|
||||
}
|
||||
|
||||
common_peg_parser common_peg_parser_builder::schema(const common_peg_parser & p, const std::string & name, const nlohmann::ordered_json & schema, bool raw) {
|
||||
return wrap(arena_.add_parser(common_peg_schema_parser{p.id(), name, std::make_shared<nlohmann::ordered_json>(schema), raw}));
|
||||
common_peg_parser common_peg_parser_builder::schema(const common_peg_parser & p, const std::string & name, const common_json & schema, bool raw) {
|
||||
return wrap(arena_.add_parser(common_peg_schema_parser{p.id(), name, std::make_shared<common_json>(schema), raw}));
|
||||
}
|
||||
|
||||
common_peg_parser common_peg_parser_builder::rule(const std::string & name, const common_peg_parser & p, bool trigger) {
|
||||
@@ -1805,8 +1807,8 @@ void common_peg_arena::build_grammar(const common_grammar_builder & builder, boo
|
||||
}
|
||||
}
|
||||
|
||||
static nlohmann::json serialize_parser_variant(const common_peg_parser_variant & variant) {
|
||||
using json = nlohmann::json;
|
||||
static nlohmann::ordered_json serialize_parser_variant(const common_peg_parser_variant & variant) {
|
||||
using json = nlohmann::ordered_json;
|
||||
|
||||
return std::visit([](const auto & p) -> json {
|
||||
using T = std::decay_t<decltype(p)>;
|
||||
@@ -1860,7 +1862,7 @@ static nlohmann::json serialize_parser_variant(const common_peg_parser_variant &
|
||||
{"type", "schema"},
|
||||
{"child", p.child},
|
||||
{"name", p.name},
|
||||
{"schema", p.schema ? *p.schema : nullptr},
|
||||
{"schema", p.schema ? common_json_raw<nlohmann::ordered_json>(*p.schema) : nlohmann::ordered_json(nullptr)},
|
||||
{"raw", p.raw}
|
||||
};
|
||||
} else if constexpr (std::is_same_v<T, common_peg_rule_parser>) {
|
||||
@@ -1888,19 +1890,19 @@ static nlohmann::json serialize_parser_variant(const common_peg_parser_variant &
|
||||
}, variant);
|
||||
}
|
||||
|
||||
nlohmann::json common_peg_arena::to_json() const {
|
||||
auto parsers = nlohmann::json::array();
|
||||
common_json common_peg_arena::to_json() const {
|
||||
auto parsers = nlohmann::ordered_json::array();
|
||||
for (const auto & parser : parsers_) {
|
||||
parsers.push_back(serialize_parser_variant(parser));
|
||||
}
|
||||
return nlohmann::json{
|
||||
return common_json_from_raw(nlohmann::ordered_json{
|
||||
{"parsers", parsers},
|
||||
{"rules", rules_},
|
||||
{"root", root_}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
static common_peg_parser_variant deserialize_parser_variant(const nlohmann::json & j) {
|
||||
static common_peg_parser_variant deserialize_parser_variant(const nlohmann::ordered_json & j) {
|
||||
if (!j.contains("type") || !j["type"].is_string()) {
|
||||
throw std::runtime_error("Parser variant JSON missing or invalid 'type' field");
|
||||
}
|
||||
@@ -2007,7 +2009,7 @@ static common_peg_parser_variant deserialize_parser_variant(const nlohmann::json
|
||||
parser.child = j["child"].get<common_peg_parser_id>();
|
||||
parser.name = j["name"];
|
||||
if (!j["schema"].is_null()) {
|
||||
parser.schema = std::make_shared<nlohmann::ordered_json>(j["schema"]);
|
||||
parser.schema = std::make_shared<common_json>(common_json_from_raw(j["schema"]));
|
||||
}
|
||||
parser.raw = j["raw"].get<bool>();
|
||||
return parser;
|
||||
@@ -2069,7 +2071,8 @@ static common_peg_parser_variant deserialize_parser_variant(const nlohmann::json
|
||||
throw std::runtime_error("Unknown parser type: " + type);
|
||||
}
|
||||
|
||||
common_peg_arena common_peg_arena::from_json(const nlohmann::json & j) {
|
||||
common_peg_arena common_peg_arena::from_json(const common_json & j_in) {
|
||||
const nlohmann::ordered_json & j = common_json_raw<nlohmann::ordered_json>(j_in);
|
||||
if (!j.contains("parsers") || !j["parsers"].is_array()) {
|
||||
throw std::runtime_error("JSON missing or invalid 'parsers' array");
|
||||
}
|
||||
@@ -2109,7 +2112,7 @@ std::string common_peg_arena::save() const {
|
||||
}
|
||||
|
||||
void common_peg_arena::load(const std::string & data) {
|
||||
*this = from_json(nlohmann::json::parse(data));
|
||||
*this = from_json(common_json::parse(data));
|
||||
}
|
||||
|
||||
common_peg_arena build_peg_parser(const std::function<common_peg_parser(common_peg_parser_builder & builder)> & fn) {
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include "json.h"
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
@@ -245,7 +245,7 @@ struct common_peg_until_parser {
|
||||
struct common_peg_schema_parser {
|
||||
common_peg_parser_id child;
|
||||
std::string name;
|
||||
std::shared_ptr<nlohmann::ordered_json> schema;
|
||||
std::shared_ptr<common_json> schema;
|
||||
|
||||
// Indicates if the GBNF should accept a raw string that matches the schema.
|
||||
bool raw;
|
||||
@@ -332,8 +332,8 @@ class common_peg_arena {
|
||||
|
||||
std::string dump(common_peg_parser_id id) const;
|
||||
|
||||
nlohmann::json to_json() const;
|
||||
static common_peg_arena from_json(const nlohmann::json & j);
|
||||
common_json to_json() const;
|
||||
static common_peg_arena from_json(const common_json & j);
|
||||
|
||||
std::string save() const;
|
||||
void load(const std::string & data);
|
||||
@@ -490,7 +490,7 @@ class common_peg_parser_builder {
|
||||
|
||||
// Wraps a parser with JSON schema metadata for grammar generation.
|
||||
// Used internally to convert JSON schemas to GBNF grammar rules.
|
||||
common_peg_parser schema(const common_peg_parser & p, const std::string & name, const nlohmann::ordered_json & schema, bool raw = false);
|
||||
common_peg_parser schema(const common_peg_parser & p, const std::string & name, const common_json & schema, bool raw = false);
|
||||
|
||||
// Creates a named rule, stores it in the grammar, and returns a ref.
|
||||
// If trigger=true, marks this rule as an entry point for lazy grammar generation.
|
||||
|
||||
Reference in New Issue
Block a user