harper-fabric-embeddings
Version:
Minimal llama.cpp embedding wrapper for Harper Fabric. Talks directly to the native addon — no build tools, no CLI, no chat wrappers.
125 lines • 5.74 kB
TypeScript
/**
* harper-fabric-embeddings
*
* Minimal llama.cpp embedding wrapper for Harper Fabric. Talks directly to
* the `@node-llama-cpp` native N-API addon — no build tools, no CLI, no chat
* wrappers, no model downloaders beyond a simple HuggingFace fetch.
*
* ~19 MB installed (native binary only) vs ~250 MB+ for node-llama-cpp.
*
* Three ways in:
* - Raw API — `init` / `embed` / `embedBatch` / `dimensions` / `dispose`
* against a module-level default engine (what harper-kb consumes).
* - Harper sub-component — `handleApplication(scope)` when loaded via
* `package:` in a parent component's config.yaml.
* - Harper models backend — the `register` factory, invoked by Harper's
* models bootstrap for `backend: harper-fabric-embeddings` config entries.
* Wires the engine into `models.embed()`, `@embed` table directives, and
* model-call analytics.
*/
import { EmbeddingEngine, type EngineOptions } from './engine.js';
export { EmbeddingEngine, decodeAndEmbed, downloadModel, renderTemplate, resolveEngineTemplates, validateTemplates, } from './engine.js';
export type { EngineOptions, EmbedManyOptions, EmbedManyResult, EmbedTemplates, LlamaContext } from './engine.js';
export { assertDeclaredPooling, readGgufPooling, POOLING_NAMES } from './gguf.js';
export type { GgufPoolingInfo, PoolingName } from './gguf.js';
/** Options for `init()`. Same shape as `EngineOptions`. */
export type InitOptions = EngineOptions;
/**
* Initialize the default embedding engine. Call once before using `embed()`.
*
* Provide either `modelPath` (absolute path to a .gguf file) or
* `modelsDir` (directory to search/download into) + optional `modelName`.
*
* Safe to call concurrently — concurrent callers share the same initialization.
* A failed attempt resets so the next call retries.
*/
export declare function init(options: InitOptions): Promise<void>;
/**
* Generate an L2-normalized embedding vector for the given text.
*
* Calls are serialized internally — concurrent callers wait in queue
* rather than hitting the llama.cpp context simultaneously.
*/
export declare function embed(text: string): Promise<number[]>;
/**
* Generate embedding vectors for multiple texts.
*
* More efficient than calling embed() in a loop — texts are processed
* sequentially through the native context without queue overhead per item.
*/
export declare function embedBatch(texts: string[]): Promise<number[][]>;
/**
* Get the embedding vector dimensionality.
*/
export declare function dimensions(): number;
/**
* Clean up native resources for the default engine.
*/
export declare function dispose(): Promise<void>;
/**
* Harper plugin hook — called on each worker thread when loaded as a
* sub-component via `package:` in the parent's config.yaml.
*
* Reads config from scope.options, initializes the GGUF engine, and
* handles close/change events for cleanup and hot-reload.
*
* Uses the module-level default engine: two sub-components loading this
* package in the same worker share one engine (the second's config is
* ignored, and either's close tears it down for both). When you need
* per-entry engines, use the models-backend `register` path instead.
*
* Config options (in parent config.yaml):
* modelName — model from the built-in registry (default: nomic-embed-text)
* modelsDir — override models directory (default: <plugin dir>/models)
* contextSize — token context window size
* batchSize — batch processing size
* threads — CPU threads for inference
* gpuLayers — layers to offload to GPU (0 = CPU only)
* addonPath — override path to llama-addon.node
* pooling — expected pooling declared by the model file (verified at init)
*/
export declare function handleApplication(scope: {
directory: string;
options: {
getAll?: () => Record<string, unknown>;
on(event: 'change', fn: () => void): void;
} & Record<string, unknown>;
on(event: 'close', fn: () => void): void;
}): Promise<void>;
/** Registration args Harper's models bootstrap passes to a backend module factory. */
export interface RegisterArgs {
/** Logical name of the config entry (`models.embedding.<name>`); callers select it via `opts.model`. */
logicalName: string;
/** `'embedding'` is the only kind this package supports. */
kind: string;
/** The env-expanded config entry from `harperdb-config.yaml`. */
config: Record<string, unknown>;
}
/**
* Harper models-backend factory. Harper's `bootstrapModels` imports this
* package when a `models:` config entry names it and invokes this export
* (a named `register` export is probed before the default export):
*
* models:
* embedding:
* default:
* backend: harper-fabric-embeddings
* modelName: nomic-embed-text
* modelsDir: ./models
*
* `modelsDir` (or `modelPath`) is required — there is no instance-root default
* on this path. `model` is accepted as an alias for `modelName`, matching the
* field Harper's built-in backends use.
*
* Registration is fast-boot: model resolution / download / load kicks off in
* the background here and the FIRST embed call awaits it (a failed attempt
* retries on the next call). Misconfiguration — wrong kind, missing model
* source, unknown model name — throws right here so Harper's bootstrap logs
* and skips the entry at boot instead of surfacing at first use.
*
* Returns the engine so tests and advanced callers can dispose it; Harper
* ignores the return value.
*/
export declare function register({ logicalName, kind, config }: RegisterArgs): Promise<EmbeddingEngine>;
export default register;
//# sourceMappingURL=index.d.ts.map