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.89 kB
/** * ADR-121 Phase 12 — Embedding-level fusion (HyDE). * * HyDE (Hypothetical Document Embeddings — Gao, Ma, Lin, Callan 2022, * "Precise Zero-Shot Dense Retrieval without Relevance Labels") fixes * a structural problem with question-based dense retrieval: question * embeddings live in "question space" while documents embed into * "answer space", so cosine similarity systematically underweights * relevant docs whose surface form differs from the question. * * The HyDE recipe: * 1. Have an LLM generate N hypothetical answers to the question. * 2. Embed each hypothetical answer. * 3. Average those embeddings into a single query vector. * 4. Search with the averaged vector. * * Empirically: this single transform produces SOTA zero-shot * retrieval on BEIR — beating supervised in-domain dense retrievers * on many tasks. The trick works because hypothetical answers live * in the same answer-space as the corpus, so the averaged vector * lands near the true relevant docs. * * This module ships the **averaging** step as a pure function — the * LLM-generation step is the caller's job (the orchestrator agent * already has an LLM). Composes with every existing retrieval shape: * * HyDE + plain search = embeddings_search_text_hyde * HyDE + MMR rerank = caller-composable (search_text_hyde * results piped through mmrRerank) * HyDE + RRF ensemble = caller-composable (search_text_hyde * across multiple LLM samples, fused) * * Relationship to RRF (Phase 11): * - RRF fuses at the **rank** level: N searches, merge ranks. More * expensive but preserves intent boundaries between variants. * - HyDE/avg fuses at the **embedding** level: 1 search after vector * average. Cheaper but interpolates between variants — the * averaged vector represents the "centroid" intent. * * The two are complementary, not redundant. Production systems * often use HyDE inside one ranked list, and RRF across multiple * ranked lists (one HyDE-search, one BM25-search, etc.). */ export interface AverageEmbeddingsOptions { /** * Per-vector weights. Length must equal vectors.length. * Defaults to uniform = 1 each. * * Use weights when the caller has confidence signals — e.g. weight * the user's original question 0.5× and the LLM's hypothetical * answers 1.0× each, so the answers dominate (the HyDE paper's * default recipe). */ readonly weights?: ReadonlyArray<number>; /** * L2-normalize each input vector BEFORE averaging. Default true. * * This is the standard HyDE recipe — without it, vectors with * larger norms dominate the average regardless of their semantic * weight. Set to false only if you already pre-normalized * (cheaper) or if you specifically want norm-weighted averaging. */ readonly normalizeInputs?: boolean; /** * L2-normalize the OUTPUT averaged vector. Default true. * * Required for cosine-similarity search backings (HNSW with * cosine, RaBitQ, DiskANN). The math: avg of unit vectors is not * itself a unit vector. */ readonly normalizeOutput?: boolean; } /** * Average N embedding vectors into a single embedding vector. * * Time complexity: O(N · dim). Memory: O(dim). * * Returns a brand-new Float32Array — does not mutate inputs. */ export declare function averageEmbeddings(vectors: ReadonlyArray<Float32Array | number[]>, options?: AverageEmbeddingsOptions): Float32Array; /** * Convenience: confirm a Float32Array is L2-unit-normalized within * `tolerance`. Useful for tests + the smoke driver to verify the * normalizeOutput contract. */ export declare function isUnitNorm(v: Float32Array, tolerance?: number): boolean; //# sourceMappingURL=embedding-fusion.d.ts.map