File size: 2,021 Bytes
79d2901
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
diff --git a/common/json-schema-to-grammar.cpp b/common/json-schema-to-grammar.cpp
index b18607c..16ad010 100644
--- a/common/json-schema-to-grammar.cpp
+++ b/common/json-schema-to-grammar.cpp
@@ -677,6 +677,13 @@ private:
             optional_props.push_back("*");
         }
 
+        if (required_props.empty() && optional_props.empty()) {
+            // No properties and no additionalProperties: avoid falling through to two
+            // adjacent `space` tokens with nothing between them, which is invalid GBNF
+            // (e.g. a no-arg tool schema like {"type":"object","properties":{}}).
+            return "\"{\" space \"}\"";
+        }
+
         std::string rule = "\"{\" space ";
         for (size_t i = 0; i < required_props.size(); i++) {
             if (i > 0) {
@@ -972,6 +979,14 @@ public:
             std::string char_rule = _add_primitive("char", PRIMITIVE_RULES.at("char"));
             int min_len = schema.contains("minLength") ? schema["minLength"].get<int>() : 0;
             int max_len = schema.contains("maxLength") ? schema["maxLength"].get<int>() : std::numeric_limits<int>::max();
+            // Clamp to the grammar engine's own repetition cap (MAX_REPETITION_THRESHOLD in
+            // src/llama-grammar.cpp, currently 2000) so a large-but-valid maxLength doesn't
+            // blow up grammar init. A bound this large isn't meaningfully enforceable via a
+            // literal GBNF repetition anyway, so treat "too large to represent" as unbounded.
+            constexpr int GRAMMAR_MAX_REPETITION_THRESHOLD = 2000;
+            if (max_len > GRAMMAR_MAX_REPETITION_THRESHOLD) {
+                max_len = std::numeric_limits<int>::max();
+            }
             return _add_rule(rule_name, "\"\\\"\" " + build_repetition(char_rule, min_len, max_len) + " \"\\\"\"");
         }
         if (schema_type == "integer" && (schema.contains("minimum") || schema.contains("exclusiveMinimum") || schema.contains("maximum") || schema.contains("exclusiveMaximum"))) {