| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- /**
- * local.ts - Local llama.cpp adapter implementing EmbeddingProvider.
- *
- * Wraps an existing `LlamaCpp` instance so the legacy GGUF path looks like
- * any other EmbeddingProvider to upstream callers. Used as the default and
- * as the fallback target when `OpenAIEmbeddingsProvider` trips its breaker.
- */
- import { getDefaultLlamaCpp, } from "../llm.js";
- export class LocalLlamaCppProvider {
- kind = "local";
- llm;
- modelId;
- dimensions = undefined;
- constructor(config = {}) {
- this.llm = config.llm ?? getDefaultLlamaCpp();
- this.modelId = config.modelId ?? "embeddinggemma";
- }
- getModelId() {
- return this.modelId;
- }
- getDimensions() {
- return this.dimensions;
- }
- async healthcheck(_signal) {
- // For the local provider, "healthy" means the embed model loads.
- // We probe with a single embed call.
- try {
- const result = await this.llm.embed("healthcheck", { model: this.modelId });
- if (!result) {
- return {
- ok: false,
- model: this.modelId,
- detail: "embed probe returned null",
- };
- }
- this.dimensions = result.embedding.length;
- return {
- ok: true,
- model: this.modelId,
- dimensions: this.dimensions,
- detail: `local llama.cpp ready, ${this.dimensions}-d`,
- };
- }
- catch (err) {
- return {
- ok: false,
- model: this.modelId,
- detail: err instanceof Error ? err.message : String(err),
- };
- }
- }
- async embed(text, options = {}) {
- if (options.signal?.aborted)
- return null;
- const result = await this.llm.embed(text, { model: options.model ?? this.modelId });
- if (!result)
- return null;
- if (this.dimensions === undefined) {
- this.dimensions = result.embedding.length;
- }
- return {
- embedding: result.embedding,
- model: this.modelId,
- };
- }
- async embedBatch(texts, options = {}) {
- if (texts.length === 0)
- return [];
- if (options.signal?.aborted)
- return texts.map(() => null);
- const raw = await this.llm.embedBatch(texts, {
- model: options.model ?? this.modelId,
- });
- return raw.map((r) => {
- if (!r)
- return null;
- if (this.dimensions === undefined && r.embedding.length > 0) {
- this.dimensions = r.embedding.length;
- }
- return {
- embedding: r.embedding,
- model: this.modelId,
- };
- });
- }
- async dispose() {
- // We do NOT dispose the underlying LlamaCpp here because the singleton
- // is shared with rerank/generate/expansion paths. Disposal is handled
- // by the existing `disposeDefaultLlamaCpp()` global hook.
- }
- }
|