node-llama-cpp 2.0.0 → 2.1.1
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 +122 -25
- package/dist/ChatPromptWrapper.d.ts +3 -0
- package/dist/ChatPromptWrapper.js.map +1 -1
- package/dist/chatWrappers/ChatMLPromptWrapper.d.ts +11 -0
- package/dist/chatWrappers/ChatMLPromptWrapper.js +19 -0
- package/dist/chatWrappers/ChatMLPromptWrapper.js.map +1 -0
- package/dist/chatWrappers/EmptyChatPromptWrapper.d.ts +1 -0
- package/dist/chatWrappers/EmptyChatPromptWrapper.js +1 -0
- package/dist/chatWrappers/EmptyChatPromptWrapper.js.map +1 -1
- package/dist/chatWrappers/GeneralChatPromptWrapper.d.ts +11 -1
- package/dist/chatWrappers/GeneralChatPromptWrapper.js +28 -4
- package/dist/chatWrappers/GeneralChatPromptWrapper.js.map +1 -1
- package/dist/chatWrappers/LlamaChatPromptWrapper.d.ts +4 -1
- package/dist/chatWrappers/LlamaChatPromptWrapper.js +8 -4
- package/dist/chatWrappers/LlamaChatPromptWrapper.js.map +1 -1
- package/dist/chatWrappers/createChatWrapperByBos.d.ts +2 -0
- package/dist/chatWrappers/createChatWrapperByBos.js +14 -0
- package/dist/chatWrappers/createChatWrapperByBos.js.map +1 -0
- package/dist/cli/commands/BuildCommand.d.ts +3 -1
- package/dist/cli/commands/BuildCommand.js +24 -2
- package/dist/cli/commands/BuildCommand.js.map +1 -1
- package/dist/cli/commands/ChatCommand.d.ts +7 -1
- package/dist/cli/commands/ChatCommand.js +87 -12
- package/dist/cli/commands/ChatCommand.js.map +1 -1
- package/dist/cli/commands/ClearCommand.js +1 -1
- package/dist/cli/commands/ClearCommand.js.map +1 -1
- package/dist/cli/commands/DownloadCommand.d.ts +3 -1
- package/dist/cli/commands/DownloadCommand.js +60 -69
- package/dist/cli/commands/DownloadCommand.js.map +1 -1
- package/dist/cli/commands/OnPostInstallCommand.js +4 -2
- package/dist/cli/commands/OnPostInstallCommand.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/llamaEvaluator/LlamaBins.d.ts +3 -3
- package/dist/llamaEvaluator/LlamaBins.js +2 -2
- package/dist/llamaEvaluator/LlamaBins.js.map +1 -1
- package/dist/llamaEvaluator/LlamaChatSession.d.ts +7 -2
- package/dist/llamaEvaluator/LlamaChatSession.js +51 -11
- package/dist/llamaEvaluator/LlamaChatSession.js.map +1 -1
- package/dist/llamaEvaluator/LlamaContext.d.ts +31 -2
- package/dist/llamaEvaluator/LlamaContext.js +69 -2
- package/dist/llamaEvaluator/LlamaContext.js.map +1 -1
- package/dist/llamaEvaluator/LlamaGrammar.d.ts +14 -0
- package/dist/llamaEvaluator/LlamaGrammar.js +30 -0
- package/dist/llamaEvaluator/LlamaGrammar.js.map +1 -0
- package/dist/llamaEvaluator/LlamaModel.d.ts +49 -1
- package/dist/llamaEvaluator/LlamaModel.js +25 -9
- package/dist/llamaEvaluator/LlamaModel.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/compileLLamaCpp.d.ts +3 -1
- package/dist/utils/compileLLamaCpp.js +34 -4
- package/dist/utils/compileLLamaCpp.js.map +1 -1
- package/dist/utils/getBin.d.ts +15 -2
- package/dist/utils/getBin.js +4 -2
- package/dist/utils/getBin.js.map +1 -1
- package/dist/utils/getGrammarsFolder.d.ts +1 -0
- package/dist/utils/getGrammarsFolder.js +18 -0
- package/dist/utils/getGrammarsFolder.js.map +1 -0
- package/dist/utils/getTextCompletion.d.ts +3 -0
- package/dist/utils/getTextCompletion.js +12 -0
- package/dist/utils/getTextCompletion.js.map +1 -0
- package/dist/utils/removeNullFields.d.ts +1 -0
- package/dist/utils/removeNullFields.js +9 -0
- package/dist/utils/removeNullFields.js.map +1 -0
- package/dist/utils/spawnCommand.d.ts +2 -1
- package/dist/utils/spawnCommand.js +2 -2
- package/dist/utils/spawnCommand.js.map +1 -1
- package/llama/addon.cpp +154 -19
- package/llama/binariesGithubRelease.json +1 -1
- package/llama/binding.gyp +6 -3
- package/llama/grammars/README.md +91 -0
- package/llama/grammars/arithmetic.gbnf +6 -0
- package/llama/grammars/chess.gbnf +13 -0
- package/llama/grammars/japanese.gbnf +7 -0
- package/llama/grammars/json.gbnf +25 -0
- package/llama/grammars/list.gbnf +4 -0
- package/llamaBins/linux-arm64-16.node +0 -0
- package/llamaBins/linux-arm64-17.node +0 -0
- package/llamaBins/linux-arm64-18.node +0 -0
- package/llamaBins/linux-arm64-19.node +0 -0
- package/llamaBins/linux-arm64-20.node +0 -0
- package/llamaBins/linux-armv7l-16.node +0 -0
- package/llamaBins/linux-armv7l-17.node +0 -0
- package/llamaBins/linux-armv7l-18.node +0 -0
- package/llamaBins/linux-armv7l-19.node +0 -0
- package/llamaBins/linux-armv7l-20.node +0 -0
- package/llamaBins/linux-ppc64le-16.node +0 -0
- package/llamaBins/linux-ppc64le-17.node +0 -0
- package/llamaBins/linux-ppc64le-18.node +0 -0
- package/llamaBins/linux-ppc64le-19.node +0 -0
- package/llamaBins/linux-ppc64le-20.node +0 -0
- package/llamaBins/linux-x64-16.node +0 -0
- package/llamaBins/linux-x64-17.node +0 -0
- package/llamaBins/linux-x64-18.node +0 -0
- package/llamaBins/linux-x64-19.node +0 -0
- package/llamaBins/linux-x64-20.node +0 -0
- package/llamaBins/mac-arm64-16.node +0 -0
- package/llamaBins/mac-arm64-17.node +0 -0
- package/llamaBins/mac-arm64-18.node +0 -0
- package/llamaBins/mac-arm64-19.node +0 -0
- package/llamaBins/mac-arm64-20.node +0 -0
- package/llamaBins/mac-x64-16.node +0 -0
- package/llamaBins/mac-x64-17.node +0 -0
- package/llamaBins/mac-x64-18.node +0 -0
- package/llamaBins/mac-x64-19.node +0 -0
- package/llamaBins/mac-x64-20.node +0 -0
- package/llamaBins/win-x64-16.node +0 -0
- package/llamaBins/win-x64-17.node +0 -0
- package/llamaBins/win-x64-18.node +0 -0
- package/llamaBins/win-x64-19.node +0 -0
- package/llamaBins/win-x64-20.node +0 -0
- package/package.json +10 -6
package/dist/utils/getBin.js
CHANGED
|
@@ -3,7 +3,7 @@ import * as console from "console";
|
|
|
3
3
|
import path from "path";
|
|
4
4
|
import process from "process";
|
|
5
5
|
import fs from "fs-extra";
|
|
6
|
-
import { defaultLlamaCppGitHubRepo, defaultLlamaCppRelease, defaultSkipDownload, llamaBinsDirectory } from "../config.js";
|
|
6
|
+
import { defaultLlamaCppCudaSupport, defaultLlamaCppGitHubRepo, defaultLlamaCppMetalSupport, defaultLlamaCppRelease, defaultSkipDownload, llamaBinsDirectory } from "../config.js";
|
|
7
7
|
import { DownloadLlamaCppCommand } from "../cli/commands/DownloadCommand.js";
|
|
8
8
|
import { getUsedBinFlag } from "./usedBinFlag.js";
|
|
9
9
|
import { getCompiledLlamaCppBinaryPath } from "./compileLLamaCpp.js";
|
|
@@ -56,7 +56,9 @@ export async function loadBin() {
|
|
|
56
56
|
else {
|
|
57
57
|
await DownloadLlamaCppCommand({
|
|
58
58
|
repo: defaultLlamaCppGitHubRepo,
|
|
59
|
-
release: defaultLlamaCppRelease
|
|
59
|
+
release: defaultLlamaCppRelease,
|
|
60
|
+
metal: defaultLlamaCppMetalSupport,
|
|
61
|
+
cuda: defaultLlamaCppCudaSupport
|
|
60
62
|
});
|
|
61
63
|
const modulePath = await getCompiledLlamaCppBinaryPath();
|
|
62
64
|
if (modulePath == null) {
|
package/dist/utils/getBin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getBin.js","sourceRoot":"","sources":["../../src/utils/getBin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,QAAQ,CAAC;AACrC,OAAO,KAAK,OAAO,MAAM,SAAS,CAAC;AACnC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,
|
|
1
|
+
{"version":3,"file":"getBin.js","sourceRoot":"","sources":["../../src/utils/getBin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getGrammarsFolder(): Promise<string>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import { llamaBinsGrammarsDirectory, llamaCppGrammarsDirectory } from "../config.js";
|
|
3
|
+
import { getUsedBinFlag } from "./usedBinFlag.js";
|
|
4
|
+
export async function getGrammarsFolder() {
|
|
5
|
+
const usedBingFlag = await getUsedBinFlag();
|
|
6
|
+
if (usedBingFlag === "localBuildFromSource") {
|
|
7
|
+
if (await fs.exists(llamaCppGrammarsDirectory))
|
|
8
|
+
return llamaCppGrammarsDirectory;
|
|
9
|
+
}
|
|
10
|
+
else if (usedBingFlag === "prebuiltBinaries") {
|
|
11
|
+
if (await fs.exists(llamaBinsGrammarsDirectory))
|
|
12
|
+
return llamaBinsGrammarsDirectory;
|
|
13
|
+
else if (await fs.exists(llamaCppGrammarsDirectory))
|
|
14
|
+
return llamaCppGrammarsDirectory;
|
|
15
|
+
}
|
|
16
|
+
throw new Error("Grammars folder not found");
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=getGrammarsFolder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getGrammarsFolder.js","sourceRoot":"","sources":["../../src/utils/getGrammarsFolder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAC,0BAA0B,EAAE,yBAAyB,EAAC,MAAM,cAAc,CAAC;AACnF,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACnC,MAAM,YAAY,GAAG,MAAM,cAAc,EAAE,CAAC;IAE5C,IAAI,YAAY,KAAK,sBAAsB,EAAE;QACzC,IAAI,MAAM,EAAE,CAAC,MAAM,CAAC,yBAAyB,CAAC;YAC1C,OAAO,yBAAyB,CAAC;KACxC;SAAM,IAAI,YAAY,KAAK,kBAAkB,EAAE;QAC5C,IAAI,MAAM,EAAE,CAAC,MAAM,CAAC,0BAA0B,CAAC;YAC3C,OAAO,0BAA0B,CAAC;aACjC,IAAI,MAAM,EAAE,CAAC,MAAM,CAAC,yBAAyB,CAAC;YAC/C,OAAO,yBAAyB,CAAC;KACxC;IAED,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function getTextCompletion(text: null, fullText: string | string[]): null;
|
|
2
|
+
export declare function getTextCompletion(text: string, fullText: string | string[]): string | null;
|
|
3
|
+
export declare function getTextCompletion(text: string | null, fullText: string | string[]): string | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function getTextCompletion(text, fullText) {
|
|
2
|
+
if (text == null) {
|
|
3
|
+
return null;
|
|
4
|
+
}
|
|
5
|
+
const fullTexts = typeof fullText === "string" ? [fullText] : fullText;
|
|
6
|
+
for (const fullText of fullTexts) {
|
|
7
|
+
if (fullText.startsWith(text))
|
|
8
|
+
return fullText.slice(text.length);
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=getTextCompletion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getTextCompletion.js","sourceRoot":"","sources":["../../src/utils/getTextCompletion.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,iBAAiB,CAAC,IAAmB,EAAE,QAA2B;IAC9E,IAAI,IAAI,IAAI,IAAI,EAAE;QACd,OAAO,IAAI,CAAC;KACf;IAED,MAAM,SAAS,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAEvE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;QAC9B,IAAI,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC;YACzB,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;KAC1C;IAED,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function removeNullFields<T extends object>(obj: T): T;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"removeNullFields.js","sourceRoot":"","sources":["../../src/utils/removeNullFields.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB,CAAmB,GAAM;IACrD,MAAM,MAAM,GAAM,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAEzC,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE;QACnB,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI;YACnB,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;KAC1B;IAED,OAAO,MAAM,CAAC;AAClB,CAAC"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export declare function spawnCommand(command: string, args: string[], cwd: string, env?: NodeJS.ProcessEnv): Promise<void>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import spawn from "cross-spawn";
|
|
2
|
-
export function spawnCommand(command, args, cwd) {
|
|
2
|
+
export function spawnCommand(command, args, cwd, env = process.env) {
|
|
3
3
|
function getCommandString() {
|
|
4
4
|
let res = command;
|
|
5
5
|
for (const arg of args) {
|
|
@@ -16,7 +16,7 @@ export function spawnCommand(command, args, cwd) {
|
|
|
16
16
|
const child = spawn(command, args, {
|
|
17
17
|
stdio: "inherit",
|
|
18
18
|
cwd,
|
|
19
|
-
env
|
|
19
|
+
env,
|
|
20
20
|
detached: false,
|
|
21
21
|
windowsHide: true
|
|
22
22
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawnCommand.js","sourceRoot":"","sources":["../../src/utils/spawnCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,aAAa,CAAC;AAEhC,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,IAAc,EAAE,GAAW;
|
|
1
|
+
{"version":3,"file":"spawnCommand.js","sourceRoot":"","sources":["../../src/utils/spawnCommand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,aAAa,CAAC;AAEhC,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,IAAc,EAAE,GAAW,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG;IACxF,SAAS,gBAAgB;QACrB,IAAI,GAAG,GAAG,OAAO,CAAC;QAElB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;YACpB,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;gBACnB,GAAG,IAAI,KAAK,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;aAC7C;iBAAM;gBACH,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC;aACpB;SACJ;QAED,OAAO,GAAG,CAAC;IACf,CAAC;IAED,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACzC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YAC/B,KAAK,EAAE,SAAS;YAChB,GAAG;YACH,GAAG;YACH,QAAQ,EAAE,KAAK;YACf,WAAW,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACtB,IAAI,IAAI,IAAI,CAAC;gBACT,OAAO,EAAE,CAAC;;gBAEV,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,gBAAgB,EAAE,qBAAqB,IAAI,EAAE,CAAC,CAAC,CAAC;QACpF,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,gBAAgB,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;QAC9F,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE;YACrB,IAAI,IAAI,IAAI,CAAC;gBACT,OAAO,EAAE,CAAC;;gBAEV,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,gBAAgB,EAAE,qBAAqB,IAAI,EAAE,CAAC,CAAC,CAAC;QACpF,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/llama/addon.cpp
CHANGED
|
@@ -3,18 +3,26 @@
|
|
|
3
3
|
#include <sstream>
|
|
4
4
|
#include <vector>
|
|
5
5
|
|
|
6
|
+
#include "common.h"
|
|
6
7
|
#include "llama.h"
|
|
8
|
+
#include "common/grammar-parser.h"
|
|
7
9
|
#include "napi.h"
|
|
8
10
|
|
|
9
11
|
class LLAMAModel : public Napi::ObjectWrap<LLAMAModel> {
|
|
10
12
|
public:
|
|
11
13
|
llama_context_params params;
|
|
12
14
|
llama_model* model;
|
|
15
|
+
float temperature;
|
|
16
|
+
int32_t top_k;
|
|
17
|
+
float top_p;
|
|
13
18
|
|
|
14
19
|
LLAMAModel(const Napi::CallbackInfo& info) : Napi::ObjectWrap<LLAMAModel>(info) {
|
|
15
20
|
params = llama_context_default_params();
|
|
16
21
|
params.seed = -1;
|
|
17
22
|
params.n_ctx = 4096;
|
|
23
|
+
temperature = 0.0f;
|
|
24
|
+
top_k = 40;
|
|
25
|
+
top_p = 0.95f;
|
|
18
26
|
|
|
19
27
|
// Get the model path
|
|
20
28
|
std::string modelPath = info[0].As<Napi::String>().Utf8Value();
|
|
@@ -65,6 +73,18 @@ class LLAMAModel : public Napi::ObjectWrap<LLAMAModel> {
|
|
|
65
73
|
if (options.Has("embedding")) {
|
|
66
74
|
params.embedding = options.Get("embedding").As<Napi::Boolean>().Value();
|
|
67
75
|
}
|
|
76
|
+
|
|
77
|
+
if (options.Has("temperature")) {
|
|
78
|
+
temperature = options.Get("temperature").As<Napi::Number>().FloatValue();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (options.Has("topK")) {
|
|
82
|
+
top_k = options.Get("topK").As<Napi::Number>().Int32Value();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (options.Has("topP")) {
|
|
86
|
+
top_p = options.Get("topP").As<Napi::Number>().FloatValue();
|
|
87
|
+
}
|
|
68
88
|
}
|
|
69
89
|
|
|
70
90
|
llama_backend_init(false);
|
|
@@ -85,20 +105,84 @@ class LLAMAModel : public Napi::ObjectWrap<LLAMAModel> {
|
|
|
85
105
|
}
|
|
86
106
|
};
|
|
87
107
|
|
|
108
|
+
class LLAMAGrammar : public Napi::ObjectWrap<LLAMAGrammar> {
|
|
109
|
+
public:
|
|
110
|
+
grammar_parser::parse_state parsed_grammar;
|
|
111
|
+
llama_grammar *grammar = nullptr;
|
|
112
|
+
|
|
113
|
+
LLAMAGrammar(const Napi::CallbackInfo& info) : Napi::ObjectWrap<LLAMAGrammar>(info) {
|
|
114
|
+
// Get the model path
|
|
115
|
+
std::string grammarCode = info[0].As<Napi::String>().Utf8Value();
|
|
116
|
+
bool should_print_grammar = false;
|
|
117
|
+
|
|
118
|
+
if (info.Length() > 1 && info[1].IsObject()) {
|
|
119
|
+
Napi::Object options = info[1].As<Napi::Object>();
|
|
120
|
+
|
|
121
|
+
if (options.Has("printGrammar")) {
|
|
122
|
+
should_print_grammar = options.Get("printGrammar").As<Napi::Boolean>().Value();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
parsed_grammar = grammar_parser::parse(grammarCode.c_str());
|
|
127
|
+
// will be empty (default) if there are parse errors
|
|
128
|
+
if (parsed_grammar.rules.empty()) {
|
|
129
|
+
Napi::Error::New(info.Env(), "Failed to parse grammar").ThrowAsJavaScriptException();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (should_print_grammar) {
|
|
134
|
+
grammar_parser::print_grammar(stderr, parsed_grammar);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
std::vector<const llama_grammar_element *> grammar_rules(parsed_grammar.c_rules());
|
|
138
|
+
grammar = llama_grammar_init(
|
|
139
|
+
grammar_rules.data(), grammar_rules.size(), parsed_grammar.symbol_ids.at("root"));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
~LLAMAGrammar() {
|
|
143
|
+
if (grammar != nullptr) {
|
|
144
|
+
llama_grammar_free(grammar);
|
|
145
|
+
grammar = nullptr;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
static void init(Napi::Object exports) {
|
|
150
|
+
exports.Set("LLAMAGrammar", DefineClass(exports.Env(), "LLAMAGrammar", {}));
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
88
154
|
class LLAMAContext : public Napi::ObjectWrap<LLAMAContext> {
|
|
89
155
|
public:
|
|
90
156
|
LLAMAModel* model;
|
|
91
157
|
llama_context* ctx;
|
|
158
|
+
LLAMAGrammar* grammar;
|
|
159
|
+
bool use_grammar = false;
|
|
160
|
+
|
|
92
161
|
LLAMAContext(const Napi::CallbackInfo& info) : Napi::ObjectWrap<LLAMAContext>(info) {
|
|
93
162
|
model = Napi::ObjectWrap<LLAMAModel>::Unwrap(info[0].As<Napi::Object>());
|
|
94
163
|
model->Ref();
|
|
95
164
|
ctx = llama_new_context_with_model(model->model, model->params);
|
|
96
165
|
Napi::MemoryManagement::AdjustExternalMemory(Env(), llama_get_state_size(ctx));
|
|
166
|
+
|
|
167
|
+
if (info.Length() > 1 && info[1].IsObject()) {
|
|
168
|
+
Napi::Object options = info[1].As<Napi::Object>();
|
|
169
|
+
|
|
170
|
+
if (options.Has("grammar")) {
|
|
171
|
+
grammar = Napi::ObjectWrap<LLAMAGrammar>::Unwrap(options.Get("grammar").As<Napi::Object>());
|
|
172
|
+
grammar->Ref();
|
|
173
|
+
use_grammar = true;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
97
176
|
}
|
|
98
177
|
~LLAMAContext() {
|
|
99
178
|
Napi::MemoryManagement::AdjustExternalMemory(Env(), -(int64_t)llama_get_state_size(ctx));
|
|
100
179
|
llama_free(ctx);
|
|
101
180
|
model->Unref();
|
|
181
|
+
|
|
182
|
+
if (use_grammar) {
|
|
183
|
+
grammar->Unref();
|
|
184
|
+
use_grammar = false;
|
|
185
|
+
}
|
|
102
186
|
}
|
|
103
187
|
Napi::Value Encode(const Napi::CallbackInfo& info) {
|
|
104
188
|
std::string text = info[0].As<Napi::String>().Utf8Value();
|
|
@@ -125,23 +209,13 @@ class LLAMAContext : public Napi::ObjectWrap<LLAMAContext> {
|
|
|
125
209
|
|
|
126
210
|
// Decode each token and accumulate the result.
|
|
127
211
|
for (size_t i = 0; i < tokens.ElementLength(); i++) {
|
|
128
|
-
|
|
129
|
-
std::vector<char> result(8, 0);
|
|
130
|
-
const int n_tokens = llama_token_to_str(ctx, (llama_token)tokens[i], result.data(), result.size());
|
|
131
|
-
if (n_tokens < 0) {
|
|
132
|
-
result.resize(-n_tokens);
|
|
133
|
-
int check = llama_token_to_str(ctx, (llama_token)tokens[i], result.data(), result.size());
|
|
134
|
-
GGML_ASSERT(check == -n_tokens);
|
|
135
|
-
} else {
|
|
136
|
-
result.resize(n_tokens);
|
|
137
|
-
}
|
|
212
|
+
const std::string piece = llama_token_to_piece(ctx, (llama_token)tokens[i]);
|
|
138
213
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
ss << str;
|
|
214
|
+
if (piece.empty()) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
ss << piece;
|
|
145
219
|
}
|
|
146
220
|
|
|
147
221
|
return Napi::String::New(info.Env(), ss.str());
|
|
@@ -152,9 +226,25 @@ class LLAMAContext : public Napi::ObjectWrap<LLAMAContext> {
|
|
|
152
226
|
Napi::Value TokenEos(const Napi::CallbackInfo& info) {
|
|
153
227
|
return Napi::Number::From(info.Env(), llama_token_eos(ctx));
|
|
154
228
|
}
|
|
155
|
-
Napi::Value
|
|
229
|
+
Napi::Value TokenNl(const Napi::CallbackInfo& info) {
|
|
230
|
+
return Napi::Number::From(info.Env(), llama_token_nl(ctx));
|
|
231
|
+
}
|
|
232
|
+
Napi::Value GetContextSize(const Napi::CallbackInfo& info) {
|
|
156
233
|
return Napi::Number::From(info.Env(), llama_n_ctx(ctx));
|
|
157
234
|
}
|
|
235
|
+
Napi::Value GetTokenString(const Napi::CallbackInfo& info) {
|
|
236
|
+
int token = info[0].As<Napi::Number>().Int32Value();
|
|
237
|
+
std::stringstream ss;
|
|
238
|
+
|
|
239
|
+
const char* str = llama_token_get_text(ctx, token);
|
|
240
|
+
if (str == nullptr) {
|
|
241
|
+
return info.Env().Undefined();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
ss << str;
|
|
245
|
+
|
|
246
|
+
return Napi::String::New(info.Env(), ss.str());
|
|
247
|
+
}
|
|
158
248
|
Napi::Value Eval(const Napi::CallbackInfo& info);
|
|
159
249
|
static void init(Napi::Object exports) {
|
|
160
250
|
exports.Set("LLAMAContext",
|
|
@@ -165,7 +255,9 @@ class LLAMAContext : public Napi::ObjectWrap<LLAMAContext> {
|
|
|
165
255
|
InstanceMethod("decode", &LLAMAContext::Decode),
|
|
166
256
|
InstanceMethod("tokenBos", &LLAMAContext::TokenBos),
|
|
167
257
|
InstanceMethod("tokenEos", &LLAMAContext::TokenEos),
|
|
168
|
-
InstanceMethod("
|
|
258
|
+
InstanceMethod("tokenNl", &LLAMAContext::TokenNl),
|
|
259
|
+
InstanceMethod("getContextSize", &LLAMAContext::GetContextSize),
|
|
260
|
+
InstanceMethod("getTokenString", &LLAMAContext::GetTokenString),
|
|
169
261
|
InstanceMethod("eval", &LLAMAContext::Eval),
|
|
170
262
|
}));
|
|
171
263
|
}
|
|
@@ -212,7 +304,49 @@ class LLAMAContextEvalWorker : Napi::AsyncWorker, Napi::Promise::Deferred {
|
|
|
212
304
|
|
|
213
305
|
llama_token_data_array candidates_p = { candidates.data(), candidates.size(), false };
|
|
214
306
|
|
|
215
|
-
|
|
307
|
+
float originalEosLogit = 0;
|
|
308
|
+
auto eos_token = llama_token_eos(ctx->ctx);
|
|
309
|
+
|
|
310
|
+
for (auto& candidate : candidates) {
|
|
311
|
+
if (candidate.id == eos_token) {
|
|
312
|
+
originalEosLogit = candidate.logit;
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (ctx->use_grammar) {
|
|
318
|
+
llama_sample_grammar(ctx->ctx, &candidates_p, (ctx->grammar)->grammar);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
for (auto& candidate : candidates) {
|
|
322
|
+
if (candidate.id == eos_token) {
|
|
323
|
+
candidate.logit = originalEosLogit;
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if ((ctx->model)->temperature <= 0) {
|
|
329
|
+
new_token_id = llama_sample_token_greedy(ctx->ctx , &candidates_p);
|
|
330
|
+
} else {
|
|
331
|
+
const int32_t top_k = (ctx->model)->top_k <= 0 ? llama_n_vocab(ctx->ctx) : (ctx->model)->top_k;
|
|
332
|
+
const int32_t n_probs = 0; // Number of probabilities to keep - 0 = disabled
|
|
333
|
+
const float tfs_z = 1.00f; // Tail free sampling - 1.0 = disabled
|
|
334
|
+
const float typical_p = 1.00f; // Typical probability - 1.0 = disabled
|
|
335
|
+
const float top_p = (ctx->model)->top_p; // Top p sampling - 1.0 = disabled
|
|
336
|
+
|
|
337
|
+
// Temperature sampling
|
|
338
|
+
size_t min_keep = std::max(1, n_probs);
|
|
339
|
+
llama_sample_top_k(ctx->ctx, &candidates_p, top_k, min_keep);
|
|
340
|
+
llama_sample_tail_free(ctx->ctx, &candidates_p, tfs_z, min_keep);
|
|
341
|
+
llama_sample_typical(ctx->ctx, &candidates_p, typical_p, min_keep);
|
|
342
|
+
llama_sample_top_p(ctx->ctx, &candidates_p, top_p, min_keep);
|
|
343
|
+
llama_sample_temperature(ctx->ctx, &candidates_p, (ctx->model)->temperature);;
|
|
344
|
+
new_token_id = llama_sample_token(ctx->ctx, &candidates_p);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (new_token_id != eos_token && ctx->use_grammar) {
|
|
348
|
+
llama_grammar_accept_token(ctx->ctx, (ctx->grammar)->grammar, new_token_id);
|
|
349
|
+
}
|
|
216
350
|
|
|
217
351
|
result = new_token_id;
|
|
218
352
|
}
|
|
@@ -238,6 +372,7 @@ Napi::Object registerCallback(Napi::Env env, Napi::Object exports) {
|
|
|
238
372
|
Napi::PropertyDescriptor::Function("systemInfo", systemInfo),
|
|
239
373
|
});
|
|
240
374
|
LLAMAModel::init(exports);
|
|
375
|
+
LLAMAGrammar::init(exports);
|
|
241
376
|
LLAMAContext::init(exports);
|
|
242
377
|
return exports;
|
|
243
378
|
}
|
package/llama/binding.gyp
CHANGED
|
@@ -7,15 +7,18 @@
|
|
|
7
7
|
"llama.cpp/ggml.c",
|
|
8
8
|
"llama.cpp/ggml-alloc.c",
|
|
9
9
|
"llama.cpp/k_quants.c",
|
|
10
|
-
"llama.cpp/llama.cpp"
|
|
10
|
+
"llama.cpp/llama.cpp",
|
|
11
|
+
"llama.cpp/common/common.cpp",
|
|
12
|
+
"llama.cpp/common/grammar-parser.cpp"
|
|
11
13
|
],
|
|
12
14
|
"include_dirs": [
|
|
13
15
|
"<!@(node -p \"require('node-addon-api').include\")",
|
|
14
|
-
"llama.cpp"
|
|
16
|
+
"llama.cpp",
|
|
17
|
+
"llama.cpp/common"
|
|
15
18
|
],
|
|
16
19
|
"cflags": ["-fexceptions"],
|
|
17
20
|
"cflags_cc": ["-fexceptions"],
|
|
18
|
-
"defines": [
|
|
21
|
+
"defines": ["GGML_USE_K_QUANTS", "NAPI_CPP_EXCEPTIONS"],
|
|
19
22
|
"msvs_settings": {
|
|
20
23
|
"VCCLCompilerTool": { "AdditionalOptions": [ '/arch:AVX2', '/EHsc' ] }
|
|
21
24
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# GBNF Guide
|
|
2
|
+
|
|
3
|
+
GBNF (GGML BNF) is a format for defining [formal grammars](https://en.wikipedia.org/wiki/Formal_grammar) to constrain model outputs in `llama.cpp`. For example, you can use it to force the model to generate valid JSON, or speak only in emojis. GBNF grammars are supported in various ways in `examples/main` and `examples/server`.
|
|
4
|
+
|
|
5
|
+
## Background
|
|
6
|
+
|
|
7
|
+
[Bakus-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
|
+
|
|
9
|
+
## Basics
|
|
10
|
+
|
|
11
|
+
In GBNF, we define *production rules* that specify how a *non-terminal* (rule name) can be replaced with sequences of *terminals* (characters, specifically Unicode [code points](https://en.wikipedia.org/wiki/Code_point)) and other non-terminals. The basic format of a production rule is `nonterminal ::= sequence...`.
|
|
12
|
+
|
|
13
|
+
## Example
|
|
14
|
+
|
|
15
|
+
Before going deeper, let's look at some of the features demonstrated in `grammars/chess.gbnf`, a small chess notation grammar:
|
|
16
|
+
```
|
|
17
|
+
# `root` specifies the pattern for the overall output
|
|
18
|
+
root ::= (
|
|
19
|
+
# it must start with the characters "1. " followed by a sequence
|
|
20
|
+
# of characters that match the `move` rule, followed by a space, followed
|
|
21
|
+
# by another move, and then a newline
|
|
22
|
+
"1. " move " " move "\n"
|
|
23
|
+
|
|
24
|
+
# it's followed by one or more subsequent moves, numbered with one or two digits
|
|
25
|
+
([1-9] [0-9]? ". " move " " move "\n")+
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# `move` is an abstract representation, which can be a pawn, nonpawn, or castle.
|
|
29
|
+
# The `[+#]?` denotes the possibility of checking or mate signs after moves
|
|
30
|
+
move ::= (pawn | nonpawn | castle) [+#]?
|
|
31
|
+
|
|
32
|
+
pawn ::= ...
|
|
33
|
+
nonpawn ::= ...
|
|
34
|
+
castle ::= ...
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Non-Terminals and Terminals
|
|
38
|
+
|
|
39
|
+
Non-terminal symbols (rule names) stand for a pattern of terminals and other non-terminals. They are required to be a dashed lowercase word, like `move`, `castle`, or `check-mate`.
|
|
40
|
+
|
|
41
|
+
Terminals are actual characters ([code points](https://en.wikipedia.org/wiki/Code_point)). They can be specified as a sequence like `"1"` or `"O-O"` or as ranges like `[1-9]` or `[NBKQR]`.
|
|
42
|
+
|
|
43
|
+
## Characters and character ranges
|
|
44
|
+
|
|
45
|
+
Terminals support the full range of Unicode. Unicode characters can be specified directly in the grammar, for example `hiragana ::= [ぁ-ゟ]`, or with escapes: 8-bit (`\xXX`), 16-bit (`\uXXXX`) or 32-bit (`\UXXXXXXXX`).
|
|
46
|
+
|
|
47
|
+
Character ranges can be negated with `^`:
|
|
48
|
+
```
|
|
49
|
+
single-line ::= [^\n]+ "\n"`
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Sequences and Alternatives
|
|
53
|
+
|
|
54
|
+
The order of symbols in a sequence matter. For example, in `"1. " move " " move "\n"`, the `"1. "` must come before the first `move`, etc.
|
|
55
|
+
|
|
56
|
+
Alternatives, denoted by `|`, give different sequences that are acceptable. For example, in `move ::= pawn | nonpawn | castle`, `move` can be a `pawn` move, a `nonpawn` move, or a `castle`.
|
|
57
|
+
|
|
58
|
+
Parentheses `()` can be used to group sequences, which allows for embedding alternatives in a larger rule or applying repetition and optptional symbols (below) to a sequence.
|
|
59
|
+
|
|
60
|
+
## Repetition and Optional Symbols
|
|
61
|
+
|
|
62
|
+
- `*` after a symbol or sequence means that it can be repeated zero or more times.
|
|
63
|
+
- `+` denotes that the symbol or sequence should appear one or more times.
|
|
64
|
+
- `?` makes the preceding symbol or sequence optional.
|
|
65
|
+
|
|
66
|
+
## Comments and newlines
|
|
67
|
+
|
|
68
|
+
Comments can be specified with `#`:
|
|
69
|
+
```
|
|
70
|
+
# defines optional whitspace
|
|
71
|
+
ws ::= [ \t\n]+
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Newlines are allowed between rules and between symbols or sequences nested inside parentheses. Additionally, a newline after an alternate marker `|` will continue the current rule, even outside of parentheses.
|
|
75
|
+
|
|
76
|
+
## The root rule
|
|
77
|
+
|
|
78
|
+
In a full grammar, the `root` rule always defines the starting point of the grammar. In other words, it specifies what the entire output must match.
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
# a grammar for lists
|
|
82
|
+
root ::= ("- " item)+
|
|
83
|
+
item ::= [^\n]+ "\n"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Next steps
|
|
87
|
+
|
|
88
|
+
This guide provides a brief overview. Check out the GBNF files in this directory (`grammars/`) for examples of full grammars. You can try them out with:
|
|
89
|
+
```
|
|
90
|
+
./main -m <model> --grammar-file grammars/some-grammar.gbnf -p 'Some prompt'
|
|
91
|
+
```
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Specifies chess moves as a list in algebraic notation, using PGN conventions
|
|
2
|
+
|
|
3
|
+
# Force first move to "1. ", then any 1-2 digit number after, relying on model to follow the pattern
|
|
4
|
+
root ::= "1. " move " " move "\n" ([1-9] [0-9]? ". " move " " move "\n")+
|
|
5
|
+
move ::= (pawn | nonpawn | castle) [+#]?
|
|
6
|
+
|
|
7
|
+
# piece type, optional file/rank, optional capture, dest file & rank
|
|
8
|
+
nonpawn ::= [NBKQR] [a-h]? [1-8]? "x"? [a-h] [1-8]
|
|
9
|
+
|
|
10
|
+
# optional file & capture, dest file & rank, optional promotion
|
|
11
|
+
pawn ::= ([a-h] "x")? [a-h] [1-8] ("=" [NBKQR])?
|
|
12
|
+
|
|
13
|
+
castle ::= "O-O" "-O"?
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
root ::= object
|
|
2
|
+
value ::= object | array | string | number | ("true" | "false" | "null") ws
|
|
3
|
+
|
|
4
|
+
object ::=
|
|
5
|
+
"{" ws (
|
|
6
|
+
string ":" ws value
|
|
7
|
+
("," ws string ":" ws value)*
|
|
8
|
+
)? "}" ws
|
|
9
|
+
|
|
10
|
+
array ::=
|
|
11
|
+
"[" ws (
|
|
12
|
+
value
|
|
13
|
+
("," ws value)*
|
|
14
|
+
)? "]" ws
|
|
15
|
+
|
|
16
|
+
string ::=
|
|
17
|
+
"\"" (
|
|
18
|
+
[^"\\] |
|
|
19
|
+
"\\" (["\\/bfnrt] | "u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]) # escapes
|
|
20
|
+
)* "\"" ws
|
|
21
|
+
|
|
22
|
+
number ::= ("-"? ([0-9] | [1-9] [0-9]*)) ("." [0-9]+)? ([eE] [-+]? [0-9]+)? ws
|
|
23
|
+
|
|
24
|
+
# Optional space: by convention, applied in this grammar after literal chars when allowed
|
|
25
|
+
ws ::= ([ \t\n] ws)?
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|