mirror of
				https://github.com/ggml-org/llama.cpp.git
				synced 2025-10-30 08:42:00 +00:00 
			
		
		
		
	json: better support for "type" unions (e.g. nullable arrays w/ typed items) (#7863)
				
					
				
			* json: better suport for "type" arrays (e.g. `{"type": ["array", "null"], "items": {"type": "string"}}`)
* json: add test for type: [array, null] fix
* update tests
			
			
This commit is contained in:
		| @@ -893,7 +893,9 @@ public: | ||||
|         } else if (schema_type.is_array()) { | ||||
|             std::vector<json> schema_types; | ||||
|             for (const auto & t : schema_type) { | ||||
|                 schema_types.push_back({{"type", t}}); | ||||
|                 json schema_copy(schema); | ||||
|                 schema_copy["type"] = t; | ||||
|                 schema_types.push_back(schema_copy); | ||||
|             } | ||||
|             return _add_rule(rule_name, _generate_union_rule(name, schema_types)); | ||||
|         } else if (schema.contains("const")) { | ||||
|   | ||||
| @@ -565,7 +565,7 @@ class SchemaConverter: | ||||
|             return self._add_rule(rule_name, self._generate_union_rule(name, schema.get('oneOf') or schema['anyOf'])) | ||||
|  | ||||
|         elif isinstance(schema_type, list): | ||||
|             return self._add_rule(rule_name, self._generate_union_rule(name, [{'type': t} for t in schema_type])) | ||||
|             return self._add_rule(rule_name, self._generate_union_rule(name, [{**schema, 'type': t} for t in schema_type])) | ||||
|  | ||||
|         elif 'const' in schema: | ||||
|             return self._add_rule(rule_name, self._generate_constant_rule(schema['const']) + ' space') | ||||
|   | ||||
| @@ -616,7 +616,7 @@ export class SchemaConverter { | ||||
|     } else if (schema.oneOf || schema.anyOf) { | ||||
|       return this._addRule(ruleName, this._generateUnionRule(name, schema.oneOf || schema.anyOf)); | ||||
|     } else if (Array.isArray(schemaType)) { | ||||
|       return this._addRule(ruleName, this._generateUnionRule(name, schemaType.map(t => ({ type: t })))); | ||||
|       return this._addRule(ruleName, this._generateUnionRule(name, schemaType.map(t => ({...schema, type: t})))); | ||||
|     } else if ('const' in schema) { | ||||
|       return this._addRule(ruleName, this._generateConstantRule(schema.const) + ' space'); | ||||
|     } else if ('enum' in schema) { | ||||
|   | ||||
| @@ -993,6 +993,31 @@ static void test_json_schema() { | ||||
|         } | ||||
|     ); | ||||
|  | ||||
|     test_schema( | ||||
|         "", | ||||
|         // Schema | ||||
|         R"""( | ||||
|             { | ||||
|                 "type": ["array", "null"], | ||||
|                 "items": { "type": "string" } | ||||
|             } | ||||
|         )""", | ||||
|         // Passing strings | ||||
|         { | ||||
|             "null", | ||||
|             "[]", | ||||
|             "[\"123\"]", | ||||
|             "[\"foo\", \"bar\"]", | ||||
|         }, | ||||
|         // Failing strings | ||||
|         { | ||||
|             "", | ||||
|             "[123]", | ||||
|             "\"foo\"", | ||||
|             "[\"foo\", 42]", | ||||
|         } | ||||
|     ); | ||||
|  | ||||
|     test_schema( | ||||
|         "min+max items", | ||||
|         // Schema | ||||
|   | ||||
| @@ -502,6 +502,38 @@ static void test_all(const std::string & lang, std::function<void(const TestCase | ||||
|         )""" | ||||
|     }); | ||||
|  | ||||
|     test({ | ||||
|         SUCCESS, | ||||
|         "string array", | ||||
|         R"""({ | ||||
|             "type": "array", | ||||
|             "prefixItems": { "type": "string" } | ||||
|         })""", | ||||
|         R"""( | ||||
|             char ::= [^"\\\x7F\x00-\x1F] | [\\] (["\\bfnrt] | "u" [0-9a-fA-F]{4}) | ||||
|             root ::= "[" space (string ("," space string)*)? "]" space | ||||
|             space ::= | " " | "\n" [ \t]{0,20} | ||||
|             string ::= "\"" char* "\"" space | ||||
|         )""" | ||||
|     }); | ||||
|  | ||||
|     test({ | ||||
|         SUCCESS, | ||||
|         "nullable string array", | ||||
|         R"""({ | ||||
|             "type": ["array", "null"], | ||||
|             "prefixItems": { "type": "string" } | ||||
|         })""", | ||||
|         R"""( | ||||
|             alternative-0 ::= "[" space (string ("," space string)*)? "]" space | ||||
|             char ::= [^"\\\x7F\x00-\x1F] | [\\] (["\\bfnrt] | "u" [0-9a-fA-F]{4}) | ||||
|             null ::= "null" space | ||||
|             root ::= alternative-0 | null | ||||
|             space ::= | " " | "\n" [ \t]{0,20} | ||||
|             string ::= "\"" char* "\"" space | ||||
|         )""" | ||||
|     }); | ||||
|  | ||||
|     test({ | ||||
|         SUCCESS, | ||||
|         "tuple1", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Olivier Chafik
					Olivier Chafik