/** * Cosine similarity between two equal-length vectors, in the range [-1, 1] * (1 = identical direction, 0 = orthogonal). This is the standard relevance * score for embedding retrieval — magnitude-invariant, so vectors need not be * pre-normalized. * * @throws if the vectors are different lengths (a dimension mismatch — usually a * sign the vectors came from different embedding models). */ export declare function cosineSimilarity(a: number[], b: number[]): number; /** Options for {@link chunkText}. */ export type ChunkOptions = { /** * Target size of each chunk, in characters. New content per chunk is capped at * this; `overlap` is added on top. Default 1000. */ chunkSize?: number; /** * Characters of trailing context repeated at the start of the next chunk, so a * fact split across a boundary still appears whole in at least one chunk. * Must be in `[0, chunkSize)`. Defaults to `min(200, chunkSize / 5)`. */ overlap?: number; }; /** * Split a long document into overlapping, embeddable chunks. * * Splitting happens on sentence/paragraph boundaries where possible (so chunks * read coherently), greedily packing segments up to `chunkSize` with `overlap` * characters of context carried into the next chunk. A single segment longer * than `chunkSize` (e.g. a giant unbroken line) is hard-split on character * windows. Returns `[]` for empty/whitespace input, and a single chunk for input * already within `chunkSize`. * * `chunkSize` bounds *new* content per chunk; with `overlap > 0` a chunk's total * length can exceed it by up to `overlap`. Tune to your embedder's context limit. * * @example * ```ts * const chunks = chunkText(longDoc, { chunkSize: 800, overlap: 100 }); * const { embeddings } = await embed(chunks); * chunks.forEach((text, i) => store.add(`doc:${i}`, embeddings[i], { text })); * ``` */ export declare function chunkText(text: string, options?: ChunkOptions): string[]; /** A vector plus its id and optional caller-defined metadata (e.g. the source text). */ export type VectorRecord = { /** Caller-chosen unique id. Re-adding the same id overwrites the record. */ id: string; /** The embedding vector. */ vector: number[]; /** Anything you want to carry alongside — typically the chunk text, a source URL, etc. */ metadata?: M; }; /** A {@link VectorRecord} returned from a search, with its similarity to the query. */ export type VectorSearchResult = VectorRecord & { /** Cosine similarity to the query vector, in [-1, 1]. Higher is more relevant. */ score: number; }; /** Options for {@link VectorStore.search}. */ export type VectorSearchOptions = { /** Maximum number of results to return, highest score first. Default 10. */ topK?: number; /** Drop results scoring below this cosine similarity. */ minScore?: number; }; /** * A lightweight in-memory vector store: add records, then `search` by a query * vector to get the top-k most similar. See {@link createVectorStore}. */ export type VectorStore = { /** Add (or overwrite, by id) a single record. The vector is copied defensively. */ add(id: string, vector: number[], metadata?: M): void; /** Add many records at once. */ addMany(records: VectorRecord[]): void; /** Get a record by id, or `undefined`. */ get(id: string): VectorRecord | undefined; /** Remove a record by id. Returns `true` if one was removed. */ remove(id: string): boolean; /** Remove every record. */ clear(): void; /** Number of records currently stored. */ readonly size: number; /** * Return the records most similar to `query`, by cosine similarity, highest * first. Bounded by `topK` (default 10) and filtered by `minScore` if given. */ search(query: number[], options?: VectorSearchOptions): VectorSearchResult[]; /** * A plain-array snapshot of every record. Persist it (e.g. to AsyncStorage or a * file) and rehydrate later with `createVectorStore(snapshot)` — the store * deliberately owns no I/O, so persistence stays yours. */ toJSON(): VectorRecord[]; }; /** * Create an in-memory {@link VectorStore}, optionally seeded from a snapshot * previously produced by {@link VectorStore.toJSON}. * * It's intentionally minimal — a linear scan over the records on each `search`. * That's more than fast enough for the thousands-of-chunks scale typical of * on-device RAG; reach for a real vector DB only past that. * * @example * ```ts * const store = createVectorStore<{ text: string }>(); * store.addMany(chunks.map((text, i) => ({ id: `c${i}`, vector: embeddings[i], metadata: { text } }))); * * const [{ embeddings: [q] }] = [await embed([question])]; * const hits = store.search(q, { topK: 4 }); * const context = hits.map((h) => h.metadata!.text).join('\n\n'); * // …feed `context` into sendMessage / generateText * ``` */ export declare function createVectorStore(initial?: VectorRecord[]): VectorStore; //# sourceMappingURL=rag.d.ts.map