localm-web 0.2.0 → 0.4.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/CHANGELOG.md +88 -0
- package/README.md +15 -3
- package/dist/assets/{inference.worker-CwvQtobb.js → inference.worker-DZbXKJZY.js} +49 -5
- package/dist/assets/inference.worker-DZbXKJZY.js.map +1 -0
- package/dist/index.d.ts +362 -5
- package/dist/index.js +381 -7
- package/dist/index.js.map +1 -1
- package/package.json +8 -1
- package/dist/assets/inference.worker-CwvQtobb.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -30,6 +30,43 @@ class QuotaExceededError extends LocalmWebError {
|
|
|
30
30
|
}
|
|
31
31
|
class BackendNotAvailableError extends LocalmWebError {
|
|
32
32
|
}
|
|
33
|
+
class StructuredOutputError extends LocalmWebError {
|
|
34
|
+
}
|
|
35
|
+
function assertJsonSchema(schema) {
|
|
36
|
+
if (schema === null || typeof schema !== "object" || Array.isArray(schema)) {
|
|
37
|
+
throw new StructuredOutputError("jsonSchema must be a plain object describing a JSON Schema.");
|
|
38
|
+
}
|
|
39
|
+
const keys = Object.keys(schema);
|
|
40
|
+
const recognized = [
|
|
41
|
+
"type",
|
|
42
|
+
"$ref",
|
|
43
|
+
"oneOf",
|
|
44
|
+
"anyOf",
|
|
45
|
+
"allOf",
|
|
46
|
+
"enum",
|
|
47
|
+
"const",
|
|
48
|
+
"properties"
|
|
49
|
+
];
|
|
50
|
+
if (!keys.some((key) => recognized.includes(key))) {
|
|
51
|
+
throw new StructuredOutputError(
|
|
52
|
+
"jsonSchema does not look like a JSON Schema (missing type/$ref/oneOf/anyOf/allOf/enum/const/properties)."
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function serializeJsonSchema(schema) {
|
|
57
|
+
assertJsonSchema(schema);
|
|
58
|
+
return JSON.stringify(schema);
|
|
59
|
+
}
|
|
60
|
+
function parseStructuredOutput(text) {
|
|
61
|
+
try {
|
|
62
|
+
return JSON.parse(text);
|
|
63
|
+
} catch (err) {
|
|
64
|
+
throw new StructuredOutputError(
|
|
65
|
+
"Engine output is not valid JSON. The model may have ignored the constrained decoding directive.",
|
|
66
|
+
err
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
33
70
|
let webllmModulePromise = null;
|
|
34
71
|
async function loadWebLLM() {
|
|
35
72
|
if (!webllmModulePromise) {
|
|
@@ -47,6 +84,15 @@ function buildSamplingParams(options) {
|
|
|
47
84
|
if (options.topP !== void 0) params.top_p = options.topP;
|
|
48
85
|
return params;
|
|
49
86
|
}
|
|
87
|
+
function buildResponseFormat(options) {
|
|
88
|
+
if (options.jsonSchema !== void 0) {
|
|
89
|
+
return { type: "json_object", schema: serializeJsonSchema(options.jsonSchema) };
|
|
90
|
+
}
|
|
91
|
+
if (options.json) {
|
|
92
|
+
return { type: "json_object" };
|
|
93
|
+
}
|
|
94
|
+
return void 0;
|
|
95
|
+
}
|
|
50
96
|
function toChatMessages(messages) {
|
|
51
97
|
return messages.map((m) => {
|
|
52
98
|
switch (m.role) {
|
|
@@ -101,10 +147,12 @@ class WebLLMEngine {
|
|
|
101
147
|
if (options.signal?.aborted) {
|
|
102
148
|
throw new GenerationAbortedError("Generation aborted before start.");
|
|
103
149
|
}
|
|
150
|
+
const responseFormat = buildResponseFormat(options);
|
|
104
151
|
const completion = await engine.chat.completions.create({
|
|
105
152
|
...buildSamplingParams(options),
|
|
106
153
|
messages: toChatMessages(messages),
|
|
107
|
-
stream: false
|
|
154
|
+
stream: false,
|
|
155
|
+
...responseFormat ? { response_format: responseFormat } : {}
|
|
108
156
|
});
|
|
109
157
|
return completion.choices[0]?.message?.content ?? "";
|
|
110
158
|
}
|
|
@@ -113,10 +161,12 @@ class WebLLMEngine {
|
|
|
113
161
|
if (options.signal?.aborted) {
|
|
114
162
|
throw new GenerationAbortedError("Generation aborted before start.");
|
|
115
163
|
}
|
|
164
|
+
const responseFormat = buildResponseFormat(options);
|
|
116
165
|
const completion = await engine.chat.completions.create({
|
|
117
166
|
...buildSamplingParams(options),
|
|
118
167
|
messages: toChatMessages(messages),
|
|
119
|
-
stream: true
|
|
168
|
+
stream: true,
|
|
169
|
+
...responseFormat ? { response_format: responseFormat } : {}
|
|
120
170
|
});
|
|
121
171
|
let index = 0;
|
|
122
172
|
let finished = false;
|
|
@@ -150,10 +200,12 @@ class WebLLMEngine {
|
|
|
150
200
|
if (options.signal?.aborted) {
|
|
151
201
|
throw new GenerationAbortedError("Generation aborted before start.");
|
|
152
202
|
}
|
|
203
|
+
const responseFormat = buildResponseFormat(options);
|
|
153
204
|
const completion = await engine.completions.create({
|
|
154
205
|
...buildSamplingParams(options),
|
|
155
206
|
prompt,
|
|
156
|
-
stream: false
|
|
207
|
+
stream: false,
|
|
208
|
+
...responseFormat ? { response_format: responseFormat } : {}
|
|
157
209
|
});
|
|
158
210
|
return completion.choices[0]?.text ?? "";
|
|
159
211
|
}
|
|
@@ -162,10 +214,12 @@ class WebLLMEngine {
|
|
|
162
214
|
if (options.signal?.aborted) {
|
|
163
215
|
throw new GenerationAbortedError("Generation aborted before start.");
|
|
164
216
|
}
|
|
217
|
+
const responseFormat = buildResponseFormat(options);
|
|
165
218
|
const completion = await engine.completions.create({
|
|
166
219
|
...buildSamplingParams(options),
|
|
167
220
|
prompt,
|
|
168
|
-
stream: true
|
|
221
|
+
stream: true,
|
|
222
|
+
...responseFormat ? { response_format: responseFormat } : {}
|
|
169
223
|
});
|
|
170
224
|
let index = 0;
|
|
171
225
|
let finished = false;
|
|
@@ -524,10 +578,66 @@ function resolveModelPreset(modelId) {
|
|
|
524
578
|
function listSupportedModels() {
|
|
525
579
|
return Object.keys(MODEL_PRESETS);
|
|
526
580
|
}
|
|
581
|
+
const EMBEDDING_PRESETS = Object.freeze({
|
|
582
|
+
"bge-small-en-v1.5": {
|
|
583
|
+
id: "bge-small-en-v1.5",
|
|
584
|
+
family: "BGE",
|
|
585
|
+
dimension: 384,
|
|
586
|
+
maxTokens: 512,
|
|
587
|
+
transformersId: "Xenova/bge-small-en-v1.5",
|
|
588
|
+
quantization: "fp32",
|
|
589
|
+
description: "BAAI BGE small English v1.5, 384-dim sentence embeddings."
|
|
590
|
+
},
|
|
591
|
+
"bge-base-en-v1.5": {
|
|
592
|
+
id: "bge-base-en-v1.5",
|
|
593
|
+
family: "BGE",
|
|
594
|
+
dimension: 768,
|
|
595
|
+
maxTokens: 512,
|
|
596
|
+
transformersId: "Xenova/bge-base-en-v1.5",
|
|
597
|
+
quantization: "fp32",
|
|
598
|
+
description: "BAAI BGE base English v1.5, 768-dim sentence embeddings."
|
|
599
|
+
}
|
|
600
|
+
});
|
|
601
|
+
function resolveEmbeddingPreset(modelId) {
|
|
602
|
+
const preset = EMBEDDING_PRESETS[modelId];
|
|
603
|
+
if (!preset) {
|
|
604
|
+
const available = Object.keys(EMBEDDING_PRESETS).join(", ");
|
|
605
|
+
throw new UnknownModelError(
|
|
606
|
+
`Unknown embedding model "${modelId}". Available models: ${available}.`
|
|
607
|
+
);
|
|
608
|
+
}
|
|
609
|
+
return preset;
|
|
610
|
+
}
|
|
611
|
+
function listSupportedEmbeddingModels() {
|
|
612
|
+
return Object.keys(EMBEDDING_PRESETS);
|
|
613
|
+
}
|
|
614
|
+
const RERANKER_PRESETS = Object.freeze({
|
|
615
|
+
"bge-reranker-base": {
|
|
616
|
+
id: "bge-reranker-base",
|
|
617
|
+
family: "BGE Reranker",
|
|
618
|
+
maxTokens: 512,
|
|
619
|
+
transformersId: "Xenova/bge-reranker-base",
|
|
620
|
+
quantization: "fp32",
|
|
621
|
+
description: "BAAI BGE reranker base — multilingual cross-encoder."
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
function resolveRerankerPreset(modelId) {
|
|
625
|
+
const preset = RERANKER_PRESETS[modelId];
|
|
626
|
+
if (!preset) {
|
|
627
|
+
const available = Object.keys(RERANKER_PRESETS).join(", ");
|
|
628
|
+
throw new UnknownModelError(
|
|
629
|
+
`Unknown reranker model "${modelId}". Available models: ${available}.`
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
return preset;
|
|
633
|
+
}
|
|
634
|
+
function listSupportedRerankerModels() {
|
|
635
|
+
return Object.keys(RERANKER_PRESETS);
|
|
636
|
+
}
|
|
527
637
|
function createInferenceWorker() {
|
|
528
638
|
return new Worker(new URL(
|
|
529
639
|
/* @vite-ignore */
|
|
530
|
-
"/assets/inference.worker-
|
|
640
|
+
"/assets/inference.worker-DZbXKJZY.js",
|
|
531
641
|
import.meta.url
|
|
532
642
|
), {
|
|
533
643
|
type: "module"
|
|
@@ -555,7 +665,8 @@ class LMTask {
|
|
|
555
665
|
return { engine, preset };
|
|
556
666
|
}
|
|
557
667
|
static defaultEngine(options) {
|
|
558
|
-
|
|
668
|
+
const useWorker = options.inWorker ?? true;
|
|
669
|
+
if (useWorker) {
|
|
559
670
|
return new WorkerEngine(createInferenceWorker());
|
|
560
671
|
}
|
|
561
672
|
return new WebLLMEngine();
|
|
@@ -576,6 +687,20 @@ class ChatReply {
|
|
|
576
687
|
this.tokensGenerated = tokensGenerated;
|
|
577
688
|
this.finishReason = finishReason;
|
|
578
689
|
}
|
|
690
|
+
/**
|
|
691
|
+
* Parse {@link ChatReply.text} as JSON.
|
|
692
|
+
*
|
|
693
|
+
* Intended for replies generated with `json: true` or `jsonSchema`.
|
|
694
|
+
* The result is cast to `T` without runtime validation; pair with Zod /
|
|
695
|
+
* Ajv on the call site if you need to verify the schema.
|
|
696
|
+
*
|
|
697
|
+
* @typeParam T - Expected parsed shape.
|
|
698
|
+
* @returns The parsed JSON value.
|
|
699
|
+
* @throws StructuredOutputError if the text is not valid JSON.
|
|
700
|
+
*/
|
|
701
|
+
json() {
|
|
702
|
+
return parseStructuredOutput(this.text);
|
|
703
|
+
}
|
|
579
704
|
}
|
|
580
705
|
class CompletionResult {
|
|
581
706
|
constructor(text, prompt, tokensGenerated, finishReason) {
|
|
@@ -584,6 +709,19 @@ class CompletionResult {
|
|
|
584
709
|
this.tokensGenerated = tokensGenerated;
|
|
585
710
|
this.finishReason = finishReason;
|
|
586
711
|
}
|
|
712
|
+
/**
|
|
713
|
+
* Parse {@link CompletionResult.text} as JSON.
|
|
714
|
+
*
|
|
715
|
+
* Intended for completions generated with `json: true` or `jsonSchema`.
|
|
716
|
+
* The result is cast to `T` without runtime validation.
|
|
717
|
+
*
|
|
718
|
+
* @typeParam T - Expected parsed shape.
|
|
719
|
+
* @returns The parsed JSON value.
|
|
720
|
+
* @throws StructuredOutputError if the text is not valid JSON.
|
|
721
|
+
*/
|
|
722
|
+
json() {
|
|
723
|
+
return parseStructuredOutput(this.text);
|
|
724
|
+
}
|
|
587
725
|
}
|
|
588
726
|
class Chat extends LMTask {
|
|
589
727
|
history = [];
|
|
@@ -702,6 +840,230 @@ class Completion extends LMTask {
|
|
|
702
840
|
}
|
|
703
841
|
}
|
|
704
842
|
}
|
|
843
|
+
let transformersModulePromise$1 = null;
|
|
844
|
+
async function loadTransformers$1() {
|
|
845
|
+
if (!transformersModulePromise$1) {
|
|
846
|
+
transformersModulePromise$1 = import("@huggingface/transformers");
|
|
847
|
+
}
|
|
848
|
+
return transformersModulePromise$1;
|
|
849
|
+
}
|
|
850
|
+
async function buildDefaultPipeline$1(preset, onProgress) {
|
|
851
|
+
const transformers = await loadTransformers$1();
|
|
852
|
+
try {
|
|
853
|
+
const pipe = await transformers.pipeline("feature-extraction", preset.transformersId, {
|
|
854
|
+
progress_callback: (report) => {
|
|
855
|
+
if (!onProgress) return;
|
|
856
|
+
const r = report;
|
|
857
|
+
onProgress({
|
|
858
|
+
progress: typeof r.progress === "number" ? r.progress / 100 : 0,
|
|
859
|
+
text: r.status ?? "",
|
|
860
|
+
loaded: 0,
|
|
861
|
+
total: 0,
|
|
862
|
+
phase: "downloading"
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
});
|
|
866
|
+
return {
|
|
867
|
+
async embed(texts, options) {
|
|
868
|
+
const output = await pipe(texts, {
|
|
869
|
+
pooling: options.pooling,
|
|
870
|
+
normalize: options.normalize
|
|
871
|
+
});
|
|
872
|
+
return output.tolist();
|
|
873
|
+
},
|
|
874
|
+
async unload() {
|
|
875
|
+
if (typeof pipe.dispose === "function") {
|
|
876
|
+
await pipe.dispose();
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
} catch (err) {
|
|
881
|
+
throw new ModelLoadError(`Failed to load embedding model "${preset.id}".`, err);
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
class Embeddings {
|
|
885
|
+
constructor(pipeline, preset) {
|
|
886
|
+
this.pipeline = pipeline;
|
|
887
|
+
this.preset = preset;
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Create and load an `Embeddings` task for the given model.
|
|
891
|
+
*
|
|
892
|
+
* @param modelId - Friendly id from the embedding registry.
|
|
893
|
+
* @param options - Optional creation options.
|
|
894
|
+
* @throws UnknownModelError if `modelId` is not in the registry.
|
|
895
|
+
* @throws ModelLoadError if the underlying pipeline fails to load.
|
|
896
|
+
*/
|
|
897
|
+
static async create(modelId, options = {}) {
|
|
898
|
+
const preset = resolveEmbeddingPreset(modelId);
|
|
899
|
+
const pipeline = options.pipeline ?? await buildDefaultPipeline$1(preset, options.onProgress);
|
|
900
|
+
return new Embeddings(pipeline, preset);
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* Encode an array of strings into dense vectors.
|
|
904
|
+
*
|
|
905
|
+
* Returns one vector per input, in the same order. Empty input array
|
|
906
|
+
* returns an empty array (no error).
|
|
907
|
+
*
|
|
908
|
+
* @param texts - Input strings.
|
|
909
|
+
* @param options - Pooling + normalization. Defaults: `pooling: "mean"`, `normalize: true`.
|
|
910
|
+
*/
|
|
911
|
+
async embed(texts, options = {}) {
|
|
912
|
+
if (texts.length === 0) return [];
|
|
913
|
+
if (!this.pipeline) {
|
|
914
|
+
throw new ModelNotLoadedError("Embeddings pipeline not initialized.");
|
|
915
|
+
}
|
|
916
|
+
const merged = {
|
|
917
|
+
normalize: options.normalize ?? true,
|
|
918
|
+
pooling: options.pooling ?? "mean"
|
|
919
|
+
};
|
|
920
|
+
return this.pipeline.embed(texts, merged);
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Convenience: encode a single string and return its vector.
|
|
924
|
+
*
|
|
925
|
+
* @param text - Input string.
|
|
926
|
+
* @param options - Forwarded to {@link Embeddings.embed}.
|
|
927
|
+
*/
|
|
928
|
+
async embedSingle(text, options = {}) {
|
|
929
|
+
const [vec] = await this.embed([text], options);
|
|
930
|
+
if (!vec) {
|
|
931
|
+
throw new ModelLoadError("Embedding pipeline returned no result.");
|
|
932
|
+
}
|
|
933
|
+
return vec;
|
|
934
|
+
}
|
|
935
|
+
/** Embedding dimension exposed by the loaded model. */
|
|
936
|
+
get dimension() {
|
|
937
|
+
return this.preset.dimension;
|
|
938
|
+
}
|
|
939
|
+
/** Release pipeline resources. Safe to call multiple times. */
|
|
940
|
+
async unload() {
|
|
941
|
+
await this.pipeline.unload?.();
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
let transformersModulePromise = null;
|
|
945
|
+
async function loadTransformers() {
|
|
946
|
+
if (!transformersModulePromise) {
|
|
947
|
+
transformersModulePromise = import("@huggingface/transformers");
|
|
948
|
+
}
|
|
949
|
+
return transformersModulePromise;
|
|
950
|
+
}
|
|
951
|
+
function sigmoidValue(x) {
|
|
952
|
+
return 1 / (1 + Math.exp(-x));
|
|
953
|
+
}
|
|
954
|
+
async function buildDefaultPipeline(preset, onProgress) {
|
|
955
|
+
const transformers = await loadTransformers();
|
|
956
|
+
try {
|
|
957
|
+
const tokenizer = await transformers.AutoTokenizer.from_pretrained(preset.transformersId, {
|
|
958
|
+
progress_callback: (report) => {
|
|
959
|
+
if (!onProgress) return;
|
|
960
|
+
const r = report;
|
|
961
|
+
onProgress({
|
|
962
|
+
progress: typeof r.progress === "number" ? r.progress / 100 : 0,
|
|
963
|
+
text: r.status ?? "",
|
|
964
|
+
loaded: 0,
|
|
965
|
+
total: 0,
|
|
966
|
+
phase: "downloading"
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
const model = await transformers.AutoModelForSequenceClassification.from_pretrained(
|
|
971
|
+
preset.transformersId,
|
|
972
|
+
{
|
|
973
|
+
progress_callback: (report) => {
|
|
974
|
+
if (!onProgress) return;
|
|
975
|
+
const r = report;
|
|
976
|
+
onProgress({
|
|
977
|
+
progress: typeof r.progress === "number" ? r.progress / 100 : 0,
|
|
978
|
+
text: r.status ?? "",
|
|
979
|
+
loaded: 0,
|
|
980
|
+
total: 0,
|
|
981
|
+
phase: "downloading"
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
);
|
|
986
|
+
return {
|
|
987
|
+
async score(query, docs) {
|
|
988
|
+
if (docs.length === 0) return [];
|
|
989
|
+
const queries = docs.map(() => query);
|
|
990
|
+
const tokenize = tokenizer;
|
|
991
|
+
const inputs = tokenize(queries, {
|
|
992
|
+
text_pair: docs,
|
|
993
|
+
padding: true,
|
|
994
|
+
truncation: true,
|
|
995
|
+
max_length: preset.maxTokens
|
|
996
|
+
});
|
|
997
|
+
const callModel = model;
|
|
998
|
+
const outputs = await callModel(inputs);
|
|
999
|
+
const logits = outputs.logits.tolist();
|
|
1000
|
+
return logits.map((row) => row[0] ?? 0);
|
|
1001
|
+
},
|
|
1002
|
+
async unload() {
|
|
1003
|
+
const m = model;
|
|
1004
|
+
if (typeof m.dispose === "function") await m.dispose();
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
} catch (err) {
|
|
1008
|
+
throw new ModelLoadError(`Failed to load reranker model "${preset.id}".`, err);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
class Reranker {
|
|
1012
|
+
constructor(pipeline, preset) {
|
|
1013
|
+
this.pipeline = pipeline;
|
|
1014
|
+
this.preset = preset;
|
|
1015
|
+
}
|
|
1016
|
+
/**
|
|
1017
|
+
* Create and load a `Reranker` task for the given model.
|
|
1018
|
+
*
|
|
1019
|
+
* @param modelId - Friendly id from the reranker registry.
|
|
1020
|
+
* @param options - Optional creation options.
|
|
1021
|
+
* @throws UnknownModelError if `modelId` is not in the registry.
|
|
1022
|
+
* @throws ModelLoadError if the underlying pipeline fails to load.
|
|
1023
|
+
*/
|
|
1024
|
+
static async create(modelId, options = {}) {
|
|
1025
|
+
const preset = resolveRerankerPreset(modelId);
|
|
1026
|
+
const pipeline = options.pipeline ?? await buildDefaultPipeline(preset, options.onProgress);
|
|
1027
|
+
return new Reranker(pipeline, preset);
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* Score each document against the query. Returns one score per doc, in
|
|
1031
|
+
* the same order. Empty `docs` returns `[]` (no error).
|
|
1032
|
+
*
|
|
1033
|
+
* @param query - Query string.
|
|
1034
|
+
* @param docs - Documents to score.
|
|
1035
|
+
* @param options - `sigmoid: true` maps logits into `[0, 1]`.
|
|
1036
|
+
*/
|
|
1037
|
+
async score(query, docs, options = {}) {
|
|
1038
|
+
if (docs.length === 0) return [];
|
|
1039
|
+
if (!this.pipeline) {
|
|
1040
|
+
throw new ModelNotLoadedError("Reranker pipeline not initialized.");
|
|
1041
|
+
}
|
|
1042
|
+
const raw = await this.pipeline.score(query, docs);
|
|
1043
|
+
return options.sigmoid ? raw.map(sigmoidValue) : raw;
|
|
1044
|
+
}
|
|
1045
|
+
/**
|
|
1046
|
+
* Score and sort documents by score in descending order. Returns a list of
|
|
1047
|
+
* {@link RankedDocument}s carrying the original index.
|
|
1048
|
+
*
|
|
1049
|
+
* @param query - Query string.
|
|
1050
|
+
* @param docs - Documents to rank.
|
|
1051
|
+
* @param options - Forwarded to {@link Reranker.score}.
|
|
1052
|
+
*/
|
|
1053
|
+
async rank(query, docs, options = {}) {
|
|
1054
|
+
const scores = await this.score(query, docs, options);
|
|
1055
|
+
const ranked = scores.map((score, index) => {
|
|
1056
|
+
const text = docs[index] ?? "";
|
|
1057
|
+
return { text, score, index };
|
|
1058
|
+
});
|
|
1059
|
+
ranked.sort((a, b) => b.score - a.score);
|
|
1060
|
+
return ranked;
|
|
1061
|
+
}
|
|
1062
|
+
/** Release pipeline resources. Safe to call multiple times. */
|
|
1063
|
+
async unload() {
|
|
1064
|
+
await this.pipeline.unload?.();
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
705
1067
|
let webllmCachePromise = null;
|
|
706
1068
|
async function loadWebLLMCacheHelpers() {
|
|
707
1069
|
if (!webllmCachePromise) {
|
|
@@ -823,13 +1185,15 @@ async function* tap(stream, onChunk) {
|
|
|
823
1185
|
yield chunk;
|
|
824
1186
|
}
|
|
825
1187
|
}
|
|
826
|
-
const VERSION = "0.
|
|
1188
|
+
const VERSION = "0.4.0";
|
|
827
1189
|
export {
|
|
828
1190
|
BackendNotAvailableError,
|
|
829
1191
|
Chat,
|
|
830
1192
|
ChatReply,
|
|
831
1193
|
Completion,
|
|
832
1194
|
CompletionResult,
|
|
1195
|
+
EMBEDDING_PRESETS,
|
|
1196
|
+
Embeddings,
|
|
833
1197
|
GenerationAbortedError,
|
|
834
1198
|
LMTask,
|
|
835
1199
|
LocalmWebError,
|
|
@@ -838,14 +1202,24 @@ export {
|
|
|
838
1202
|
ModelLoadError,
|
|
839
1203
|
ModelNotLoadedError,
|
|
840
1204
|
QuotaExceededError,
|
|
1205
|
+
RERANKER_PRESETS,
|
|
1206
|
+
Reranker,
|
|
1207
|
+
StructuredOutputError,
|
|
841
1208
|
UnknownModelError,
|
|
842
1209
|
VERSION,
|
|
843
1210
|
WebGPUUnavailableError,
|
|
844
1211
|
WorkerEngine,
|
|
1212
|
+
assertJsonSchema,
|
|
845
1213
|
collectStream,
|
|
846
1214
|
createInferenceWorker,
|
|
1215
|
+
listSupportedEmbeddingModels,
|
|
847
1216
|
listSupportedModels,
|
|
1217
|
+
listSupportedRerankerModels,
|
|
1218
|
+
parseStructuredOutput,
|
|
1219
|
+
resolveEmbeddingPreset,
|
|
848
1220
|
resolveModelPreset,
|
|
1221
|
+
resolveRerankerPreset,
|
|
1222
|
+
serializeJsonSchema,
|
|
849
1223
|
tap
|
|
850
1224
|
};
|
|
851
1225
|
//# sourceMappingURL=index.js.map
|