




















1+import os from "node:os";
2+import path from "node:path";
13import {
24createPluginRegistryFixture,
35registerVirtualTestPlugin,
@@ -21,7 +23,9 @@ import llamaCppPlugin from "./index.js";
2123import {
2224DEFAULT_LLAMA_CPP_EMBEDDING_MODEL,
2325createLlamaCppEmbeddingProvider,
26+createLlamaCppMemoryEmbeddingProvider,
2427formatLlamaCppSetupError,
28+llamaCppEmbeddingProviderAdapter,
2529} from "./src/embedding-provider.js";
26302731afterEach(() => {
@@ -106,6 +110,285 @@ describe("llama.cpp provider plugin", () => {
106110});
107111});
108112113+it("keeps the default model identity when configured with its exact cache artifact path", async () => {
114+const modelPath = path.join(
115+os.homedir(),
116+".node-llama-cpp",
117+"models",
118+"hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf",
119+);
120+memoryHostEmbeddingMocks.createLocalEmbeddingProvider.mockResolvedValue({
121+id: "local",
122+model: modelPath,
123+embedQuery: vi.fn(),
124+embedBatch: vi.fn(),
125+});
126+127+const result = await createLlamaCppMemoryEmbeddingProvider(
128+{
129+config: {},
130+provider: "local",
131+fallback: "none",
132+model: modelPath,
133+local: { modelPath },
134+},
135+{ nodeLlamaCppImportUrl: "file:///plugin/node-llama-cpp.js" },
136+);
137+138+expect(result.provider?.model).toBe(DEFAULT_LLAMA_CPP_EMBEDDING_MODEL);
139+expect(result.runtime?.cacheKeyData).toEqual({
140+provider: "local",
141+model: DEFAULT_LLAMA_CPP_EMBEDDING_MODEL,
142+});
143+expect(result.runtime?.indexIdentityAliases).toEqual([
144+{
145+model: modelPath,
146+cacheKeyData: {
147+provider: "local",
148+model: modelPath,
149+},
150+},
151+{
152+model: "hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf",
153+cacheKeyData: {
154+provider: "local",
155+model: "hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf",
156+},
157+},
158+]);
159+expect(
160+llamaCppEmbeddingProviderAdapter.resolveIndexIdentity?.({
161+config: {},
162+provider: "local",
163+model: modelPath,
164+local: { modelPath },
165+}),
166+).toEqual({
167+model: DEFAULT_LLAMA_CPP_EMBEDDING_MODEL,
168+cacheKeyData: {
169+provider: "local",
170+model: DEFAULT_LLAMA_CPP_EMBEDDING_MODEL,
171+},
172+aliases: [
173+{
174+model: modelPath,
175+cacheKeyData: {
176+provider: "local",
177+model: modelPath,
178+},
179+},
180+{
181+model: "hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf",
182+cacheKeyData: {
183+provider: "local",
184+model: "hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf",
185+},
186+},
187+],
188+});
189+expect(memoryHostEmbeddingMocks.createLocalEmbeddingProvider).toHaveBeenCalledWith(
190+expect.objectContaining({
191+model: modelPath,
192+local: { modelPath },
193+}),
194+{
195+nodeLlamaCppImportUrl: "file:///plugin/node-llama-cpp.js",
196+},
197+);
198+});
199+200+it("keeps an arbitrary same-basename model path as a distinct identity", async () => {
201+const modelPath = path.join(
202+os.tmpdir(),
203+"custom-models",
204+DEFAULT_LLAMA_CPP_EMBEDDING_MODEL.split("/").at(-1)!,
205+);
206+memoryHostEmbeddingMocks.createLocalEmbeddingProvider.mockResolvedValue({
207+id: "local",
208+model: modelPath,
209+embedQuery: vi.fn(),
210+embedBatch: vi.fn(),
211+});
212+213+const result = await createLlamaCppMemoryEmbeddingProvider(
214+{
215+config: {},
216+provider: "local",
217+fallback: "none",
218+model: modelPath,
219+local: { modelPath },
220+},
221+{ nodeLlamaCppImportUrl: "file:///plugin/node-llama-cpp.js" },
222+);
223+224+expect(result.provider?.model).toBe(modelPath);
225+expect(result.runtime?.cacheKeyData).toEqual({
226+provider: "local",
227+model: modelPath,
228+});
229+expect(result.runtime).not.toHaveProperty("indexIdentityAliases");
230+});
231+232+it("keeps a bare same-basename file in the default cache as a distinct identity", async () => {
233+const modelPath = path.join(
234+os.homedir(),
235+".node-llama-cpp",
236+"models",
237+DEFAULT_LLAMA_CPP_EMBEDDING_MODEL.split("/").at(-1)!,
238+);
239+memoryHostEmbeddingMocks.createLocalEmbeddingProvider.mockResolvedValue({
240+id: "local",
241+model: modelPath,
242+embedQuery: vi.fn(),
243+embedBatch: vi.fn(),
244+});
245+246+const result = await createLlamaCppMemoryEmbeddingProvider(
247+{
248+config: {},
249+provider: "local",
250+fallback: "none",
251+model: modelPath,
252+local: { modelPath },
253+},
254+{ nodeLlamaCppImportUrl: "file:///plugin/node-llama-cpp.js" },
255+);
256+257+expect(result.provider?.model).toBe(modelPath);
258+expect(result.runtime).not.toHaveProperty("indexIdentityAliases");
259+});
260+261+it("keeps the default model identity with a custom cache directory", async () => {
262+const modelCacheDir = path.join(os.tmpdir(), "llama-cpp-model-cache");
263+const modelPath = path.join(modelCacheDir, "hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf");
264+memoryHostEmbeddingMocks.createLocalEmbeddingProvider.mockResolvedValue({
265+id: "local",
266+model: modelPath,
267+embedQuery: vi.fn(),
268+embedBatch: vi.fn(),
269+});
270+271+const result = await createLlamaCppMemoryEmbeddingProvider(
272+{
273+config: {},
274+provider: "local",
275+fallback: "none",
276+model: DEFAULT_LLAMA_CPP_EMBEDDING_MODEL,
277+local: { modelPath: DEFAULT_LLAMA_CPP_EMBEDDING_MODEL, modelCacheDir },
278+},
279+{ nodeLlamaCppImportUrl: "file:///plugin/node-llama-cpp.js" },
280+);
281+282+expect(result.provider?.model).toBe(DEFAULT_LLAMA_CPP_EMBEDDING_MODEL);
283+expect(result.runtime?.cacheKeyData).toEqual({
284+provider: "local",
285+model: DEFAULT_LLAMA_CPP_EMBEDDING_MODEL,
286+});
287+expect(result.runtime?.indexIdentityAliases).toEqual([
288+{
289+model: modelPath,
290+cacheKeyData: {
291+provider: "local",
292+model: modelPath,
293+},
294+},
295+{
296+model: "hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf",
297+cacheKeyData: {
298+provider: "local",
299+model: "hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf",
300+},
301+},
302+]);
303+});
304+305+it.each([
306+{
307+direction: "default URI to exact relative cache artifact",
308+modelPath: DEFAULT_LLAMA_CPP_EMBEDDING_MODEL,
309+},
310+{
311+direction: "exact relative cache artifact to default URI",
312+modelPath: "hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf",
313+},
314+])("keeps $direction compatible", ({ modelPath }) => {
315+const modelCacheDir = path.join(os.tmpdir(), "llama-cpp-relative-model-cache");
316+const relativeModelPath = "hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf";
317+const resolvedModelPath = path.join(modelCacheDir, relativeModelPath);
318+319+expect(
320+llamaCppEmbeddingProviderAdapter.resolveIndexIdentity?.({
321+config: {},
322+provider: "local",
323+model: modelPath,
324+local: { modelPath, modelCacheDir },
325+}),
326+).toEqual({
327+model: DEFAULT_LLAMA_CPP_EMBEDDING_MODEL,
328+cacheKeyData: {
329+provider: "local",
330+model: DEFAULT_LLAMA_CPP_EMBEDDING_MODEL,
331+},
332+aliases: [
333+{
334+model: resolvedModelPath,
335+cacheKeyData: {
336+provider: "local",
337+model: resolvedModelPath,
338+},
339+},
340+{
341+model: relativeModelPath,
342+cacheKeyData: {
343+provider: "local",
344+model: relativeModelPath,
345+},
346+},
347+],
348+});
349+});
350+351+it("keeps the default model identity for its exact relative cache artifact", async () => {
352+const modelCacheDir = path.join(os.tmpdir(), "llama-cpp-relative-model-cache");
353+const modelPath = "hf_ggml-org_embeddinggemma-300m-qat-Q8_0.gguf";
354+const resolvedModelPath = path.join(modelCacheDir, modelPath);
355+memoryHostEmbeddingMocks.createLocalEmbeddingProvider.mockResolvedValue({
356+id: "local",
357+model: modelPath,
358+embedQuery: vi.fn(),
359+embedBatch: vi.fn(),
360+});
361+362+const result = await createLlamaCppMemoryEmbeddingProvider(
363+{
364+config: {},
365+provider: "local",
366+fallback: "none",
367+model: modelPath,
368+local: { modelPath, modelCacheDir },
369+},
370+{ nodeLlamaCppImportUrl: "file:///plugin/node-llama-cpp.js" },
371+);
372+373+expect(result.provider?.model).toBe(DEFAULT_LLAMA_CPP_EMBEDDING_MODEL);
374+expect(result.runtime?.indexIdentityAliases).toEqual([
375+{
376+model: resolvedModelPath,
377+cacheKeyData: {
378+provider: "local",
379+model: resolvedModelPath,
380+},
381+},
382+{
383+model: modelPath,
384+cacheKeyData: {
385+provider: "local",
386+model: modelPath,
387+},
388+},
389+]);
390+});
391+109392it("formats missing runtime errors with the plugin install command", () => {
110393const err = Object.assign(new Error("Cannot find package 'node-llama-cpp'"), {
111394code: "ERR_MODULE_NOT_FOUND",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。