char-fork/llama.cpp

git clone https://git.t4t.associates/char-fork/llama.cpp

Aldehir Rojascommon : implement common_schema internal representation for JSON schemas (#28736)acecd5603

char/aliceai-t5-moe
6.0 KiB198 linesraw
1#pragma once
2
3#include "json.h"
4
5#include <cstdint>
6#include <initializer_list>
7#include <map>
8#include <memory>
9#include <string>
10#include <vector>
11
12// JSON schema, covering the subset that json_schema_to_grammar() can convert.
13
14struct common_chat_schema {
15    enum node_kind {
16        KIND_ANY,
17        KIND_REF,
18        KIND_ANY_OF,
19        KIND_ALL_OF,
20        KIND_CONST,
21        KIND_ENUM,
22        KIND_NULL,
23        KIND_BOOLEAN,
24        KIND_NUMBER,
25        KIND_INTEGER,
26        KIND_STRING,
27        KIND_ARRAY,
28        KIND_TUPLE,
29        KIND_OBJECT,
30    };
31
32    enum value_type {
33        TYPE_NULL,
34        TYPE_BOOLEAN,
35        TYPE_NUMBER,
36        TYPE_INTEGER,
37        TYPE_STRING,
38        TYPE_ARRAY,
39        TYPE_OBJECT,
40    };
41
42    enum string_format {
43        FORMAT_NONE,
44        FORMAT_UUID,  // uuid, uuid1 .. uuid5
45        FORMAT_DATE,
46        FORMAT_TIME,
47        FORMAT_DATE_TIME,
48    };
49
50    class type_set {
51        uint32_t mask_ = 0;
52
53      public:
54        type_set() = default;
55        type_set(std::initializer_list<value_type> types) {
56            for (auto type : types) {
57                add(type);
58            }
59        }
60
61        static type_set all() {
62            return { TYPE_NULL, TYPE_BOOLEAN, TYPE_NUMBER, TYPE_INTEGER, TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT };
63        }
64
65        void add(value_type type) { mask_ |= 1u << type; }
66
67        bool has(value_type type) const { return (mask_ & (1u << type)) != 0; }
68        bool is_only(value_type type) const { return mask_ == (1u << type); }
69        bool empty() const { return mask_ == 0; }
70
71        type_set & operator|=(const type_set & other) { mask_ |= other.mask_; return *this; }
72        type_set & operator&=(const type_set & other) { mask_ &= other.mask_; return *this; }
73
74        bool operator==(const type_set & other) const { return mask_ == other.mask_; }
75        bool operator!=(const type_set & other) const { return mask_ != other.mask_; }
76    };
77
78    virtual ~common_chat_schema() = default;
79    virtual node_kind kind() const = 0;
80
81    type_set value_types() const;
82
83    // Whether a value matching the schema may be a string, through any branch of it.
84    bool may_be_string() const;
85
86    static const char * kind_name(node_kind kind);
87    static const char * type_name(value_type type);
88};
89
90using common_chat_schema_ptr = std::unique_ptr<common_chat_schema>;
91
92struct common_chat_schema_any : common_chat_schema {
93    node_kind kind() const override { return KIND_ANY; }
94};
95
96// {"$ref": "#/..."}, only references into the same document are supported
97struct common_chat_schema_ref : common_chat_schema {
98    std::string                ref;
99    const common_chat_schema * target = nullptr;  // owned by common_chat_schema_document::refs
100
101    explicit common_chat_schema_ref(std::string ref) : ref(std::move(ref)) {}
102
103    node_kind kind() const override { return KIND_REF; }
104};
105
106// oneOf / anyOf, or a "type" array expanded to one alternative per type
107struct common_chat_schema_any_of : common_chat_schema {
108    std::vector<common_chat_schema_ptr> children;
109
110    node_kind kind() const override { return KIND_ANY_OF; }
111};
112
113struct common_chat_schema_all_of : common_chat_schema {
114    std::vector<common_chat_schema_ptr> children;
115
116    node_kind kind() const override { return KIND_ALL_OF; }
117};
118
119struct common_chat_schema_const : common_chat_schema {
120    common_json value;
121
122    explicit common_chat_schema_const(common_json value) : value(std::move(value)) {}
123
124    node_kind kind() const override { return KIND_CONST; }
125};
126
127struct common_chat_schema_enum : common_chat_schema {
128    std::vector<common_json> values;
129
130    node_kind kind() const override { return KIND_ENUM; }
131};
132
133struct common_chat_schema_null : common_chat_schema {
134    node_kind kind() const override { return KIND_NULL; }
135};
136
137struct common_chat_schema_boolean : common_chat_schema {
138    node_kind kind() const override { return KIND_BOOLEAN; }
139};
140
141struct common_chat_schema_number : common_chat_schema {
142    node_kind kind() const override { return KIND_NUMBER; }
143};
144
145// bounds are inclusive, exclusiveMinimum / exclusiveMaximum are folded in
146struct common_chat_schema_integer : common_chat_schema {
147    int64_t minimum = INT64_MIN;  // INT64_MIN for unbounded
148    int64_t maximum = INT64_MAX;  // INT64_MAX for unbounded
149
150    node_kind kind() const override { return KIND_INTEGER; }
151};
152
153struct common_chat_schema_string : common_chat_schema {
154    std::string   pattern;  // empty when absent
155    string_format format     = FORMAT_NONE;
156    int           min_length = 0;
157    int           max_length = -1;  // -1 for unbounded
158
159    node_kind kind() const override { return KIND_STRING; }
160};
161
162struct common_chat_schema_array : common_chat_schema {
163    common_chat_schema_ptr items;  // a common_chat_schema_any when "items" is absent
164    int                    min_items = 0;
165    int                    max_items = -1;  // -1 for unbounded
166
167    node_kind kind() const override { return KIND_ARRAY; }
168};
169
170struct common_chat_schema_tuple : common_chat_schema {
171    std::vector<common_chat_schema_ptr> items;
172
173    node_kind kind() const override { return KIND_TUPLE; }
174};
175
176struct common_chat_schema_property {
177    std::string            name;
178    common_chat_schema_ptr schema;
179    bool                   required = false;
180};
181
182struct common_chat_schema_object : common_chat_schema {
183    std::vector<common_chat_schema_property> properties;             // in schema order
184    common_chat_schema_ptr                   additional_properties;  // null when not allowed
185
186    node_kind kind() const override { return KIND_OBJECT; }
187};
188
189struct common_chat_schema_document {
190    common_chat_schema_ptr                        root;
191    std::map<std::string, common_chat_schema_ptr> refs;
192};
193
194// A document shared by the PEG parsers built from its nodes, which it keeps alive
195using common_chat_schema_document_ptr = std::shared_ptr<const common_chat_schema_document>;
196
197// Throws std::runtime_error when the schema falls outside the supported subset.
198common_chat_schema_document common_chat_schema_from_json(const common_json & schema);