node-llama-cpp 2.8.12 → 2.8.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/llama/addon.cpp +2 -2
- package/llama/binariesGithubRelease.json +1 -1
- package/llama/gitRelease.bundle +0 -0
- package/llama/grammars/README.md +249 -11
- package/llamaBins/linux-arm64/libggml.so +0 -0
- package/llamaBins/linux-arm64/libllama.so +0 -0
- package/llamaBins/linux-arm64/llama-addon.node +0 -0
- package/llamaBins/linux-armv7l/libggml.so +0 -0
- package/llamaBins/linux-armv7l/libllama.so +0 -0
- package/llamaBins/linux-armv7l/llama-addon.node +0 -0
- package/llamaBins/linux-x64/libggml.so +0 -0
- package/llamaBins/linux-x64/libllama.so +0 -0
- package/llamaBins/linux-x64/llama-addon.node +0 -0
- package/llamaBins/mac-arm64/ggml-common.h +1829 -0
- package/llamaBins/mac-arm64/ggml-metal.metal +6168 -0
- package/llamaBins/mac-arm64/libggml.dylib +0 -0
- package/llamaBins/mac-arm64/libllama.dylib +0 -0
- package/llamaBins/mac-arm64/llama-addon.node +0 -0
- package/llamaBins/mac-x64/ggml-common.h +1829 -0
- package/llamaBins/mac-x64/ggml-metal.metal +6168 -0
- package/llamaBins/mac-x64/libggml.dylib +0 -0
- package/llamaBins/mac-x64/libllama.dylib +0 -0
- package/llamaBins/mac-x64/llama-addon.node +0 -0
- package/llamaBins/win-x64/Release/ggml.dll +0 -0
- package/llamaBins/win-x64/Release/llama.dll +0 -0
- package/llamaBins/win-x64/llama-addon.exp +0 -0
- package/llamaBins/win-x64/llama-addon.lib +0 -0
- package/llamaBins/win-x64/llama-addon.node +0 -0
- package/package.json +1 -1
- package/llamaBins/mac-arm64/default.metallib +0 -0
- package/llamaBins/mac-x64/default.metallib +0 -0
package/README.md
CHANGED
package/llama/addon.cpp
CHANGED
|
@@ -391,7 +391,7 @@ class LLAMAContextEvalWorker : Napi::AsyncWorker, Napi::Promise::Deferred {
|
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
if (use_grammar && (grammar_evaluation_state)->grammar != nullptr) {
|
|
394
|
-
|
|
394
|
+
llama_grammar_sample((grammar_evaluation_state)->grammar, ctx->ctx, &candidates_p);
|
|
395
395
|
}
|
|
396
396
|
|
|
397
397
|
if (temperature <= 0) {
|
|
@@ -414,7 +414,7 @@ class LLAMAContextEvalWorker : Napi::AsyncWorker, Napi::Promise::Deferred {
|
|
|
414
414
|
}
|
|
415
415
|
|
|
416
416
|
if (new_token_id != eos_token && use_grammar && (grammar_evaluation_state)->grammar != nullptr) {
|
|
417
|
-
llama_grammar_accept_token(
|
|
417
|
+
llama_grammar_accept_token((grammar_evaluation_state)->grammar, ctx->ctx, new_token_id);
|
|
418
418
|
}
|
|
419
419
|
|
|
420
420
|
result = new_token_id;
|
package/llama/gitRelease.bundle
CHANGED
|
Binary file
|
package/llama/grammars/README.md
CHANGED
|
@@ -4,7 +4,7 @@ GBNF (GGML BNF) is a format for defining [formal grammars](https://en.wikipedia.
|
|
|
4
4
|
|
|
5
5
|
## Background
|
|
6
6
|
|
|
7
|
-
[
|
|
7
|
+
[Backus-Naur Form (BNF)](https://en.wikipedia.org/wiki/Backus%E2%80%93Naur_form) is a notation for describing the syntax of formal languages like programming languages, file formats, and protocols. GBNF is an extension of BNF that primarily adds a few modern regex-like features.
|
|
8
8
|
|
|
9
9
|
## Basics
|
|
10
10
|
|
|
@@ -126,19 +126,257 @@ You can use GBNF grammars:
|
|
|
126
126
|
- in CLI, with [examples/json_schema_to_grammar.py](../examples/json_schema_to_grammar.py)
|
|
127
127
|
- in JavaScript with [json-schema-to-grammar.mjs](../examples/server/public/json-schema-to-grammar.mjs) (this is used by the [server](../examples/server)'s Web UI)
|
|
128
128
|
|
|
129
|
-
Take a look at [tests](
|
|
129
|
+
Take a look at [tests](../tests/test-json-schema-to-grammar.cpp) to see which features are likely supported (you'll also find usage examples in https://github.com/ggerganov/llama.cpp/pull/5978, https://github.com/ggerganov/llama.cpp/pull/6659 & https://github.com/ggerganov/llama.cpp/pull/6555).
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
llama-cli \
|
|
133
|
+
-hfr bartowski/Phi-3-medium-128k-instruct-GGUF \
|
|
134
|
+
-hff Phi-3-medium-128k-instruct-Q8_0.gguf \
|
|
135
|
+
-j '{
|
|
136
|
+
"type": "array",
|
|
137
|
+
"items": {
|
|
138
|
+
"type": "object",
|
|
139
|
+
"properties": {
|
|
140
|
+
"name": {
|
|
141
|
+
"type": "string",
|
|
142
|
+
"minLength": 1,
|
|
143
|
+
"maxLength": 100
|
|
144
|
+
},
|
|
145
|
+
"age": {
|
|
146
|
+
"type": "integer",
|
|
147
|
+
"minimum": 0,
|
|
148
|
+
"maximum": 150
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"required": ["name", "age"],
|
|
152
|
+
"additionalProperties": false
|
|
153
|
+
},
|
|
154
|
+
"minItems": 10,
|
|
155
|
+
"maxItems": 100
|
|
156
|
+
}' \
|
|
157
|
+
-p 'Generate a {name, age}[] JSON array with famous actors of all ages.'
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
<details>
|
|
161
|
+
|
|
162
|
+
<summary>Show grammar</summary>
|
|
163
|
+
|
|
164
|
+
You can convert any schema in command-line with:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
examples/json_schema_to_grammar.py name-age-schema.json
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
char ::= [^"\\\x7F\x00-\x1F] | [\\] (["\\bfnrt] | "u" [0-9a-fA-F]{4})
|
|
172
|
+
item ::= "{" space item-name-kv "," space item-age-kv "}" space
|
|
173
|
+
item-age ::= ([0-9] | ([1-8] [0-9] | [9] [0-9]) | "1" ([0-4] [0-9] | [5] "0")) space
|
|
174
|
+
item-age-kv ::= "\"age\"" space ":" space item-age
|
|
175
|
+
item-name ::= "\"" char{1,100} "\"" space
|
|
176
|
+
item-name-kv ::= "\"name\"" space ":" space item-name
|
|
177
|
+
root ::= "[" space item ("," space item){9,99} "]" space
|
|
178
|
+
space ::= | " " | "\n" [ \t]{0,20}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
</details>
|
|
182
|
+
|
|
183
|
+
Here is also a list of known limitations (contributions welcome):
|
|
184
|
+
|
|
185
|
+
- `additionalProperties` defaults to `false` (produces faster grammars + reduces hallucinations).
|
|
186
|
+
- `"additionalProperties": true` may produce keys that contain unescaped newlines.
|
|
187
|
+
- Unsupported features are skipped silently. It is currently advised to use the command-line Python converter (see above) to see any warnings, and to inspect the resulting grammar / test it w/ [llama-gbnf-validator](../examples/gbnf-validator/gbnf-validator.cpp).
|
|
188
|
+
- Can't mix `properties` w/ `anyOf` / `oneOf` in the same type (https://github.com/ggerganov/llama.cpp/issues/7703)
|
|
189
|
+
- [prefixItems](https://json-schema.org/draft/2020-12/json-schema-core#name-prefixitems) is broken (but [items](https://json-schema.org/draft/2020-12/json-schema-core#name-items) works)
|
|
190
|
+
- `minimum`, `exclusiveMinimum`, `maximum`, `exclusiveMaximum`: only supported for `"type": "integer"` for now, not `number`
|
|
191
|
+
- Nested `$ref`s are broken (https://github.com/ggerganov/llama.cpp/issues/8073)
|
|
192
|
+
- [pattern](https://json-schema.org/draft/2020-12/json-schema-validation#name-pattern)s must start with `^` and end with `$`
|
|
193
|
+
- Remote `$ref`s not supported in the C++ version (Python & JavaScript versions fetch https refs)
|
|
194
|
+
- `string` [formats](https://json-schema.org/draft/2020-12/json-schema-validation#name-defined-formats) lack `uri`, `email`
|
|
195
|
+
- No [`patternProperties`](https://json-schema.org/draft/2020-12/json-schema-core#name-patternproperties)
|
|
130
196
|
|
|
131
|
-
|
|
197
|
+
And a non-exhaustive list of other unsupported features that are unlikely to be implemented (hard and/or too slow to support w/ stateless grammars):
|
|
132
198
|
|
|
133
|
-
- `
|
|
134
|
-
- `minimum`, `exclusiveMinimum`, `maximum`, `exclusiveMaximum`
|
|
135
|
-
- `integer` constraints to be implemented in https://github.com/ggerganov/llama.cpp/pull/7797
|
|
136
|
-
- Remote `$ref`s in the C++ version (Python & JavaScript versions fetch https refs)
|
|
137
|
-
- Mixing `properties` w/ `anyOf` / `oneOf` in the same type (https://github.com/ggerganov/llama.cpp/issues/7703)
|
|
138
|
-
- `string` formats `uri`, `email`
|
|
199
|
+
- [`uniqueItems`](https://json-schema.org/draft/2020-12/json-schema-validation#name-uniqueitems)
|
|
139
200
|
- [`contains`](https://json-schema.org/draft/2020-12/json-schema-core#name-contains) / `minContains`
|
|
140
|
-
- `uniqueItems`
|
|
141
201
|
- `$anchor` (cf. [dereferencing](https://json-schema.org/draft/2020-12/json-schema-core#name-dereferencing))
|
|
142
202
|
- [`not`](https://json-schema.org/draft/2020-12/json-schema-core#name-not)
|
|
143
203
|
- [Conditionals](https://json-schema.org/draft/2020-12/json-schema-core#name-keywords-for-applying-subsche) `if` / `then` / `else` / `dependentSchemas`
|
|
144
|
-
|
|
204
|
+
|
|
205
|
+
### A word about additionalProperties
|
|
206
|
+
|
|
207
|
+
> [!WARNING]
|
|
208
|
+
> The JSON schemas spec states `object`s accept [additional properties](https://json-schema.org/understanding-json-schema/reference/object#additionalproperties) by default.
|
|
209
|
+
> Since this is slow and seems prone to hallucinations, we default to no additional properties.
|
|
210
|
+
> You can set `"additionalProperties": true` in the the schema of any object to explicitly allow additional properties.
|
|
211
|
+
|
|
212
|
+
If you're using [Pydantic](https://pydantic.dev/) to generate schemas, you can enable additional properties with the `extra` config on each model class:
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
# pip install pydantic
|
|
216
|
+
import json
|
|
217
|
+
from typing import Annotated, List
|
|
218
|
+
from pydantic import BaseModel, Extra, Field
|
|
219
|
+
class QAPair(BaseModel):
|
|
220
|
+
class Config:
|
|
221
|
+
extra = 'allow' # triggers additionalProperties: true in the JSON schema
|
|
222
|
+
question: str
|
|
223
|
+
concise_answer: str
|
|
224
|
+
justification: str
|
|
225
|
+
|
|
226
|
+
class Summary(BaseModel):
|
|
227
|
+
class Config:
|
|
228
|
+
extra = 'allow'
|
|
229
|
+
key_facts: List[Annotated[str, Field(pattern='- .{5,}')]]
|
|
230
|
+
question_answers: List[Annotated[List[QAPair], Field(min_items=5)]]
|
|
231
|
+
|
|
232
|
+
print(json.dumps(Summary.model_json_schema(), indent=2))
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
<details>
|
|
236
|
+
<summary>Show JSON schema & grammar</summary>
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"$defs": {
|
|
241
|
+
"QAPair": {
|
|
242
|
+
"additionalProperties": true,
|
|
243
|
+
"properties": {
|
|
244
|
+
"question": {
|
|
245
|
+
"title": "Question",
|
|
246
|
+
"type": "string"
|
|
247
|
+
},
|
|
248
|
+
"concise_answer": {
|
|
249
|
+
"title": "Concise Answer",
|
|
250
|
+
"type": "string"
|
|
251
|
+
},
|
|
252
|
+
"justification": {
|
|
253
|
+
"title": "Justification",
|
|
254
|
+
"type": "string"
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
"required": [
|
|
258
|
+
"question",
|
|
259
|
+
"concise_answer",
|
|
260
|
+
"justification"
|
|
261
|
+
],
|
|
262
|
+
"title": "QAPair",
|
|
263
|
+
"type": "object"
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
"additionalProperties": true,
|
|
267
|
+
"properties": {
|
|
268
|
+
"key_facts": {
|
|
269
|
+
"items": {
|
|
270
|
+
"pattern": "^- .{5,}$",
|
|
271
|
+
"type": "string"
|
|
272
|
+
},
|
|
273
|
+
"title": "Key Facts",
|
|
274
|
+
"type": "array"
|
|
275
|
+
},
|
|
276
|
+
"question_answers": {
|
|
277
|
+
"items": {
|
|
278
|
+
"items": {
|
|
279
|
+
"$ref": "#/$defs/QAPair"
|
|
280
|
+
},
|
|
281
|
+
"minItems": 5,
|
|
282
|
+
"type": "array"
|
|
283
|
+
},
|
|
284
|
+
"title": "Question Answers",
|
|
285
|
+
"type": "array"
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
"required": [
|
|
289
|
+
"key_facts",
|
|
290
|
+
"question_answers"
|
|
291
|
+
],
|
|
292
|
+
"title": "Summary",
|
|
293
|
+
"type": "object"
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
QAPair ::= "{" space QAPair-question-kv "," space QAPair-concise-answer-kv "," space QAPair-justification-kv ( "," space ( QAPair-additional-kv ( "," space QAPair-additional-kv )* ) )? "}" space
|
|
299
|
+
QAPair-additional-k ::= ["] ( [c] ([o] ([n] ([c] ([i] ([s] ([e] ([_] ([a] ([n] ([s] ([w] ([e] ([r] char+ | [^"r] char*) | [^"e] char*) | [^"w] char*) | [^"s] char*) | [^"n] char*) | [^"a] char*) | [^"_] char*) | [^"e] char*) | [^"s] char*) | [^"i] char*) | [^"c] char*) | [^"n] char*) | [^"o] char*) | [j] ([u] ([s] ([t] ([i] ([f] ([i] ([c] ([a] ([t] ([i] ([o] ([n] char+ | [^"n] char*) | [^"o] char*) | [^"i] char*) | [^"t] char*) | [^"a] char*) | [^"c] char*) | [^"i] char*) | [^"f] char*) | [^"i] char*) | [^"t] char*) | [^"s] char*) | [^"u] char*) | [q] ([u] ([e] ([s] ([t] ([i] ([o] ([n] char+ | [^"n] char*) | [^"o] char*) | [^"i] char*) | [^"t] char*) | [^"s] char*) | [^"e] char*) | [^"u] char*) | [^"cjq] char* )? ["] space
|
|
300
|
+
QAPair-additional-kv ::= QAPair-additional-k ":" space value
|
|
301
|
+
QAPair-concise-answer-kv ::= "\"concise_answer\"" space ":" space string
|
|
302
|
+
QAPair-justification-kv ::= "\"justification\"" space ":" space string
|
|
303
|
+
QAPair-question-kv ::= "\"question\"" space ":" space string
|
|
304
|
+
additional-k ::= ["] ( [k] ([e] ([y] ([_] ([f] ([a] ([c] ([t] ([s] char+ | [^"s] char*) | [^"t] char*) | [^"c] char*) | [^"a] char*) | [^"f] char*) | [^"_] char*) | [^"y] char*) | [^"e] char*) | [q] ([u] ([e] ([s] ([t] ([i] ([o] ([n] ([_] ([a] ([n] ([s] ([w] ([e] ([r] ([s] char+ | [^"s] char*) | [^"r] char*) | [^"e] char*) | [^"w] char*) | [^"s] char*) | [^"n] char*) | [^"a] char*) | [^"_] char*) | [^"n] char*) | [^"o] char*) | [^"i] char*) | [^"t] char*) | [^"s] char*) | [^"e] char*) | [^"u] char*) | [^"kq] char* )? ["] space
|
|
305
|
+
additional-kv ::= additional-k ":" space value
|
|
306
|
+
array ::= "[" space ( value ("," space value)* )? "]" space
|
|
307
|
+
boolean ::= ("true" | "false") space
|
|
308
|
+
char ::= [^"\\\x7F\x00-\x1F] | [\\] (["\\bfnrt] | "u" [0-9a-fA-F]{4})
|
|
309
|
+
decimal-part ::= [0-9]{1,16}
|
|
310
|
+
dot ::= [^\x0A\x0D]
|
|
311
|
+
integral-part ::= [0] | [1-9] [0-9]{0,15}
|
|
312
|
+
key-facts ::= "[" space (key-facts-item ("," space key-facts-item)*)? "]" space
|
|
313
|
+
key-facts-item ::= "\"" "- " key-facts-item-1{5,} "\"" space
|
|
314
|
+
key-facts-item-1 ::= dot
|
|
315
|
+
key-facts-kv ::= "\"key_facts\"" space ":" space key-facts
|
|
316
|
+
null ::= "null" space
|
|
317
|
+
number ::= ("-"? integral-part) ("." decimal-part)? ([eE] [-+]? integral-part)? space
|
|
318
|
+
object ::= "{" space ( string ":" space value ("," space string ":" space value)* )? "}" space
|
|
319
|
+
question-answers ::= "[" space (question-answers-item ("," space question-answers-item)*)? "]" space
|
|
320
|
+
question-answers-item ::= "[" space question-answers-item-item ("," space question-answers-item-item){4,} "]" space
|
|
321
|
+
question-answers-item-item ::= QAPair
|
|
322
|
+
question-answers-kv ::= "\"question_answers\"" space ":" space question-answers
|
|
323
|
+
root ::= "{" space key-facts-kv "," space question-answers-kv ( "," space ( additional-kv ( "," space additional-kv )* ) )? "}" space
|
|
324
|
+
space ::= | " " | "\n" [ \t]{0,20}
|
|
325
|
+
string ::= "\"" char* "\"" space
|
|
326
|
+
value ::= object | array | string | number | boolean | null
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
</details>
|
|
330
|
+
|
|
331
|
+
If you're using [Zod](https://zod.dev/), you can make your objects to explicitly allow extra properties w/ `nonstrict()` / `passthrough()` (or explicitly no extra props w/ `z.object(...).strict()` or `z.strictObject(...)`) but note that [zod-to-json-schema](https://github.com/StefanTerdell/zod-to-json-schema) currently always sets `"additionalProperties": false` anyway.
|
|
332
|
+
|
|
333
|
+
```js
|
|
334
|
+
import { z } from 'zod';
|
|
335
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
336
|
+
|
|
337
|
+
const Foo = z.object({
|
|
338
|
+
age: z.number().positive(),
|
|
339
|
+
email: z.string().email(),
|
|
340
|
+
}).strict();
|
|
341
|
+
|
|
342
|
+
console.log(zodToJsonSchema(Foo));
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
<details>
|
|
346
|
+
<summary>Show JSON schema & grammar</summary>
|
|
347
|
+
|
|
348
|
+
```json
|
|
349
|
+
{
|
|
350
|
+
"type": "object",
|
|
351
|
+
"properties": {
|
|
352
|
+
"age": {
|
|
353
|
+
"type": "number",
|
|
354
|
+
"exclusiveMinimum": 0
|
|
355
|
+
},
|
|
356
|
+
"email": {
|
|
357
|
+
"type": "string",
|
|
358
|
+
"format": "email"
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
"required": [
|
|
362
|
+
"age",
|
|
363
|
+
"email"
|
|
364
|
+
],
|
|
365
|
+
"additionalProperties": false,
|
|
366
|
+
"$schema": "http://json-schema.org/draft-07/schema#"
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
age-kv ::= "\"age\"" space ":" space number
|
|
372
|
+
char ::= [^"\\\x7F\x00-\x1F] | [\\] (["\\bfnrt] | "u" [0-9a-fA-F]{4})
|
|
373
|
+
decimal-part ::= [0-9]{1,16}
|
|
374
|
+
email-kv ::= "\"email\"" space ":" space string
|
|
375
|
+
integral-part ::= [0] | [1-9] [0-9]{0,15}
|
|
376
|
+
number ::= ("-"? integral-part) ("." decimal-part)? ([eE] [-+]? integral-part)? space
|
|
377
|
+
root ::= "{" space age-kv "," space email-kv "}" space
|
|
378
|
+
space ::= | " " | "\n" [ \t]{0,20}
|
|
379
|
+
string ::= "\"" char* "\"" space
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
</details>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|