UNPKG

@claude-flow/embeddings

Version:

V3 Embedding Service - OpenAI, Transformers.js, Agentic-Flow (ONNX), Mock providers with hyperbolic embeddings, normalization, and chunking

87 lines • 3.62 kB
/** * ADR-121 Phase 21 — Content-addressed embed cache (BEYOND SOTA). * * The Phase 20 lazy router cuts feature-extraction cost by 24% on a * mixed workload — but it still pays the question-embed cost on * EVERY query, even when the same question was asked moments ago. * Production RAG has heavy repeated-query patterns (FAQs, common * queries hit thousands of times). The right fix is a * content-addressed cache: hash the (normalized) input text, look * up the cached vector, skip the embed entirely on a hit. * * This module ships: * - `EmbedCache` — in-memory LRU cache with hit/miss stats * - `wrapWithCache(embedFn, cache)` — transparent adapter that * turns any embed function into a cache-checking one * * Cache key = sha256-hex of (normalized text + dim). The dim is * mixed in so two providers with different output sizes don't * collide. Normalization: lowercase + trim + collapse internal * whitespace — matches what production cache lookups would do. * * Composes with the Phase 20 lazy router by passing * `wrapWithCache(embedFn, cache)` as the `embed` adapter. */ export interface EmbedCacheOptions { /** Max entries before LRU eviction kicks in. Default 1000. */ readonly maxEntries?: number; /** Vector dimension — mixed into the cache key. Default auto-detected on first set. */ readonly dimension?: number; } export interface EmbedCacheStats { readonly entries: number; readonly maxEntries: number; readonly hits: number; readonly misses: number; /** Total lookups (hits + misses). */ readonly lookups: number; /** Hit rate in [0, 1]. */ readonly hitRate: number; /** Total bytes occupied by cached vectors (best-effort estimate). */ readonly approxByteSize: number; } /** * In-memory LRU cache for embeddings. The cache key is the sha256 * hex of the canonicalized text + dim — so two distinct text bodies * never collide and the same text always lands on the same key. * * Cache state is process-local. For cross-process sharing use * `PersistentEmbeddingCache` from `persistent-cache.ts`. */ export declare class EmbedCache { private readonly maxEntries; private dim; private readonly store; private hits; private misses; constructor(options?: EmbedCacheOptions); /** * Compute the cache key for a text + dim pair. Exposed for * testing + so the lazy router can pre-key lookups. */ keyFor(text: string, dimension: number): string; get(text: string): Float32Array | undefined; set(text: string, vector: Float32Array | number[]): void; has(text: string): boolean; /** Clear all entries; reset stats. */ reset(): void; stats(): EmbedCacheStats; } /** * Canonicalize text for stable cache key derivation: trim, collapse * internal whitespace, lowercase. Identical to what production cache * lookups should do — "how does AUTH work?" and "how does auth work?" * should hit the same cache entry. */ export declare function canonicalizeText(text: string): string; /** * Wrap an async embed function with a cache-checking adapter. On * cache hit, returns the cached vector without calling the wrapped * embedder. On miss, calls the wrapped embedder and stores the * result. * * The returned function has the same signature as the input function * so it can be passed to any router as a drop-in replacement. */ export declare function wrapWithCache(embedder: (text: string) => Promise<Float32Array | number[]>, cache: EmbedCache): (text: string) => Promise<Float32Array>; //# sourceMappingURL=embed-cache.d.ts.map