@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/README.md +94 -14
- package/dist/index.cjs +666 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +336 -23
- package/dist/index.d.ts +336 -23
- package/dist/index.js +657 -73
- package/dist/index.js.map +1 -1
- package/package.json +10 -9
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
|
-
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
*
|
|
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
|
-
/**
|
|
448
|
-
|
|
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
|
|
456
|
-
* {@link import('./vector-store.js').LexicalVectorStore} capability
|
|
457
|
-
*
|
|
458
|
-
*
|
|
459
|
-
*
|
|
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
|
|
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
|
-
*
|
|
470
|
-
*
|
|
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
|
-
|
|
479
|
-
|
|
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
|
-
|
|
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
|
-
/**
|
|
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
|
-
|
|
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 };
|