@gmickel/gno 1.46.0 → 2.1.0
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 +17 -5
- package/THIRD_PARTY_NOTICES.md +46 -0
- package/assets/skill/SKILL.md +7 -6
- package/assets/spa-production.json.gz +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.1.0.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.1.0.zip.sha256 +1 -0
- package/browser-extension/dist/chunk-4tc9v0ja.js +74 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/browser-extension/dist/preview.html +1 -1
- package/browser-extension/dist/service-worker.js +32 -33
- package/bunfig.toml +2 -0
- package/package.json +40 -26
- package/spec/cli.md +29 -4
- package/spec/db/schema.sql +146 -1
- package/spec/mcp.md +26 -0
- package/src/app/context-runtime-types.ts +3 -0
- package/src/app/context-runtime.ts +2 -0
- package/src/cli/commands/ask.ts +6 -1
- package/src/cli/commands/daemon.ts +21 -8
- package/src/cli/commands/embed.ts +77 -41
- package/src/cli/detach.ts +3 -2
- package/src/config/types.ts +3 -3
- package/src/converters/adapters/markitdownTs/adapter.ts +1 -2
- package/src/converters/adapters/officeparser/adapter.ts +1 -2
- package/src/converters/versions.ts +6 -8
- package/src/core/context-evidence.ts +8 -4
- package/src/core/job-manager.ts +95 -13
- package/src/core/network-boundary-inventory.ts +10 -0
- package/src/core/shutdown-budget.ts +45 -0
- package/src/embed/backlog.ts +107 -4
- package/src/embed/batch.ts +42 -2
- package/src/embed/fingerprint.ts +16 -0
- package/src/embed/retry.ts +113 -5
- package/src/embed/variant-backlog.ts +105 -0
- package/src/embed/variant-plan.ts +62 -0
- package/src/embed/variant-retry.ts +113 -0
- package/src/ingestion/graph-reconciliation.ts +327 -0
- package/src/ingestion/sync.ts +9 -272
- package/src/llm/http-inference.ts +6 -0
- package/src/llm/httpEmbedding.ts +37 -6
- package/src/llm/httpGeneration.ts +18 -3
- package/src/llm/httpRerank.ts +23 -5
- package/src/llm/inference-cancellation.ts +168 -0
- package/src/llm/inference-scope.ts +202 -0
- package/src/llm/lazy-ports.ts +115 -0
- package/src/llm/native-worker/client.ts +541 -0
- package/src/llm/native-worker/dispatcher.ts +228 -0
- package/src/llm/native-worker/embedding-identity.ts +33 -0
- package/src/llm/native-worker/entry.ts +173 -0
- package/src/llm/native-worker/errors.ts +32 -0
- package/src/llm/native-worker/evaluation.ts +16 -0
- package/src/llm/native-worker/owned-exit.ts +108 -0
- package/src/llm/native-worker/owner.ts +141 -0
- package/src/llm/native-worker/ports.ts +317 -0
- package/src/llm/native-worker/protocol.ts +442 -0
- package/src/llm/native-worker/runtime-config.ts +92 -0
- package/src/llm/nodeLlamaCpp/adapter.ts +77 -20
- package/src/llm/nodeLlamaCpp/embedding.ts +130 -46
- package/src/llm/nodeLlamaCpp/generation.ts +34 -5
- package/src/llm/nodeLlamaCpp/lifecycle-options.ts +99 -0
- package/src/llm/nodeLlamaCpp/lifecycle.ts +209 -204
- package/src/llm/nodeLlamaCpp/rerank-capacity.ts +111 -0
- package/src/llm/nodeLlamaCpp/rerank.ts +118 -27
- package/src/llm/nodeLlamaCpp/simulator-handle.ts +73 -0
- package/src/llm/nodeLlamaCpp/simulator-install.ts +124 -0
- package/src/llm/nodeLlamaCpp/simulator-session.ts +240 -0
- package/src/llm/nodeLlamaCpp/simulator-types.ts +80 -0
- package/src/llm/types.ts +35 -5
- package/src/mcp/context.ts +27 -0
- package/src/mcp/http-transport.ts +12 -10
- package/src/mcp/server.ts +3 -0
- package/src/mcp/tool-profile.ts +30 -8
- package/src/mcp/tools/context.ts +8 -11
- package/src/mcp/tools/embed.ts +1 -1
- package/src/mcp/tools/index-cmd.ts +1 -1
- package/src/mcp/tools/index.ts +10 -8
- package/src/mcp/tools/query.ts +14 -30
- package/src/mcp/tools/vsearch.ts +1 -1
- package/src/pipeline/answer.ts +23 -3
- package/src/pipeline/claim-verifier.ts +6 -0
- package/src/pipeline/expansion.ts +43 -40
- package/src/pipeline/explain.ts +6 -2
- package/src/pipeline/filters.ts +63 -0
- package/src/pipeline/fusion.ts +29 -9
- package/src/pipeline/graph-retrieval.ts +29 -9
- package/src/pipeline/hybrid.ts +198 -55
- package/src/pipeline/hydration.ts +161 -0
- package/src/pipeline/owner-fusion.ts +87 -0
- package/src/pipeline/rerank.ts +35 -11
- package/src/pipeline/search.ts +13 -2
- package/src/pipeline/types.ts +5 -3
- package/src/pipeline/vsearch.ts +87 -7
- package/src/sdk/client.ts +47 -3
- package/src/sdk/embed.ts +63 -39
- package/src/serve/background-runtime.ts +1 -1
- package/src/serve/context.ts +41 -56
- package/src/serve/embed-scheduler.ts +58 -35
- package/src/serve/public/components/IndexingProgress.tsx +46 -60
- package/src/serve/public/components/PublishExportDialog.tsx +266 -0
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/globals.css +35 -0
- package/src/serve/public/lib/publish-export.ts +81 -1
- package/src/serve/public/lib/shiki-language-ids.ts +14 -0
- package/src/serve/public/pages/Collections.tsx +12 -46
- package/src/serve/public/pages/DocView.tsx +14 -52
- package/src/serve/resident-admission.ts +36 -36
- package/src/serve/resident-background-work.ts +20 -2
- package/src/serve/resident-request.ts +11 -5
- package/src/serve/resident-runtime.ts +97 -61
- package/src/serve/resident-shutdown.ts +153 -0
- package/src/serve/routes/api.ts +3 -1
- package/src/serve/server.ts +47 -26
- package/src/store/migrations/028-vector-variants.ts +54 -0
- package/src/store/migrations/029-graph-reference-state.ts +77 -0
- package/src/store/migrations/index.ts +4 -0
- package/src/store/sqlite/adapter.ts +251 -183
- package/src/store/sqlite/eligibility.ts +174 -0
- package/src/store/sqlite/graph-edge-application.ts +66 -0
- package/src/store/sqlite/graph-reference-state.ts +194 -0
- package/src/store/sqlite/legacy-vector-ownership.ts +79 -0
- package/src/store/types.ts +80 -12
- package/src/store/vector/eligibility.ts +36 -0
- package/src/store/vector/freshness.ts +33 -6
- package/src/store/vector/lazy.ts +81 -0
- package/src/store/vector/sqlite-vec.ts +106 -54
- package/src/store/vector/stats.ts +14 -3
- package/src/store/vector/types.ts +35 -2
- package/src/store/vector/variant-search.ts +192 -0
- package/src/store/vector/variants.ts +451 -0
- package/vendor/converters/markitdown-ts/LICENSE +21 -0
- package/vendor/converters/markitdown-ts/dist/index.cjs +1180 -0
- package/vendor/converters/markitdown-ts/dist/index.d.cts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.d.mts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.d.ts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.mjs +1152 -0
- package/vendor/converters/markitdown-ts/package.json +77 -0
- package/vendor/converters/officeparser/LICENSE +21 -0
- package/vendor/converters/officeparser/dist/OfficeConverter.d.ts +47 -0
- package/vendor/converters/officeparser/dist/OfficeConverter.js +76 -0
- package/vendor/converters/officeparser/dist/OfficeGenerator.d.ts +23 -0
- package/vendor/converters/officeparser/dist/OfficeGenerator.js +73 -0
- package/vendor/converters/officeparser/dist/OfficeParser.d.ts +106 -0
- package/vendor/converters/officeparser/dist/OfficeParser.js +332 -0
- package/vendor/converters/officeparser/dist/cli.d.ts +28 -0
- package/vendor/converters/officeparser/dist/cli.js +381 -0
- package/vendor/converters/officeparser/dist/defaults.d.ts +41 -0
- package/vendor/converters/officeparser/dist/defaults.js +218 -0
- package/vendor/converters/officeparser/dist/generators/BaseGenerator.d.ts +107 -0
- package/vendor/converters/officeparser/dist/generators/BaseGenerator.js +248 -0
- package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.d.ts +82 -0
- package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.js +797 -0
- package/vendor/converters/officeparser/dist/generators/CsvGenerator.d.ts +38 -0
- package/vendor/converters/officeparser/dist/generators/CsvGenerator.js +245 -0
- package/vendor/converters/officeparser/dist/generators/EpubGenerator.d.ts +43 -0
- package/vendor/converters/officeparser/dist/generators/EpubGenerator.js +315 -0
- package/vendor/converters/officeparser/dist/generators/HtmlGenerator.d.ts +59 -0
- package/vendor/converters/officeparser/dist/generators/HtmlGenerator.js +1942 -0
- package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.d.ts +96 -0
- package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.js +1175 -0
- package/vendor/converters/officeparser/dist/generators/PdfGenerator.d.ts +22 -0
- package/vendor/converters/officeparser/dist/generators/PdfGenerator.js +194 -0
- package/vendor/converters/officeparser/dist/generators/RtfGenerator.d.ts +29 -0
- package/vendor/converters/officeparser/dist/generators/RtfGenerator.js +316 -0
- package/vendor/converters/officeparser/dist/generators/TextGenerator.d.ts +13 -0
- package/vendor/converters/officeparser/dist/generators/TextGenerator.js +201 -0
- package/vendor/converters/officeparser/dist/index.d.ts +60 -0
- package/vendor/converters/officeparser/dist/index.js +72 -0
- package/vendor/converters/officeparser/dist/index.mjs +18 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.d.ts +2621 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.iife.js +1336 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.mjs +1335 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.d.ts +2621 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.iife.js +1336 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.mjs +1335 -0
- package/vendor/converters/officeparser/dist/parsers/CsvParser.d.ts +9 -0
- package/vendor/converters/officeparser/dist/parsers/CsvParser.js +115 -0
- package/vendor/converters/officeparser/dist/parsers/EpubParser.d.ts +8 -0
- package/vendor/converters/officeparser/dist/parsers/EpubParser.js +217 -0
- package/vendor/converters/officeparser/dist/parsers/ExcelParser.d.ts +32 -0
- package/vendor/converters/officeparser/dist/parsers/ExcelParser.js +736 -0
- package/vendor/converters/officeparser/dist/parsers/HtmlParser.d.ts +2 -0
- package/vendor/converters/officeparser/dist/parsers/HtmlParser.js +1287 -0
- package/vendor/converters/officeparser/dist/parsers/MarkdownParser.d.ts +2 -0
- package/vendor/converters/officeparser/dist/parsers/MarkdownParser.js +1272 -0
- package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.d.ts +31 -0
- package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.js +1819 -0
- package/vendor/converters/officeparser/dist/parsers/PdfParser.d.ts +67 -0
- package/vendor/converters/officeparser/dist/parsers/PdfParser.js +848 -0
- package/vendor/converters/officeparser/dist/parsers/PowerPointParser.d.ts +32 -0
- package/vendor/converters/officeparser/dist/parsers/PowerPointParser.js +950 -0
- package/vendor/converters/officeparser/dist/parsers/RtfParser.d.ts +187 -0
- package/vendor/converters/officeparser/dist/parsers/RtfParser.js +1801 -0
- package/vendor/converters/officeparser/dist/parsers/WordParser.d.ts +79 -0
- package/vendor/converters/officeparser/dist/parsers/WordParser.js +1177 -0
- package/vendor/converters/officeparser/dist/sbom.cdx.json +1763 -0
- package/vendor/converters/officeparser/dist/types.d.ts +2507 -0
- package/vendor/converters/officeparser/dist/types.js +107 -0
- package/vendor/converters/officeparser/dist/utils/astUtils.d.ts +16 -0
- package/vendor/converters/officeparser/dist/utils/astUtils.js +33 -0
- package/vendor/converters/officeparser/dist/utils/chartUtils.d.ts +6 -0
- package/vendor/converters/officeparser/dist/utils/chartUtils.js +257 -0
- package/vendor/converters/officeparser/dist/utils/configUtils.d.ts +44 -0
- package/vendor/converters/officeparser/dist/utils/configUtils.js +315 -0
- package/vendor/converters/officeparser/dist/utils/dateUtils.d.ts +17 -0
- package/vendor/converters/officeparser/dist/utils/dateUtils.js +69 -0
- package/vendor/converters/officeparser/dist/utils/envUtils.d.ts +29 -0
- package/vendor/converters/officeparser/dist/utils/envUtils.js +152 -0
- package/vendor/converters/officeparser/dist/utils/errorUtils.d.ts +72 -0
- package/vendor/converters/officeparser/dist/utils/errorUtils.js +245 -0
- package/vendor/converters/officeparser/dist/utils/imageUtils.d.ts +66 -0
- package/vendor/converters/officeparser/dist/utils/imageUtils.js +133 -0
- package/vendor/converters/officeparser/dist/utils/mathUtils.d.ts +42 -0
- package/vendor/converters/officeparser/dist/utils/mathUtils.js +385 -0
- package/vendor/converters/officeparser/dist/utils/moduleLoader.d.ts +18 -0
- package/vendor/converters/officeparser/dist/utils/moduleLoader.js +106 -0
- package/vendor/converters/officeparser/dist/utils/ocrUtils.d.ts +42 -0
- package/vendor/converters/officeparser/dist/utils/ocrUtils.js +428 -0
- package/vendor/converters/officeparser/dist/utils/sanitize.d.ts +148 -0
- package/vendor/converters/officeparser/dist/utils/sanitize.js +344 -0
- package/vendor/converters/officeparser/dist/utils/sheetUtils.d.ts +7 -0
- package/vendor/converters/officeparser/dist/utils/sheetUtils.js +35 -0
- package/vendor/converters/officeparser/dist/utils/styleMapper.d.ts +36 -0
- package/vendor/converters/officeparser/dist/utils/styleMapper.js +224 -0
- package/vendor/converters/officeparser/dist/utils/xmlUtils.d.ts +163 -0
- package/vendor/converters/officeparser/dist/utils/xmlUtils.js +461 -0
- package/vendor/converters/officeparser/dist/utils/zipUtils.d.ts +134 -0
- package/vendor/converters/officeparser/dist/utils/zipUtils.js +337 -0
- package/vendor/converters/officeparser/package.json +147 -0
- package/vendor/converters/upstream-manifest.json +124 -0
- package/vendor/dependency-fixes/README.md +77 -0
- package/vendor/dependency-fixes/vendor-converters.py +83 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.46.0.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.46.0.zip.sha256 +0 -1
- package/browser-extension/dist/chunk-627emwpj.js +0 -75
- /package/browser-extension/dist/{chunk-ydfx5d7p.css → chunk-z74y8n8c.css} +0 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/** Pinned native formatting contract; no context allocation or input clipping. */
|
|
2
|
+
import type { LlamaModel, Token } from "node-llama-cpp";
|
|
3
|
+
|
|
4
|
+
import { getModuleVersion } from "node-llama-cpp";
|
|
5
|
+
|
|
6
|
+
const installedVersion = await getModuleVersion();
|
|
7
|
+
|
|
8
|
+
export const RERANK_NATIVE_VERSION = "3.20.0";
|
|
9
|
+
export const RERANK_TEMPLATE =
|
|
10
|
+
'<|im_start|>system\nJudge whether the Document meets the requirements based on the Query and the Instruct provided. Note that the answer can only be "yes" or "no".<|im_end|>\n<|im_start|>user\n<Instruct>: Given a web search query, retrieve relevant passages that answer the query\n<Query>: {query}\n<Document>: {document}<|im_end|>\n<|im_start|>assistant\n<think>\n\n</think>\n\n';
|
|
11
|
+
|
|
12
|
+
type CapacityModel = Pick<
|
|
13
|
+
LlamaModel,
|
|
14
|
+
| "fileInfo"
|
|
15
|
+
| "tokens"
|
|
16
|
+
| "tokenize"
|
|
17
|
+
| "tokenizer"
|
|
18
|
+
| "trainContextSize"
|
|
19
|
+
| "vocabularyType"
|
|
20
|
+
>;
|
|
21
|
+
|
|
22
|
+
export type RerankCapacity =
|
|
23
|
+
| { kind: "empty" }
|
|
24
|
+
| { kind: "auto"; reason: string }
|
|
25
|
+
| { kind: "sized"; contextSize: number; requiredTokens: number };
|
|
26
|
+
|
|
27
|
+
function supported(model: CapacityModel, version: string): boolean {
|
|
28
|
+
return (
|
|
29
|
+
version === RERANK_NATIVE_VERSION &&
|
|
30
|
+
model.fileInfo.metadata.general?.architecture === "qwen3" &&
|
|
31
|
+
model.vocabularyType === "bpe" &&
|
|
32
|
+
model.fileInfo.metadata.tokenizer?.["chat_template.rerank"] ===
|
|
33
|
+
RERANK_TEMPLATE
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** 3.20.0 LlamaRankingContext.js is byte-identical to the audited 3.19.1 source.
|
|
38
|
+
* Mirrors 3.20.0 _getEvaluationInput for the one audited template/vocabulary. */
|
|
39
|
+
export function formatRerankPair(
|
|
40
|
+
model: CapacityModel,
|
|
41
|
+
query: string,
|
|
42
|
+
document: string,
|
|
43
|
+
version = installedVersion
|
|
44
|
+
): Token[] | null {
|
|
45
|
+
if (!supported(model, version)) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
const [prefix, rest = ""] = RERANK_TEMPLATE.split("{query}");
|
|
49
|
+
const [middle, suffix = ""] = rest.split("{document}");
|
|
50
|
+
const input = [
|
|
51
|
+
...model.tokenize(prefix ?? "", true, "trimLeadingSpace"),
|
|
52
|
+
...model.tokenizer(query, false, "trimLeadingSpace"),
|
|
53
|
+
...model.tokenize(middle ?? "", true, "trimLeadingSpace"),
|
|
54
|
+
...model.tokenizer(document, false, "trimLeadingSpace"),
|
|
55
|
+
...model.tokenize(suffix, true, "trimLeadingSpace"),
|
|
56
|
+
];
|
|
57
|
+
const { bos, eos, shouldPrependBosToken, shouldAppendEosToken } =
|
|
58
|
+
model.tokens;
|
|
59
|
+
if (shouldPrependBosToken && bos != null && input.at(0) !== bos) {
|
|
60
|
+
input.unshift(bos);
|
|
61
|
+
}
|
|
62
|
+
if (shouldAppendEosToken && eos != null && input.at(-1) !== eos) {
|
|
63
|
+
// Native 3.20.0 prepends here despite calling this an end token. Preserve parity.
|
|
64
|
+
input.unshift(eos);
|
|
65
|
+
}
|
|
66
|
+
return input;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function getRerankCapacity(
|
|
70
|
+
model: CapacityModel,
|
|
71
|
+
query: string,
|
|
72
|
+
documents: readonly string[],
|
|
73
|
+
version = installedVersion
|
|
74
|
+
): RerankCapacity {
|
|
75
|
+
if (documents.length === 0) {
|
|
76
|
+
return { kind: "empty" };
|
|
77
|
+
}
|
|
78
|
+
if (!supported(model, version)) {
|
|
79
|
+
return {
|
|
80
|
+
kind: "auto",
|
|
81
|
+
reason: "Unsupported native version, model or template",
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const maximum = model.trainContextSize;
|
|
85
|
+
if (!Number.isSafeInteger(maximum) || maximum <= 0) {
|
|
86
|
+
return { kind: "auto", reason: "Unknown model context limit" };
|
|
87
|
+
}
|
|
88
|
+
let requiredTokens = 0;
|
|
89
|
+
for (const document of documents) {
|
|
90
|
+
const tokens = formatRerankPair(model, query, document, version);
|
|
91
|
+
if (tokens === null) {
|
|
92
|
+
return { kind: "auto", reason: "Unsupported formatter" };
|
|
93
|
+
}
|
|
94
|
+
requiredTokens = Math.max(requiredTokens, tokens.length);
|
|
95
|
+
}
|
|
96
|
+
if (requiredTokens > maximum) {
|
|
97
|
+
throw new RangeError(
|
|
98
|
+
`Rerank input requires ${requiredTokens} tokens; model supports ${maximum}`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
// 3.20.0 config.contextSizePad is 256. The frozen native audit scored
|
|
102
|
+
// ceil((full pair + 256) / 256) * 256 at exact parity; no smaller guard is proven.
|
|
103
|
+
const contextSize = Math.ceil((requiredTokens + 256) / 256) * 256;
|
|
104
|
+
if (contextSize > maximum) {
|
|
105
|
+
return {
|
|
106
|
+
kind: "auto",
|
|
107
|
+
reason: "Padded capacity exceeds model context limit",
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
return { kind: "sized", contextSize, requiredTokens };
|
|
111
|
+
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
import type { NativeEvaluationOptions } from "../native-worker/evaluation";
|
|
2
|
+
import type { LlmResult, RerankPort, RerankScore } from "../types";
|
|
1
3
|
/**
|
|
2
4
|
* Rerank port implementation using node-llama-cpp.
|
|
3
5
|
*
|
|
4
6
|
* @module src/llm/nodeLlamaCpp/rerank
|
|
5
7
|
*/
|
|
6
|
-
|
|
7
|
-
import type { LlmResult, RerankPort, RerankScore } from "../types";
|
|
8
8
|
import type { ModelManager } from "./lifecycle";
|
|
9
9
|
|
|
10
10
|
import { inferenceFailedError } from "../errors";
|
|
11
|
+
import { checkEvaluation, startEvaluation } from "../native-worker/evaluation";
|
|
12
|
+
import { getRerankCapacity } from "./rerank-capacity";
|
|
11
13
|
|
|
12
14
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
13
15
|
// Types
|
|
@@ -28,6 +30,15 @@ export class NodeLlamaCppRerank implements RerankPort {
|
|
|
28
30
|
readonly modelUri: string;
|
|
29
31
|
private readonly modelPath: string;
|
|
30
32
|
|
|
33
|
+
private context: Awaited<
|
|
34
|
+
ReturnType<LlamaModel["createRankingContext"]>
|
|
35
|
+
> | null = null;
|
|
36
|
+
private contextModel: LlamaModel | null = null;
|
|
37
|
+
private contextSize: number | undefined;
|
|
38
|
+
private contextConfiguration: string | undefined;
|
|
39
|
+
private pending: Promise<void> = Promise.resolve();
|
|
40
|
+
private disposed = false;
|
|
41
|
+
|
|
31
42
|
constructor(manager: ModelManager, modelUri: string, modelPath: string) {
|
|
32
43
|
this.manager = manager;
|
|
33
44
|
this.modelUri = modelUri;
|
|
@@ -36,41 +47,103 @@ export class NodeLlamaCppRerank implements RerankPort {
|
|
|
36
47
|
|
|
37
48
|
async rerank(
|
|
38
49
|
query: string,
|
|
39
|
-
documents: string[]
|
|
50
|
+
documents: string[],
|
|
51
|
+
options?: NativeEvaluationOptions
|
|
40
52
|
): Promise<LlmResult<RerankScore[]>> {
|
|
41
53
|
if (documents.length === 0) {
|
|
42
54
|
return { ok: true, value: [] };
|
|
43
55
|
}
|
|
44
56
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// Build index map for O(1) lookups (handles duplicates correctly)
|
|
55
|
-
const indexMap = new Map<string, number[]>();
|
|
56
|
-
for (let i = 0; i < documents.length; i += 1) {
|
|
57
|
-
const doc = documents[i] as string; // Guaranteed by loop bounds
|
|
58
|
-
const indices = indexMap.get(doc) ?? [];
|
|
59
|
-
indices.push(i);
|
|
60
|
-
indexMap.set(doc, indices);
|
|
57
|
+
if (this.disposed) {
|
|
58
|
+
return {
|
|
59
|
+
ok: false,
|
|
60
|
+
error: inferenceFailedError(
|
|
61
|
+
this.modelUri,
|
|
62
|
+
new Error("Rerank port is disposed")
|
|
63
|
+
),
|
|
64
|
+
};
|
|
61
65
|
}
|
|
66
|
+
// Snapshot caller-owned input before waiting for a different capacity batch.
|
|
67
|
+
const input = [...documents];
|
|
68
|
+
const operation = this.pending.then(() =>
|
|
69
|
+
this.score(query, input, options)
|
|
70
|
+
);
|
|
71
|
+
this.pending = operation.then(
|
|
72
|
+
() => {},
|
|
73
|
+
() => {}
|
|
74
|
+
);
|
|
75
|
+
return operation;
|
|
76
|
+
}
|
|
62
77
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
78
|
+
private async score(
|
|
79
|
+
query: string,
|
|
80
|
+
documents: string[],
|
|
81
|
+
options?: NativeEvaluationOptions
|
|
82
|
+
): Promise<LlmResult<RerankScore[]>> {
|
|
83
|
+
const lease = this.manager.acquireLease(this.modelUri);
|
|
66
84
|
try {
|
|
67
|
-
|
|
85
|
+
checkEvaluation(options);
|
|
86
|
+
const model = await this.manager.loadModel(
|
|
87
|
+
this.modelPath,
|
|
88
|
+
this.modelUri,
|
|
89
|
+
"rerank",
|
|
90
|
+
options?.signal
|
|
91
|
+
);
|
|
92
|
+
if (!model.ok) return model;
|
|
93
|
+
checkEvaluation(options);
|
|
94
|
+
const llamaModel = model.value.model as LlamaModel;
|
|
95
|
+
if (llamaModel.disposed) throw new Error("Rerank model is disposed");
|
|
96
|
+
const capacity = getRerankCapacity(llamaModel, query, documents);
|
|
97
|
+
const contextSize =
|
|
98
|
+
capacity.kind === "sized" ? capacity.contextSize : undefined;
|
|
99
|
+
const configuration = JSON.stringify([
|
|
100
|
+
llamaModel.fileInfo.metadata.general?.architecture,
|
|
101
|
+
llamaModel.fileInfo.metadata.tokenizer?.["chat_template.rerank"],
|
|
102
|
+
llamaModel.vocabularyType,
|
|
103
|
+
llamaModel.trainContextSize,
|
|
104
|
+
]);
|
|
105
|
+
if (
|
|
106
|
+
this.contextConfiguration !== configuration ||
|
|
107
|
+
this.contextModel !== llamaModel ||
|
|
108
|
+
this.contextSize !== contextSize ||
|
|
109
|
+
this.context?.disposed
|
|
110
|
+
) {
|
|
111
|
+
await this.releaseContext();
|
|
112
|
+
}
|
|
113
|
+
if (!this.context) {
|
|
114
|
+
this.context = await llamaModel.createRankingContext({
|
|
115
|
+
...(contextSize === undefined ? {} : { contextSize }),
|
|
116
|
+
createSignal: options?.signal,
|
|
117
|
+
});
|
|
118
|
+
this.contextModel = llamaModel;
|
|
119
|
+
this.contextSize = contextSize;
|
|
120
|
+
this.contextConfiguration = configuration;
|
|
121
|
+
}
|
|
122
|
+
if (this.context.disposed || llamaModel.disposed)
|
|
123
|
+
throw new Error("Rerank context is disposed");
|
|
124
|
+
// Build index map for O(1) lookups (handles duplicates correctly)
|
|
125
|
+
const indexMap = new Map<string, number[]>();
|
|
126
|
+
for (let i = 0; i < documents.length; i += 1) {
|
|
127
|
+
const doc = documents[i] as string; // Guaranteed by loop bounds
|
|
128
|
+
const indices = indexMap.get(doc) ?? [];
|
|
129
|
+
indices.push(i);
|
|
130
|
+
indexMap.set(doc, indices);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
startEvaluation(options);
|
|
134
|
+
const ranked = await this.context.rankAndSort(query, documents);
|
|
135
|
+
checkEvaluation(options);
|
|
136
|
+
if (ranked.length !== documents.length)
|
|
137
|
+
throw new Error("Rerank returned incomplete scores");
|
|
68
138
|
|
|
69
139
|
// Convert to RerankScore format with O(1) index lookup
|
|
70
140
|
const scores: RerankScore[] = ranked.map((item, rank) => {
|
|
71
141
|
const indices = indexMap.get(item.document) ?? [];
|
|
72
142
|
// Shift to handle duplicates (each duplicate gets next index)
|
|
73
|
-
const index = indices.shift()
|
|
143
|
+
const index = indices.shift();
|
|
144
|
+
if (index === undefined || !Number.isFinite(item.score)) {
|
|
145
|
+
throw new Error("Rerank returned invalid candidate scores");
|
|
146
|
+
}
|
|
74
147
|
return {
|
|
75
148
|
index,
|
|
76
149
|
score: item.score,
|
|
@@ -80,16 +153,34 @@ export class NodeLlamaCppRerank implements RerankPort {
|
|
|
80
153
|
|
|
81
154
|
return { ok: true, value: scores };
|
|
82
155
|
} catch (e) {
|
|
156
|
+
await this.releaseContext();
|
|
83
157
|
return { ok: false, error: inferenceFailedError(this.modelUri, e) };
|
|
84
158
|
} finally {
|
|
159
|
+
lease.release();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private async releaseContext(): Promise<void> {
|
|
164
|
+
const context = this.context;
|
|
165
|
+
this.context = null;
|
|
166
|
+
this.contextModel = null;
|
|
167
|
+
this.contextSize = undefined;
|
|
168
|
+
this.contextConfiguration = undefined;
|
|
169
|
+
if (context && !context.disposed) {
|
|
85
170
|
await context.dispose().catch(() => {
|
|
86
|
-
//
|
|
171
|
+
// A failed native context must never be reused.
|
|
87
172
|
});
|
|
88
173
|
}
|
|
89
174
|
}
|
|
90
175
|
|
|
91
176
|
async dispose(): Promise<void> {
|
|
92
|
-
|
|
93
|
-
|
|
177
|
+
this.disposed = true;
|
|
178
|
+
await this.pending;
|
|
179
|
+
const lease = this.manager.acquireLease(this.modelUri, false);
|
|
180
|
+
try {
|
|
181
|
+
await this.releaseContext();
|
|
182
|
+
} finally {
|
|
183
|
+
lease.release();
|
|
184
|
+
}
|
|
94
185
|
}
|
|
95
186
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/** MIT, Copyright (c) 2023 Gilad S. PR636 simulator lifetime backport.
|
|
2
|
+
* https://github.com/withcatai/node-llama-cpp/commit/3f686d75aa9cda1b20b80465883f5f7358e42880
|
|
3
|
+
* Full notice in THIRD_PARTY_NOTICES.md. No native dependency files are changed.
|
|
4
|
+
*/
|
|
5
|
+
import type {
|
|
6
|
+
SimulatorBackend,
|
|
7
|
+
SimulatorDependencies,
|
|
8
|
+
SimulatorDisposable,
|
|
9
|
+
SimulatorGuard,
|
|
10
|
+
SimulatorModel,
|
|
11
|
+
} from "./simulator-types";
|
|
12
|
+
|
|
13
|
+
// Keep the local weak finalizer helper so repeated disposal joins the same
|
|
14
|
+
// promise without retaining the model target.
|
|
15
|
+
const finalizers = new FinalizationRegistry<SimulatorDisposable>((target) => {
|
|
16
|
+
try {
|
|
17
|
+
void Promise.resolve(target.dispose()).catch(() => {});
|
|
18
|
+
} catch {
|
|
19
|
+
/* Finalizers cannot report to callers. */
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
function register(target: object, disposable: SimulatorDisposable): () => void {
|
|
23
|
+
const token = {};
|
|
24
|
+
finalizers.register(target, disposable, token);
|
|
25
|
+
return () => {
|
|
26
|
+
finalizers.unregister(token);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class SimulatorModelHandle {
|
|
31
|
+
readonly disposeGuard: SimulatorGuard;
|
|
32
|
+
private readonly backendHandle: SimulatorDisposable;
|
|
33
|
+
private readonly listener: SimulatorDisposable;
|
|
34
|
+
private readonly unregisterBackend: () => void;
|
|
35
|
+
private readonly unregisterListener: () => void;
|
|
36
|
+
private disposal?: Promise<void>;
|
|
37
|
+
|
|
38
|
+
constructor(
|
|
39
|
+
llama: SimulatorBackend,
|
|
40
|
+
readonly model: SimulatorModel,
|
|
41
|
+
dependencies: SimulatorDependencies
|
|
42
|
+
) {
|
|
43
|
+
this.disposeGuard = new dependencies.DisposeGuard([
|
|
44
|
+
llama._backendDisposeGuard,
|
|
45
|
+
]);
|
|
46
|
+
this.backendHandle =
|
|
47
|
+
llama._backendDisposeGuard.createPreventDisposalHandle();
|
|
48
|
+
this.unregisterBackend = register(model, this.backendHandle);
|
|
49
|
+
const reference = new WeakRef(this);
|
|
50
|
+
this.listener = llama.onDispose.createListener(() =>
|
|
51
|
+
reference
|
|
52
|
+
.deref()
|
|
53
|
+
?.dispose()
|
|
54
|
+
.catch(() => {})
|
|
55
|
+
);
|
|
56
|
+
this.unregisterListener = register(model, this.listener);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
dispose(): Promise<void> {
|
|
60
|
+
// All eviction/session/backend callers must observe the same completion.
|
|
61
|
+
this.disposal ??= this.disposeInternal();
|
|
62
|
+
return this.disposal;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private async disposeInternal(): Promise<void> {
|
|
66
|
+
this.unregisterBackend();
|
|
67
|
+
await this.listener.dispose();
|
|
68
|
+
this.unregisterListener();
|
|
69
|
+
await this.disposeGuard.acquireDisposeLock();
|
|
70
|
+
await this.model.dispose().catch(() => {});
|
|
71
|
+
await this.backendHandle.dispose();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/** Install the pinned simulator guard in memory, including npm/nested installs. */
|
|
2
|
+
import type {
|
|
3
|
+
SimulatorBackend,
|
|
4
|
+
SimulatorDependencies,
|
|
5
|
+
} from "./simulator-types";
|
|
6
|
+
|
|
7
|
+
import { GuardedSimulatorSession } from "./simulator-session";
|
|
8
|
+
|
|
9
|
+
const SOURCE_SHA256 =
|
|
10
|
+
"8bd7b140540eda598d18313eeb17d72d737c39280252449b2b9a5a43db8927b2";
|
|
11
|
+
const INSTALLATION = Symbol.for("gno.node-llama-cpp.simulator-lifetime.v1");
|
|
12
|
+
const FACTORY_SHAPE =
|
|
13
|
+
/new\s+GgufInsightsSimulatorSession\s*\(\s*this\._llama\s*,\s*lruCacheSize\s*\)/;
|
|
14
|
+
let installation: Promise<void> | undefined;
|
|
15
|
+
|
|
16
|
+
function unsupported(): Error {
|
|
17
|
+
return new Error(
|
|
18
|
+
"Unsupported node-llama-cpp simulator source: expected unmodified 3.20.0 for the native lifetime guard"
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Resolve against the actual dependency export, never a repository node_modules path. */
|
|
23
|
+
export async function verifySimulatorPackage(
|
|
24
|
+
entry = import.meta.resolve("node-llama-cpp")
|
|
25
|
+
): Promise<string> {
|
|
26
|
+
const index = new URL(entry);
|
|
27
|
+
if (index.protocol !== "file:") throw unsupported();
|
|
28
|
+
const metadata: unknown = await Bun.file(
|
|
29
|
+
new URL("../package.json", index)
|
|
30
|
+
).json();
|
|
31
|
+
if (
|
|
32
|
+
typeof metadata !== "object" ||
|
|
33
|
+
metadata === null ||
|
|
34
|
+
!("name" in metadata) ||
|
|
35
|
+
!("version" in metadata) ||
|
|
36
|
+
metadata.name !== "node-llama-cpp" ||
|
|
37
|
+
metadata.version !== "3.20.0"
|
|
38
|
+
)
|
|
39
|
+
throw unsupported();
|
|
40
|
+
const source = await Bun.file(
|
|
41
|
+
new URL("./gguf/insights/GgufInsights.js", index)
|
|
42
|
+
).arrayBuffer();
|
|
43
|
+
if (
|
|
44
|
+
new Bun.CryptoHasher("sha256").update(source).digest("hex") !==
|
|
45
|
+
SOURCE_SHA256
|
|
46
|
+
)
|
|
47
|
+
throw unsupported();
|
|
48
|
+
return index.href;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Internal, native-free helper loading remains anchored to this package copy. */
|
|
52
|
+
export async function loadSimulatorDependencies(
|
|
53
|
+
entry: string
|
|
54
|
+
): Promise<SimulatorDependencies> {
|
|
55
|
+
const [guards, cache, locks, binding, tensors, byteModule] =
|
|
56
|
+
await Promise.all([
|
|
57
|
+
import(new URL("./utils/DisposeGuard.js", entry).href),
|
|
58
|
+
import(new URL("./utils/LruCache.js", entry).href),
|
|
59
|
+
import(import.meta.resolve("lifecycle-utils", entry)),
|
|
60
|
+
import(new URL("./bindings/types.js", entry).href),
|
|
61
|
+
import(new URL("./gguf/types/GgufTensorInfoTypes.js", entry).href),
|
|
62
|
+
import(import.meta.resolve("bytes", entry)),
|
|
63
|
+
]);
|
|
64
|
+
return {
|
|
65
|
+
DisposeGuard: guards.DisposeGuard,
|
|
66
|
+
LruCache: cache.LruCache,
|
|
67
|
+
acquireLock: locks.acquireLock,
|
|
68
|
+
needInitLock: binding.doesLlamaBackendNeedAddonInitLock,
|
|
69
|
+
addonInit: binding.LlamaLocks.addonInit,
|
|
70
|
+
debug: binding.LlamaLogLevel.debug,
|
|
71
|
+
error: binding.LlamaLogLevel.error,
|
|
72
|
+
f16: tensors.GgmlType.F16,
|
|
73
|
+
bytes: byteModule.default,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function install(): Promise<void> {
|
|
78
|
+
const entry = await verifySimulatorPackage();
|
|
79
|
+
const module = await import(entry);
|
|
80
|
+
const prototype: Record<PropertyKey, unknown> | undefined =
|
|
81
|
+
module.GgufInsights?.prototype;
|
|
82
|
+
if (!prototype) throw unsupported();
|
|
83
|
+
if (prototype[INSTALLATION] !== undefined) {
|
|
84
|
+
if (prototype[INSTALLATION] !== prototype._createSimulatorSession)
|
|
85
|
+
throw unsupported();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (
|
|
89
|
+
typeof prototype._createSimulatorSession !== "function" ||
|
|
90
|
+
!FACTORY_SHAPE.test(prototype._createSimulatorSession.toString())
|
|
91
|
+
)
|
|
92
|
+
throw unsupported();
|
|
93
|
+
const dependencies = await loadSimulatorDependencies(entry);
|
|
94
|
+
const factory = function (
|
|
95
|
+
this: {
|
|
96
|
+
_llama: SimulatorBackend;
|
|
97
|
+
ggufFileInfo?: { metadata: { general: { architecture?: string } } };
|
|
98
|
+
},
|
|
99
|
+
lruCacheSize = 10
|
|
100
|
+
) {
|
|
101
|
+
return new GuardedSimulatorSession(
|
|
102
|
+
this._llama,
|
|
103
|
+
dependencies,
|
|
104
|
+
lruCacheSize,
|
|
105
|
+
this.ggufFileInfo?.metadata.general.architecture === "clip"
|
|
106
|
+
? new Error("Cannot simulate CLIP architecture models")
|
|
107
|
+
: undefined
|
|
108
|
+
);
|
|
109
|
+
};
|
|
110
|
+
Object.defineProperty(prototype, "_createSimulatorSession", {
|
|
111
|
+
configurable: true,
|
|
112
|
+
writable: true,
|
|
113
|
+
value: factory,
|
|
114
|
+
});
|
|
115
|
+
Object.defineProperty(prototype, INSTALLATION, { value: factory });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function installSimulatorLifetimeGuard(): Promise<void> {
|
|
119
|
+
installation ??= install().catch((error: unknown) => {
|
|
120
|
+
installation = undefined;
|
|
121
|
+
throw error;
|
|
122
|
+
});
|
|
123
|
+
return installation;
|
|
124
|
+
}
|