@dudousxd/nestjs-agent-rag 0.10.3 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Passage, Retriever, EmbeddingProvider, RetrieveOptions, Reranker, ToolSpec, ToolHandler } from '@dudousxd/nestjs-agent-core';
1
+ import { Passage, Retriever, EmbeddingProvider, RetrieveOptions, Reranker, ToolSpec, ToolHandler, RerankOptions } from '@dudousxd/nestjs-agent-core';
2
2
 
3
3
  interface ChunkOptions {
4
4
  /** Target max characters per chunk. Default 800. */
@@ -433,56 +433,217 @@ declare class MemoryVectorStore implements VectorStore {
433
433
  }
434
434
 
435
435
  /**
436
- * The minimal Postgres surface {@link PgVectorStore} needs — adapt your own `pg` / `postgres.js`
437
- * client to it, so this package pulls in NO driver (bring your own, like the store adapters take an
438
- * ORM handle and the Redis transport takes a client). `query` runs parameterized SQL (`$1,$2,…`) and
439
- * resolves the result rows.
436
+ * Turning a natural-language question into full-text search terms, for the lexical leg of
437
+ * `PgLexicalVectorStore`.
438
+ *
439
+ * With the `simple` text-search configuration (no stemming, no stop words; any language) a question
440
+ * searched as is either matches nothing (every word required) or, as "any word", ranks chunks full
441
+ * of "the / of / which / de / que" first. So the query side drops the stop words of the question's
442
+ * language(s) and keeps the meaningful terms, which the store then ranks by how many of them a chunk
443
+ * holds, rare terms weighing more (an IDF over the matching rows, BM25-style).
444
+ */
445
+ /**
446
+ * Postgres' Snowball stop word lists (`tsearch_data/{english,portuguese,spanish}.stop`), minus
447
+ * one-letter words (never terms here) and words that carry meaning in a sibling language
448
+ * ("estado", "sentido").
449
+ */
450
+ declare const DEFAULT_STOP_WORDS: Readonly<Record<string, ReadonlySet<string>>>;
451
+ /**
452
+ * The meaningful terms of a question, in order, deduplicated, at most `max`: the stop words of the
453
+ * language(s) the question is written in are dropped (the language(s) with the most stop words in
454
+ * it, so "sea"/"son" stay terms in an English question although they are Spanish stop words). A
455
+ * question made only of stop words keeps them all (there is nothing else to search for).
456
+ */
457
+ declare function keywordTerms(query: string, max?: number, stopWords?: Readonly<Record<string, ReadonlySet<string>>>): string[];
458
+ /** Whether the user wrote search syntax (a quoted phrase, `-exclusion`) worth honoring as such. */
459
+ declare function hasSearchSyntax(query: string): boolean;
460
+ /** `'a' | 'b' | …` for `to_tsquery` (terms are letter/digit runs, so quoting is enough). */
461
+ declare function anyTermTsquery(terms: string[]): string;
462
+
463
+ /**
464
+ * The minimal Postgres surface {@link import('./pg-vector-store.js').PgVectorStore} needs — adapt your
465
+ * own `pg` / `postgres.js` client to it, so this package pulls in NO driver (bring your own, like the
466
+ * store adapters take an ORM handle and the Redis transport takes a client). `query` runs
467
+ * parameterized SQL (`$1,$2,…`) and resolves the result rows.
468
+ *
469
+ * `transaction` is optional. When present, the store uses it for the few reads that must share one
470
+ * connection with a `SET LOCAL` (pgvector's iterative index scan); without it those settings are
471
+ * simply not applied. You rarely write either by hand: pass a `pg` `Pool`, a Drizzle database or a
472
+ * `postgres.js` `sql` and {@link toPgClient} builds both.
440
473
  */
441
474
  interface PgClient {
442
475
  query<Row = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<Row[]>;
476
+ /** Run `work` inside one transaction on one connection; commit on success, roll back on throw. */
477
+ transaction?<T>(work: (tx: PgClient) => Promise<T>): Promise<T>;
478
+ }
479
+ /**
480
+ * A node-postgres `Pool`, `PoolClient` or `Client` — anything whose `query(text, values)` resolves a
481
+ * result with `rows`. Typed structurally so this package needs no `pg` import.
482
+ */
483
+ interface NodePgQueryable {
484
+ query(text: string, values?: any[]): Promise<unknown>;
485
+ }
486
+ /** A `postgres.js` `sql` instance (or a transaction handle from `sql.begin`). */
487
+ interface PostgresJsSql {
488
+ unsafe(query: string, params?: any[]): PromiseLike<unknown>;
489
+ begin?(...args: any[]): PromiseLike<unknown>;
490
+ }
491
+ /**
492
+ * A Drizzle database — `drizzle(pool)` for node-postgres or `drizzle(sql)` for postgres.js. Drizzle
493
+ * exposes the driver it wraps as `$client`, which is what the store talks to; this saves the
494
+ * `(db as unknown as { $client: Pool }).$client` cast at every call site.
495
+ */
496
+ interface DrizzleLike {
497
+ $client: NodePgQueryable | PostgresJsSql;
498
+ }
499
+ /** Everything {@link toPgClient} (and so the `PgVectorStore` constructor) accepts. */
500
+ type PgClientSource = PgClient | NodePgQueryable | PostgresJsSql | DrizzleLike;
501
+ /**
502
+ * Normalize a Postgres handle into a {@link PgClient}:
503
+ *
504
+ * - a Drizzle database → its `$client`, then one of the below;
505
+ * - a `postgres.js` `sql` → `sql.unsafe(text, params)`, transactions via `sql.begin`;
506
+ * - a node-postgres `Pool` → `pool.query(...).rows`, transactions on a checked-out client
507
+ * (`BEGIN`/`COMMIT`/`ROLLBACK`, then `release()`); a single `Client`/`PoolClient` runs its
508
+ * transaction in place;
509
+ * - a hand-written {@link PgClient} (`query` resolving the rows array) passes through unchanged.
510
+ *
511
+ * Detection is structural and happens per call result for `query` (an array is taken as the rows, an
512
+ * object's `rows` otherwise), so a hand-written adapter keeps working exactly as before.
513
+ */
514
+ declare function toPgClient(source: PgClientSource): PgClient;
515
+
516
+ /** Where the lexical leg of a {@link PgLexicalVectorStore} reads its `tsvector` from. */
517
+ interface PgFullTextOptions {
518
+ /**
519
+ * Text-search configuration (`simple`, `english`, `portuguese`, …). Default `simple` — no stemming
520
+ * or stop words, so it works for any language and matches exact terms, which is what the lexical
521
+ * leg of a hybrid search is for. Must be the same configuration the index was built with, or
522
+ * Postgres cannot use the index and scans the table (still correct, just slow).
523
+ */
524
+ config?: string;
525
+ /**
526
+ * A `tsvector` column you maintain yourself (typically `GENERATED ALWAYS AS (…) STORED` in a
527
+ * migration, e.g. weighting a title above the body), with its own GIN index. When omitted the
528
+ * store searches the expression `to_tsvector(config, text)`, and `ensureSchema` creates a GIN
529
+ * expression index over exactly that.
530
+ */
531
+ column?: string;
532
+ /**
533
+ * Search natural-language questions by their meaningful terms (default `true`): the question's
534
+ * stop words are dropped (see {@link PgFullTextOptions.stopWords}) and rows holding any remaining
535
+ * term (at most 24) are ranked by the sum of the matched terms' IDF among those rows (BM25
536
+ * without term frequencies), `ts_rank_cd` breaking ties; a question with explicit search syntax
537
+ * (a quoted phrase, `-word`) is first tried as written. `false`: only `websearch_to_tsquery` on
538
+ * the query as written (every word must appear).
539
+ */
540
+ anyTermFallback?: boolean;
541
+ /**
542
+ * Stop word lists dropped from questions, by language; only the list(s) with the most words in
543
+ * the question apply, so a word that is a stop word in another language stays a term. Default
544
+ * {@link DEFAULT_STOP_WORDS} (English, Portuguese, Spanish: Postgres' Snowball lists). `false`
545
+ * keeps every word. With a language `config` (`english`) Postgres drops that language's stop
546
+ * words as well.
547
+ */
548
+ stopWords?: Readonly<Record<string, ReadonlySet<string>>> | false;
443
549
  }
444
550
  interface PgVectorStoreOptions {
445
551
  /** Table name. Default `agent_rag_chunks`. */
446
552
  table?: string;
447
- /** Embedding width — must match your model (e.g. 1536 for text-embedding-3-small). Default 1536. */
448
- dimensions?: number;
553
+ /**
554
+ * Embedding width — must match your model (e.g. 1536 for text-embedding-3-small). Default 1536.
555
+ *
556
+ * Pass a **list** to let several models' vectors share one table (mixed dimensions, e.g. while
557
+ * migrating from a 768-wide local model to a 1536-wide hosted one): the column becomes an untyped
558
+ * `vector`, `ensureSchema` creates one *partial* HNSW index per listed width
559
+ * (`((embedding::vector(n))) … WHERE vector_dims(embedding) = n`), and `search` only compares the
560
+ * query against vectors of its own width, through that width's index. A query whose width is not
561
+ * listed is still answered — exactly, by a sequential scan. Filter on the model as well (put it in
562
+ * the chunk metadata) when two models share a width.
563
+ */
564
+ dimensions?: number | readonly number[];
565
+ /**
566
+ * Allow chunks with no embedding (`embedding: []` on upsert is stored as `NULL`): index text first
567
+ * and embed later, or keep full-text-only chunks when there is no embedding model at all. The
568
+ * vector leg skips them; the lexical leg of {@link PgLexicalVectorStore} still finds them. Default
569
+ * `false` — the column stays `NOT NULL`. Only affects the DDL `ensureSchema` emits for a new table.
570
+ */
571
+ nullableEmbeddings?: boolean;
572
+ /**
573
+ * pgvector ≥ 0.8 iterative index scans for `search`: keep walking the HNSW graph until enough rows
574
+ * pass the metadata filter, instead of returning fewer than `topK` when a selective filter (one
575
+ * tenant of many) rejects most of the candidates the index produced. Applied with `SET LOCAL`, so
576
+ * it needs a client with a `transaction` (a `pg` Pool, Drizzle or postgres.js all have one); it is
577
+ * silently skipped on an older pgvector or a client without transactions. Default off.
578
+ */
579
+ iterativeScan?: 'strict_order' | 'relaxed_order';
580
+ /** `hnsw.ef_search` for `search` (candidate list size; pgvector's default is 40). Needs a `transaction`. */
581
+ efSearch?: number;
582
+ /**
583
+ * Rows per multi-row `INSERT … ON CONFLICT` statement in `upsert`. Default 100. Duplicate ids in
584
+ * one `upsert` call collapse to the last occurrence (as the old row-by-row loop left them).
585
+ */
586
+ upsertBatchSize?: number;
449
587
  }
450
588
  /**
451
589
  * A pgvector-backed {@link VectorStore} — the production reference adapter. Cosine distance via the
452
590
  * `<=>` operator over an HNSW index; metadata in a `jsonb` column filtered with `@>`. Call
453
- * {@link PgVectorStore.ensureSchema} once at boot to create the extension, table, and index.
591
+ * {@link PgVectorStore.ensureSchema} once at boot to create the extension, table, and index — or copy
592
+ * {@link PgVectorStore.schemaStatements} into a migration.
593
+ *
594
+ * The constructor takes a `pg` `Pool`, a Drizzle database, a `postgres.js` `sql`, or a hand-written
595
+ * {@link PgClient} (see {@link toPgClient}).
454
596
  *
455
- * This store does **not** implement the optional
456
- * {@link import('./vector-store.js').LexicalVectorStore} capability, unlike
457
- * {@link import('./redis-vector-store.js').RedisVectorStore}. That is a deliberate omission, not an
458
- * oversight: RediSearch already indexes the chunk text (the schema declares it `TEXT`), so BM25 is
459
- * free there, whereas the table below indexes nothing lexically — `text` is a plain column with no
460
- * `tsvector` and no GIN index. Adding one is not a transparent upgrade:
597
+ * This class does **not** implement the optional
598
+ * {@link import('./vector-store.js').LexicalVectorStore} capability; {@link PgLexicalVectorStore}
599
+ * (below) does. The split is deliberate: lexical search over Postgres needs a GIN index, and a
600
+ * store that silently gained `searchText` on upgrade would be picked up by every
601
+ * `isLexicalVectorStore(store)` check and start sequentially scanning an unindexed chunks table:
461
602
  *
462
- * - it is new DDL in `ensureSchema`, and `CREATE INDEX` (non-concurrently, as this method must, since
603
+ * - it is new DDL, and `CREATE INDEX` (non-concurrently, as `ensureSchema` must, since
463
604
  * `CONCURRENTLY` cannot run in a transaction) takes a write lock on an already-populated chunks
464
605
  * table — a boot-time stall proportional to corpus size for every existing deployment;
465
606
  * - it forces a text-search-configuration choice (`english` vs `simple` vs …) that must match between
466
607
  * the index expression and every query, or Postgres silently ignores the index and sequentially
467
608
  * scans the corpus — a failure mode that stays *correct* while quietly getting slower with scale.
468
609
  *
469
- * Both want a migration a consumer runs and observes, not a side effect of upgrading the library. The
470
- * capability interface is open, so a `PgLexicalVectorStore` (or an option here, gated on an
471
- * explicitly-created index) can be added later without changing anything else.
610
+ * So lexical search is something you opt into by constructing the subclass, with the index created
611
+ * by a migration you run and watch (or by `ensureSchema`, on a table small enough not to care).
472
612
  *
473
613
  * The enumeration and bulk-deletion methods {@link VectorStore} requires need nothing new here,
474
614
  * unlike the lexical capability above: enumeration and bulk deletion are `DISTINCT`, `= ANY($1)`, `DELETE … WHERE`
475
615
  * and `count(*)` over the table and index that already exist. No DDL, no boot-time lock, no migration.
616
+ *
617
+ * Subclassing: every statement filters through {@link PgVectorStore.whereConditions}, so a subclass
618
+ * can map an opaque filter onto its own columns (a tenant id, an ACL) in one place.
476
619
  */
477
620
  declare class PgVectorStore implements VectorStore {
478
- private readonly client;
479
- private readonly table;
621
+ protected readonly client: PgClient;
622
+ protected readonly table: string;
623
+ /** The single width (fixed-dimension table), or `undefined` for a mixed-dimension table. */
480
624
  private readonly dimensions;
481
- constructor(client: PgClient, options?: PgVectorStoreOptions);
625
+ /** The widths with a partial HNSW index, for a mixed-dimension table. */
626
+ private readonly indexedDimensions;
627
+ private readonly nullableEmbeddings;
628
+ private readonly iterativeScan;
629
+ private readonly efSearch;
630
+ private readonly upsertBatchSize;
631
+ private iterativeScanSupport;
632
+ constructor(client: PgClientSource, options?: PgVectorStoreOptions);
482
633
  /** Telemetry self-description — the table is the namespace a retrieval was served from. */
483
634
  describeRetrieval(): RetrievalDescriptor;
484
- /** Idempotent DDL: the `vector` extension, the chunks table, and the cosine HNSW index. */
635
+ /**
636
+ * The idempotent DDL {@link PgVectorStore.ensureSchema} runs, in order — for a migration instead
637
+ * of a boot-time side effect. On a populated table, run the index statements `CONCURRENTLY` there.
638
+ */
639
+ schemaStatements(): string[];
640
+ /** Idempotent DDL: the `vector` extension, the chunks table, and the cosine HNSW index(es). */
485
641
  ensureSchema(): Promise<void>;
642
+ /**
643
+ * Multi-row `INSERT … ON CONFLICT (id) DO UPDATE`, {@link PgVectorStoreOptions.upsertBatchSize}
644
+ * rows per statement. An empty `embedding` is written as `NULL` (see
645
+ * {@link PgVectorStoreOptions.nullableEmbeddings}).
646
+ */
486
647
  upsert(records: VectorRecord[]): Promise<void>;
487
648
  remove(documentId: string): Promise<void>;
488
649
  /**
@@ -523,7 +684,61 @@ declare class PgVectorStore implements VectorStore {
523
684
  */
524
685
  removeWhere(filter: Record<string, unknown>): Promise<number>;
525
686
  countChunks(filter?: Record<string, unknown>): Promise<number>;
687
+ /**
688
+ * Cosine similarity, nearest first. On a mixed-dimension table only vectors as wide as the query
689
+ * are compared (through that width's partial index when it has one); chunks without an embedding
690
+ * are never returned.
691
+ */
526
692
  search(embedding: number[], options: VectorSearchOptions): Promise<Passage[]>;
693
+ /**
694
+ * The SQL conditions (ANDed) a metadata `filter` compiles to, appending their bindings to `params`
695
+ * (placeholders are numbered after what `params` already holds). Every statement that takes a
696
+ * filter goes through here, so a subclass that maps the filter onto its own columns — a tenant id,
697
+ * an access list — overrides this one method. Return `['false']` to deny.
698
+ */
699
+ protected whereConditions(filter: Record<string, unknown> | undefined, params: unknown[]): string[];
700
+ private where;
701
+ /** Run a read with the configured HNSW settings `SET LOCAL` in one transaction, when possible. */
702
+ private withSearchSettings;
703
+ /** `hnsw.iterative_scan` exists from pgvector 0.8.0; setting it on an older one is an error. */
704
+ private supportsIterativeScan;
705
+ }
706
+ /**
707
+ * {@link PgVectorStore} plus Postgres full-text search: a {@link LexicalVectorStore}, so
708
+ * `LexicalRetriever` and `HybridRetriever` work on Postgres exactly as on RediSearch — the dense leg
709
+ * over pgvector, the lexical leg over a `tsvector`, both on the same rows and ids.
710
+ *
711
+ * A question is searched by its meaningful terms: its stop words dropped, rows holding any remaining
712
+ * term ranked by IDF-weighted coverage, `ts_rank_cd` (cover density) breaking ties (see
713
+ * {@link PgFullTextOptions.anyTermFallback}); explicit syntax (quoted phrases, `-exclusions`) goes
714
+ * through `websearch_to_tsquery` first.
715
+ *
716
+ * The `tsvector` is either a column you own ({@link PgFullTextOptions.column}) or the expression
717
+ * `to_tsvector(config, text)`, for which {@link PgVectorStore.schemaStatements} adds a GIN
718
+ * expression index. See {@link PgVectorStore} for why that index belongs in a migration on a
719
+ * populated table.
720
+ */
721
+ declare class PgLexicalVectorStore extends PgVectorStore implements LexicalVectorStore {
722
+ private readonly tsConfig;
723
+ private readonly tsColumn;
724
+ private readonly anyTermFallback;
725
+ private readonly stopWords;
726
+ constructor(client: PgClientSource, options?: PgVectorStoreOptions & {
727
+ fullText?: PgFullTextOptions;
728
+ });
729
+ schemaStatements(): string[];
730
+ searchText(query: string, options: VectorSearchOptions): Promise<Passage[]>;
731
+ /** `websearch_to_tsquery` on the query as written: every word, quoted phrases, `-exclusions`. */
732
+ private runTextSearch;
733
+ /**
734
+ * Rows holding any of `terms`, ranked by the sum of the matched terms' IDF among those rows,
735
+ * `ln(1 + (N - df + 0.5) / (df + 0.5))`, then `ts_rank_cd`. Each (row, term) match is evaluated
736
+ * once, and `ts_rank_cd` only for the rows ranked within `topK` (ties included): a question full
737
+ * of common words can match most of the table.
738
+ */
739
+ private runRankedTermSearch;
740
+ /** Must be character-for-character the index expression, or the planner won't use the index. */
741
+ private tsvector;
527
742
  }
528
743
 
529
744
  /**
@@ -1212,4 +1427,102 @@ interface RetrievalTool {
1212
1427
  */
1213
1428
  declare function createRetrievalTool(retriever: Retriever, options?: RetrievalToolOptions): RetrievalTool;
1214
1429
 
1215
- export { type ChunkOptions, type ChunkRecord, type DescribesRetrieval, EmbeddingRetriever, type EmbeddingRetrieverOptions, FilteredRetriever, HybridRetriever, type HybridRetrieverOptions, type IndexedDocument, type IngestChunksOptions, type IngestDocument, type IngestOptions, type InstrumentRetrieverOptions, KeywordRetriever, type KeywordRetrieverOptions, LexicalRetriever, type LexicalVectorStore, type ListChunksOptions, MemoryVectorStore, type MetadataPatch, type PgClient, PgVectorStore, type PgVectorStoreOptions, RAG_DIAGNOSTIC_LIB, RAG_RETRIEVAL_CHANNEL, RAG_RETRIEVAL_EVENT, type RagRetrievalEvent, type RedisSearchClient, RedisVectorSchemaMismatchError, RedisVectorStore, type RedisVectorStoreOptions, RerankingRetriever, type RerankingRetrieverOptions, type RetrievalDescriptor, type RetrievalTool, type RetrievalToolOptions, type RetrieverKind, type StoredChunk, UnsafeRemovalError, type VectorRecord, type VectorSearchOptions, type VectorStore, type VectorStoreKind, applyMetadataPatch, chunkDocuments, chunkIndexOf, chunkText, createRetrievalTool, describeRetrieval, describeSharedSource, describeSource, describesRetrieval, documentIdOf, emitRagRetrieval, ingestChunks, ingestDocuments, instrumentRetriever, isLexicalVectorStore };
1430
+ /** A non-2xx answer (or a malformed one) from an embeddings or rerank endpoint. */
1431
+ declare class HttpModelError extends Error {
1432
+ /** HTTP status; `502` when the endpoint answered 2xx with a body that doesn't fit the contract. */
1433
+ readonly status: number;
1434
+ constructor(
1435
+ /** HTTP status; `502` when the endpoint answered 2xx with a body that doesn't fit the contract. */
1436
+ status: number, message: string);
1437
+ }
1438
+ interface OpenAiEmbeddingsOptions {
1439
+ /** The embedding model id, sent as `model`. */
1440
+ model: string;
1441
+ /**
1442
+ * Base URL up to and including `/v1` — the client posts to `<baseUrl>/embeddings`. Default
1443
+ * `https://api.openai.com/v1`. Point it at any OpenAI-compatible server: Azure/OpenRouter/an LLM
1444
+ * gateway, Ollama (`http://localhost:11434/v1`), Hugging Face TEI, vLLM, LocalAI, LM Studio…
1445
+ */
1446
+ baseUrl?: string;
1447
+ /** Sent as `Authorization: Bearer <apiKey>` when set. Local servers usually need none. */
1448
+ apiKey?: string;
1449
+ /** Output width for models that support shortening (`text-embedding-3-*`), sent as `dimensions`. */
1450
+ dimensions?: number;
1451
+ /** Inputs per request. Default 64. */
1452
+ batchSize?: number;
1453
+ /**
1454
+ * Inputs longer than this many characters are truncated before sending, so one oversized chunk
1455
+ * doesn't fail a whole batch on the model's context limit. Default 24 000 (≈ 6–8k tokens); set
1456
+ * `Infinity` to send inputs as they are.
1457
+ */
1458
+ maxInputChars?: number;
1459
+ /** Extra request headers (an org/project id, a gateway's attribution header). */
1460
+ headers?: Record<string, string>;
1461
+ /** Per-request timeout. Default 120 000 ms. */
1462
+ timeoutMs?: number;
1463
+ /** Called with the provider-reported token count of every request — for cost accounting. */
1464
+ onUsage?: (tokens: number) => void;
1465
+ /** `fetch` to use. Default the global one. */
1466
+ fetch?: typeof fetch;
1467
+ }
1468
+ /**
1469
+ * An {@link EmbeddingProvider} over any OpenAI-compatible `POST /v1/embeddings` endpoint, with no SDK
1470
+ * dependency: OpenAI itself, or a gateway/local server speaking the same protocol (TEI, Ollama,
1471
+ * vLLM, LocalAI…). For a Vercel AI SDK model use `aiSdkEmbedding` from `-ai-sdk` instead.
1472
+ *
1473
+ * Batches by {@link OpenAiEmbeddingsOptions.batchSize}, restores input order from each item's
1474
+ * `index`, and fails loudly (an {@link HttpModelError}) on a non-2xx answer or a vector count that
1475
+ * doesn't match the inputs. Empty strings are sent as a single space, since OpenAI rejects them.
1476
+ *
1477
+ * ```ts
1478
+ * const embedder = openAiEmbeddings({ model: 'text-embedding-3-small', apiKey: process.env.OPENAI_API_KEY });
1479
+ * const local = openAiEmbeddings({ baseUrl: 'http://tei:8080/v1', model: 'BAAI/bge-m3' });
1480
+ * ```
1481
+ */
1482
+ declare function openAiEmbeddings(options: OpenAiEmbeddingsOptions): EmbeddingProvider;
1483
+
1484
+ interface HttpRerankerOptions {
1485
+ /**
1486
+ * The full rerank endpoint: `https://api.cohere.com/v2/rerank`, `https://api.jina.ai/v1/rerank`,
1487
+ * `https://api.voyageai.com/v1/rerank`, or a Hugging Face TEI / Infinity / vLLM server's `/rerank`.
1488
+ */
1489
+ url: string;
1490
+ /** Model id, sent as `model` (hosted APIs require it; TEI serves one model and ignores it). */
1491
+ model?: string;
1492
+ /** Sent as `Authorization: Bearer <apiKey>` when set. */
1493
+ apiKey?: string;
1494
+ /**
1495
+ * Request body dialect. `cohere` (Cohere, Jina, Voyage, Infinity, vLLM): `{ query, documents,
1496
+ * top_n }`. `tei`: `{ query, texts }`. Default `auto`, which sends `documents` **and** `texts` so
1497
+ * one config works against both families. Responses are read in every dialect regardless.
1498
+ */
1499
+ format?: 'auto' | 'cohere' | 'tei';
1500
+ /** Extra request headers. */
1501
+ headers?: Record<string, string>;
1502
+ /** Per-request timeout. Default 30 000 ms. */
1503
+ timeoutMs?: number;
1504
+ /** `fetch` to use. Default the global one. */
1505
+ fetch?: typeof fetch;
1506
+ }
1507
+ /**
1508
+ * A cross-encoder {@link Reranker} behind an HTTP `/rerank` endpoint — the Cohere-style contract
1509
+ * most providers and self-hosted servers share. Compose it with `RerankingRetriever`:
1510
+ *
1511
+ * ```ts
1512
+ * const reranker = new HttpReranker({ url: 'https://api.cohere.com/v2/rerank', model: 'rerank-v3.5', apiKey });
1513
+ * const retriever = new RerankingRetriever(hybrid, reranker, { fetchTopK: 30 });
1514
+ * ```
1515
+ *
1516
+ * Reads `results: [{ index, relevance_score }]` (Cohere, Jina), `data: [{ index, relevance_score }]`
1517
+ * (Voyage) and a bare `[{ index, score }]` (TEI). Each passage keeps its fields and takes the new
1518
+ * score; the list is re-sorted and cut to `topK`. Indices the server invents are ignored.
1519
+ */
1520
+ declare class HttpReranker implements Reranker {
1521
+ private readonly options;
1522
+ private readonly format;
1523
+ private readonly doFetch;
1524
+ constructor(options: HttpRerankerOptions);
1525
+ rerank(query: string, passages: Passage[], options?: RerankOptions): Promise<Passage[]>;
1526
+ }
1527
+
1528
+ export { type ChunkOptions, type ChunkRecord, DEFAULT_STOP_WORDS, type DescribesRetrieval, type DrizzleLike, EmbeddingRetriever, type EmbeddingRetrieverOptions, FilteredRetriever, HttpModelError, HttpReranker, type HttpRerankerOptions, HybridRetriever, type HybridRetrieverOptions, type IndexedDocument, type IngestChunksOptions, type IngestDocument, type IngestOptions, type InstrumentRetrieverOptions, KeywordRetriever, type KeywordRetrieverOptions, LexicalRetriever, type LexicalVectorStore, type ListChunksOptions, MemoryVectorStore, type MetadataPatch, type NodePgQueryable, type OpenAiEmbeddingsOptions, type PgClient, type PgClientSource, type PgFullTextOptions, PgLexicalVectorStore, PgVectorStore, type PgVectorStoreOptions, type PostgresJsSql, RAG_DIAGNOSTIC_LIB, RAG_RETRIEVAL_CHANNEL, RAG_RETRIEVAL_EVENT, type RagRetrievalEvent, type RedisSearchClient, RedisVectorSchemaMismatchError, RedisVectorStore, type RedisVectorStoreOptions, RerankingRetriever, type RerankingRetrieverOptions, type RetrievalDescriptor, type RetrievalTool, type RetrievalToolOptions, type RetrieverKind, type StoredChunk, UnsafeRemovalError, type VectorRecord, type VectorSearchOptions, type VectorStore, type VectorStoreKind, anyTermTsquery, applyMetadataPatch, chunkDocuments, chunkIndexOf, chunkText, createRetrievalTool, describeRetrieval, describeSharedSource, describeSource, describesRetrieval, documentIdOf, emitRagRetrieval, hasSearchSyntax, ingestChunks, ingestDocuments, instrumentRetriever, isLexicalVectorStore, keywordTerms, openAiEmbeddings, toPgClient };