Skip to content

Commit fe6db32

Browse files
authored
common : simplify autoparser tagged parser rules (ggml-org#21216)
* common : simplify autoparser tagged parser rules * cont : remove upper limit on optional args * cont : revert changes to parsing at the end * cont : undo arbitrary ordering of optional args * cont : fix uninitialized required parameters * revert to simplify merge * re-apply patches * restore flexible optional arg ordering tests
1 parent dce7cb8 commit fe6db32

1 file changed

Lines changed: 14 additions & 36 deletions

File tree

common/chat-auto-parser-generator.cpp

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -332,58 +332,36 @@ common_peg_parser analyze_tools::build_tool_parser_tag_tagged(parser_build_conte
332332
const auto & inputs = ctx.inputs;
333333
bool force_tools = inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_REQUIRED;
334334

335+
auto until_suffix = p.rule("until-suffix", p.until(arguments.value_suffix));
336+
335337
common_peg_parser tool_choice = p.choice();
336338

337339
foreach_function(inputs.tools, [&](const json & tool) {
338340
const auto & func = tool.at("function");
339341
std::string name = func.at("name");
340-
const auto & params = func.contains("parameters") ? func.at("parameters") : json::object();
342+
auto params = func.contains("parameters") ? func.at("parameters") : json::object();
341343
const auto & properties = params.contains("properties") ? params.at("properties") : json::object();
344+
342345
std::set<std::string> required;
346+
if (params.contains("required")) {
347+
params.at("required").get_to(required);
348+
}
349+
350+
auto schema_info = common_schema_info();
351+
schema_info.resolve_refs(params);
343352

344353
// Build parser for each argument, separating required and optional
345354
std::vector<common_peg_parser> required_parsers;
346355
std::vector<common_peg_parser> optional_parsers;
347356
for (const auto & [param_name, param_schema] : properties.items()) {
348-
bool is_required = required.find(param_name) != required.end();
349-
std::string type = "object";
350-
if (param_schema.contains("type")) {
351-
const auto & type_obj = param_schema.at("type");
352-
if (type_obj.is_string()) {
353-
type_obj.get_to(type);
354-
} else if (type_obj.is_array()) {
355-
// Handle nullable types like ["string", "null"]
356-
for (const auto & t : type_obj) {
357-
if (t.is_string() && t.get<std::string>() != "null") {
358-
type = t.get<std::string>();
359-
break;
360-
}
361-
}
362-
} else if (type_obj.is_object()) {
363-
if (type_obj.contains("type") && type_obj.at("type").is_string()) {
364-
type_obj.at("type").get_to(type);
365-
}
366-
}
367-
}
368-
// Infer string type from enum values when type is unspecified
369-
if (type == "object" && param_schema.contains("enum")) {
370-
const auto & enum_vals = param_schema.at("enum");
371-
if (enum_vals.is_array()) {
372-
for (const auto & v : enum_vals) {
373-
if (v.is_string()) {
374-
type = "string";
375-
break;
376-
}
377-
}
378-
}
379-
}
357+
bool is_required = required.find(param_name) != required.end();
380358

381359
auto arg =
382360
p.tool_arg(p.tool_arg_open(arguments.name_prefix + p.tool_arg_name(p.literal(param_name)) +
383361
arguments.name_suffix) +
384362
arguments.value_prefix +
385-
(type == "string" ?
386-
p.tool_arg_string_value(p.schema(p.until(arguments.value_suffix),
363+
(schema_info.resolves_to_string(param_schema) ?
364+
p.tool_arg_string_value(p.schema(until_suffix,
387365
"tool-" + name + "-arg-" + param_name + "-schema",
388366
param_schema, true)) :
389367
p.tool_arg_json_value(p.schema(
@@ -414,7 +392,7 @@ common_peg_parser analyze_tools::build_tool_parser_tag_tagged(parser_build_conte
414392
for (const auto & opt : optional_parsers) {
415393
any_opt |= opt;
416394
}
417-
args_seq = args_seq + p.repeat(p.space() + any_opt, 0, (int) optional_parsers.size());
395+
args_seq = args_seq + p.repeat(p.space() + any_opt, 0, -1);
418396
}
419397

420398
if (!arguments.start.empty()) {

0 commit comments

Comments
 (0)