@dudousxd/nestjs-agent-rag 0.9.0 → 0.10.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 +59 -1
- package/dist/index.cjs +221 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +258 -1
- package/dist/index.d.ts +258 -1
- package/dist/index.js +212 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.d.cts
CHANGED
|
@@ -319,6 +319,68 @@ declare function chunkIndexOf(chunkId: string): number;
|
|
|
319
319
|
/** Collapse a chunk id (`${documentId}#<n>`) back to its source document id. */
|
|
320
320
|
declare function documentIdOf(chunkId: string): string;
|
|
321
321
|
|
|
322
|
+
/**
|
|
323
|
+
* What a retrieval was served BY — the static half of retrieval telemetry, separated from the
|
|
324
|
+
* emitting half (`retrieval-telemetry.ts`) so a store or a retriever can describe itself without
|
|
325
|
+
* importing anything that emits. That separation is not tidiness: `retrieval-telemetry.ts` imports
|
|
326
|
+
* the retrievers' shapes to detect them, and the retrievers import their descriptor kind, so putting
|
|
327
|
+
* both halves in one module would make every retriever ↔ telemetry edge a cycle.
|
|
328
|
+
*/
|
|
329
|
+
/** Which retrieval strategy answered. `unknown` is a retriever this package did not ship. */
|
|
330
|
+
type RetrieverKind = 'embedding' | 'keyword' | 'lexical' | 'hybrid' | 'filtered' | 'reranking' | 'unknown';
|
|
331
|
+
/** Which backend held the chunks. Omitted entirely for a retriever that holds its own (keyword). */
|
|
332
|
+
type VectorStoreKind = 'memory' | 'pg' | 'redis';
|
|
333
|
+
/**
|
|
334
|
+
* A retriever's (or a store's) self-description, as it appears on a retrieval event. Every field is
|
|
335
|
+
* optional because the describer is answering only for the layer it *is*: a store knows its backend
|
|
336
|
+
* and namespace but not which strategy queried it; `KeywordRetriever` knows its strategy but has no
|
|
337
|
+
* store at all.
|
|
338
|
+
*/
|
|
339
|
+
interface RetrievalDescriptor {
|
|
340
|
+
retriever?: RetrieverKind;
|
|
341
|
+
store?: VectorStoreKind;
|
|
342
|
+
/**
|
|
343
|
+
* The namespace the chunks live in — `PgVectorStore`'s table, `RedisVectorStore`'s RediSearch
|
|
344
|
+
* index. This is the STORE-level namespace, not a per-query metadata scope: a host that partitions
|
|
345
|
+
* one index into logical collections with a metadata filter (the usual multi-tenant shape) reports
|
|
346
|
+
* that through `InstrumentRetrieverOptions.collection`, which overrides this.
|
|
347
|
+
*/
|
|
348
|
+
collection?: string;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* The optional capability a store or retriever implements to appear on a retrieval event as
|
|
352
|
+
* something other than `unknown`. Deliberately NOT a member of `VectorStore` or of core's
|
|
353
|
+
* `Retriever`: both are implemented outside this package, and adding a required member to either
|
|
354
|
+
* would break every existing implementation on upgrade — for a field that only observability reads.
|
|
355
|
+
*/
|
|
356
|
+
interface DescribesRetrieval {
|
|
357
|
+
describeRetrieval(): RetrievalDescriptor;
|
|
358
|
+
}
|
|
359
|
+
/** Structural guard, so a `VectorStore`/`Retriever` is narrowed to the capability without a cast. */
|
|
360
|
+
declare function describesRetrieval(value: unknown): value is DescribesRetrieval;
|
|
361
|
+
/** A candidate's descriptor, or an empty one when it does not carry the capability. */
|
|
362
|
+
declare function describeRetrieval(candidate: unknown): RetrievalDescriptor;
|
|
363
|
+
/**
|
|
364
|
+
* The store half of a wrapped retriever's descriptor: the base's `store`/`collection` with its
|
|
365
|
+
* `retriever` dropped, so the wrapper can stamp its own strategy on top.
|
|
366
|
+
*
|
|
367
|
+
* `new FilteredRetriever(new EmbeddingRetriever(embedder, pg), scope)` therefore reports
|
|
368
|
+
* `{ retriever: 'filtered', store: 'pg', collection: 'agent_rag_chunks' }` rather than losing the
|
|
369
|
+
* store: which backend answered is the thing a "retrievals by store" panel exists to show, and a
|
|
370
|
+
* production wiring is almost always two or three wrappers deep.
|
|
371
|
+
*/
|
|
372
|
+
declare function describeSource(base: unknown): Omit<RetrievalDescriptor, 'retriever'>;
|
|
373
|
+
/**
|
|
374
|
+
* The store half shared by EVERY leg of a composed retriever, or nothing when they disagree.
|
|
375
|
+
*
|
|
376
|
+
* A hybrid whose legs are the dense and lexical halves of the same RediSearch index (the shape
|
|
377
|
+
* `LexicalRetriever` exists for) genuinely was served by that one store, and reporting it is what
|
|
378
|
+
* makes the store breakdown add up. A hybrid fusing pgvector with an in-process BM25 index was not
|
|
379
|
+
* served by either alone, and picking the first leg would silently attribute every such retrieval to
|
|
380
|
+
* a store that answered half of it.
|
|
381
|
+
*/
|
|
382
|
+
declare function describeSharedSource(legs: readonly unknown[]): Omit<RetrievalDescriptor, 'retriever'>;
|
|
383
|
+
|
|
322
384
|
/**
|
|
323
385
|
* An in-process {@link VectorStore} — cosine similarity over a Map, no infra. The reference adapter
|
|
324
386
|
* for tests and small/embedded corpora; for production scale use `PgVectorStore` (or your own).
|
|
@@ -331,6 +393,12 @@ declare function documentIdOf(chunkId: string): string;
|
|
|
331
393
|
*/
|
|
332
394
|
declare class MemoryVectorStore implements VectorStore {
|
|
333
395
|
private readonly records;
|
|
396
|
+
/**
|
|
397
|
+
* Telemetry self-description. No `collection`: there is no namespace to name — the corpus IS this
|
|
398
|
+
* instance, and two `MemoryVectorStore`s in one process are two corpora with nothing to tell them
|
|
399
|
+
* apart on a dashboard.
|
|
400
|
+
*/
|
|
401
|
+
describeRetrieval(): RetrievalDescriptor;
|
|
334
402
|
upsert(records: VectorRecord[]): Promise<void>;
|
|
335
403
|
remove(documentId: string): Promise<void>;
|
|
336
404
|
/**
|
|
@@ -411,6 +479,8 @@ declare class PgVectorStore implements VectorStore {
|
|
|
411
479
|
private readonly table;
|
|
412
480
|
private readonly dimensions;
|
|
413
481
|
constructor(client: PgClient, options?: PgVectorStoreOptions);
|
|
482
|
+
/** Telemetry self-description — the table is the namespace a retrieval was served from. */
|
|
483
|
+
describeRetrieval(): RetrievalDescriptor;
|
|
414
484
|
/** Idempotent DDL: the `vector` extension, the chunks table, and the cosine HNSW index. */
|
|
415
485
|
ensureSchema(): Promise<void>;
|
|
416
486
|
upsert(records: VectorRecord[]): Promise<void>;
|
|
@@ -531,6 +601,12 @@ declare class RedisVectorStore implements LexicalVectorStore {
|
|
|
531
601
|
private readonly filterableFields;
|
|
532
602
|
private readonly lexicalScorer;
|
|
533
603
|
constructor(client: RedisSearchClient, options?: RedisVectorStoreOptions);
|
|
604
|
+
/**
|
|
605
|
+
* Telemetry self-description — the RediSearch INDEX, not the key prefix: the index is what both
|
|
606
|
+
* legs query, and two stores sharing one index (the dense and lexical halves of a hybrid) must
|
|
607
|
+
* report the same namespace or `describeSharedSource` would see them disagree and drop the store.
|
|
608
|
+
*/
|
|
609
|
+
describeRetrieval(): RetrievalDescriptor;
|
|
534
610
|
/**
|
|
535
611
|
* Idempotent, and drift-aware: create the HNSW/cosine index if `FT.INFO` says it doesn't exist —
|
|
536
612
|
* and if it DOES exist, compare what's there against this store's configuration instead of
|
|
@@ -740,6 +816,8 @@ declare class EmbeddingRetriever implements Retriever {
|
|
|
740
816
|
private readonly store;
|
|
741
817
|
private readonly options;
|
|
742
818
|
constructor(embedder: EmbeddingProvider, store: VectorStore, options?: EmbeddingRetrieverOptions);
|
|
819
|
+
/** Telemetry self-description — the dense strategy, over whatever store it was handed. */
|
|
820
|
+
describeRetrieval(): RetrievalDescriptor;
|
|
743
821
|
retrieve(query: string, options?: RetrieveOptions): Promise<Passage[]>;
|
|
744
822
|
}
|
|
745
823
|
|
|
@@ -799,6 +877,12 @@ declare class KeywordRetriever implements Retriever {
|
|
|
799
877
|
private readonly k1;
|
|
800
878
|
private readonly b;
|
|
801
879
|
constructor(options?: KeywordRetrieverOptions);
|
|
880
|
+
/**
|
|
881
|
+
* Telemetry self-description. No `store`: this retriever holds its own copy of the corpus in
|
|
882
|
+
* process, so attributing its retrievals to whichever vector store happens to hold the same chunks
|
|
883
|
+
* would credit a backend that was never queried.
|
|
884
|
+
*/
|
|
885
|
+
describeRetrieval(): RetrievalDescriptor;
|
|
802
886
|
/** How many chunks are currently indexed. */
|
|
803
887
|
get size(): number;
|
|
804
888
|
/** Index (or re-index) records. Re-adding an existing id replaces its posting and updates stats. */
|
|
@@ -844,6 +928,8 @@ declare class KeywordRetriever implements Retriever {
|
|
|
844
928
|
declare class LexicalRetriever implements Retriever {
|
|
845
929
|
private readonly store;
|
|
846
930
|
constructor(store: LexicalVectorStore);
|
|
931
|
+
/** Telemetry self-description — the store's own lexical index, so the store is the same one. */
|
|
932
|
+
describeRetrieval(): RetrievalDescriptor;
|
|
847
933
|
retrieve(query: string, options?: RetrieveOptions): Promise<Passage[]>;
|
|
848
934
|
}
|
|
849
935
|
|
|
@@ -895,6 +981,8 @@ declare class HybridRetriever implements Retriever {
|
|
|
895
981
|
private readonly retrievers;
|
|
896
982
|
private readonly options;
|
|
897
983
|
constructor(retrievers: Retriever[], options?: HybridRetrieverOptions);
|
|
984
|
+
/** Telemetry self-description — the store only when every leg agrees; see `describeSharedSource`. */
|
|
985
|
+
describeRetrieval(): RetrievalDescriptor;
|
|
898
986
|
retrieve(query: string, options?: RetrieveOptions): Promise<Passage[]>;
|
|
899
987
|
}
|
|
900
988
|
|
|
@@ -913,6 +1001,8 @@ declare class RerankingRetriever implements Retriever {
|
|
|
913
1001
|
private readonly reranker;
|
|
914
1002
|
private readonly options;
|
|
915
1003
|
constructor(base: Retriever, reranker: Reranker, options?: RerankingRetrieverOptions);
|
|
1004
|
+
/** Telemetry self-description — the two-stage strategy, over the base's store. */
|
|
1005
|
+
describeRetrieval(): RetrievalDescriptor;
|
|
916
1006
|
retrieve(query: string, options?: RetrieveOptions): Promise<Passage[]>;
|
|
917
1007
|
}
|
|
918
1008
|
|
|
@@ -929,15 +1019,178 @@ declare class FilteredRetriever implements Retriever {
|
|
|
929
1019
|
private readonly base;
|
|
930
1020
|
private readonly filter;
|
|
931
1021
|
constructor(base: Retriever, filter: Record<string, unknown>);
|
|
1022
|
+
/** Telemetry self-description — this scope, over the base's store. */
|
|
1023
|
+
describeRetrieval(): RetrievalDescriptor;
|
|
932
1024
|
retrieve(query: string, options?: RetrieveOptions): Promise<Passage[]>;
|
|
933
1025
|
}
|
|
934
1026
|
|
|
1027
|
+
/**
|
|
1028
|
+
* Retrieval telemetry: one diagnostics event per retrieval, carrying how long it took, how much came
|
|
1029
|
+
* back, how good it was, and what served it.
|
|
1030
|
+
*
|
|
1031
|
+
* Until this existed, retrieval reached Telescope only as the *tool call* that wrapped it (see
|
|
1032
|
+
* `retrieval-tool.ts`), which says a retrieval happened and nothing else. The questions an operator
|
|
1033
|
+
* actually arrives with — is retrieval slow, is it returning nothing, is one collection colder than
|
|
1034
|
+
* the rest, did the scores collapse after a model swap — are all invisible in a tool-call row,
|
|
1035
|
+
* because a tool call that returns zero passages and one that returns five perfect ones are the same
|
|
1036
|
+
* row with the same `ok` status.
|
|
1037
|
+
*
|
|
1038
|
+
* ## One seam, not six
|
|
1039
|
+
*
|
|
1040
|
+
* Instrumentation is a WRAPPER over the core `Retriever` SPI ({@link instrumentRetriever}), not code
|
|
1041
|
+
* inside each retriever. Every retriever in this package — and every retriever outside it — is the
|
|
1042
|
+
* same one-method interface, so one wrapper covers all of them, including ones this package has
|
|
1043
|
+
* never heard of. The alternative, an `emit` inside each of the six `retrieve` methods, would have
|
|
1044
|
+
* had to be repeated in each, skipped by third-party retrievers entirely, and would have double- and
|
|
1045
|
+
* triple-counted the composed ones (a hybrid over two legs emitting three events for one retrieval).
|
|
1046
|
+
*
|
|
1047
|
+
* ## How a composed retrieval reports
|
|
1048
|
+
*
|
|
1049
|
+
* **The outermost instrumented retriever in a call tree emits; anything instrumented inside it stays
|
|
1050
|
+
* silent.** A retrieval is one question the caller asked, so it is one event no matter how many
|
|
1051
|
+
* retrievers cooperated to answer it: `RerankingRetriever` over a `HybridRetriever` over a dense and
|
|
1052
|
+
* a lexical leg is ONE retrieval, reported as `retriever: 'reranking'` with the duration of the
|
|
1053
|
+
* whole thing and the scores the caller actually got back.
|
|
1054
|
+
*
|
|
1055
|
+
* The suppression is enforced with an {@link AsyncLocalStorage} flag rather than by asking hosts to
|
|
1056
|
+
* wrap carefully, because the wrapping that double-counts is the natural one: a host that wraps its
|
|
1057
|
+
* top-level retriever and *also* wraps the dense leg it shares with another code path has not made a
|
|
1058
|
+
* mistake, and would otherwise get two events per retrieval, a zero-hit rate computed over a mixture
|
|
1059
|
+
* of legs and composites, and a retrieval count roughly twice its query count.
|
|
1060
|
+
*
|
|
1061
|
+
* ## Opt-out safety, and what the hot path pays
|
|
1062
|
+
*
|
|
1063
|
+
* The event goes out on `aviary:rag:retrieval` via `@dudousxd/nestjs-diagnostics`, whose `emit` is
|
|
1064
|
+
* gated on `channel.hasSubscribers` and never throws. This wrapper checks that same gate BEFORE it
|
|
1065
|
+
* does anything at all — no clock read, no `AsyncLocalStorage.run`, no score arithmetic — and
|
|
1066
|
+
* delegates straight through when nothing is listening. A host that wires this package without
|
|
1067
|
+
* Telescope (or any subscriber) pays two `Map` lookups and a boolean per retrieval, and nothing else
|
|
1068
|
+
* changes: the wrapper returns the base retriever's passages verbatim, and rethrows its errors
|
|
1069
|
+
* unchanged.
|
|
1070
|
+
*
|
|
1071
|
+
* ## Why this channel is not merged into the typed `ChannelRegistry`
|
|
1072
|
+
*
|
|
1073
|
+
* `@dudousxd/nestjs-agent-rag-media` already emits `media.ingested`/`media.removed`/`media.skipped`/
|
|
1074
|
+
* `media.failed` on the same `rag` lib, and flip's host app emits `rag:search` on it. Declaring
|
|
1075
|
+
* `ChannelRegistry['rag'] = { retrieval: RagRetrievalEvent }` here would narrow `EventOf<'rag'>` to
|
|
1076
|
+
* this one key process-wide and turn every one of those sibling emits into a compile error in any
|
|
1077
|
+
* project that installs both packages. The payload stays typed where it matters — {@link emitRagRetrieval}
|
|
1078
|
+
* takes {@link RagRetrievalEvent} — and the wire contract is documented below instead.
|
|
1079
|
+
*/
|
|
1080
|
+
/** The diagnostics lib segment. Shared with `@dudousxd/nestjs-agent-rag-media`'s `media.*` events. */
|
|
1081
|
+
declare const RAG_DIAGNOSTIC_LIB = "rag";
|
|
1082
|
+
/** The diagnostics event segment. */
|
|
1083
|
+
declare const RAG_RETRIEVAL_EVENT = "retrieval";
|
|
1084
|
+
/**
|
|
1085
|
+
* The full channel name a subscriber listens on: `aviary:rag:retrieval`. This is the wire contract —
|
|
1086
|
+
* `@dudousxd/nestjs-agent-telescope` subscribes to this exact string rather than importing this
|
|
1087
|
+
* package, which is what keeps the telescope extension free of a dependency on the retrieval stack
|
|
1088
|
+
* (and lets a host that uses neither still observe retrieval with a bare `diagnostics_channel`
|
|
1089
|
+
* subscription).
|
|
1090
|
+
*/
|
|
1091
|
+
declare const RAG_RETRIEVAL_CHANNEL: string;
|
|
1092
|
+
/**
|
|
1093
|
+
* The payload of one retrieval event. Counts, durations, kinds and scores only — never the query
|
|
1094
|
+
* text and never passage text. Both are user content, and this lands in an ops store with a short
|
|
1095
|
+
* retention window and a Slack-facing redaction budget; everything here is safe to put on a
|
|
1096
|
+
* dashboard and is what tells the failure modes apart anyway.
|
|
1097
|
+
*
|
|
1098
|
+
* The DURATION is not in here: it rides the envelope (`emit`'s `opts.durationMs`), which is the field
|
|
1099
|
+
* Telescope's OTel exporter turns into a latency histogram. Putting it in the payload instead would
|
|
1100
|
+
* have made retrieval latency a number somebody reads out of a JSON blob rather than a graph.
|
|
1101
|
+
*/
|
|
1102
|
+
interface RagRetrievalEvent {
|
|
1103
|
+
/** Which strategy answered — the OUTERMOST one, for a composed retriever. */
|
|
1104
|
+
retriever: RetrieverKind;
|
|
1105
|
+
/** Which backend held the chunks. Absent for an in-process retriever, or when legs disagree. */
|
|
1106
|
+
store?: VectorStoreKind;
|
|
1107
|
+
/** Store namespace (pg table / RediSearch index), or the host's logical collection. */
|
|
1108
|
+
collection?: string;
|
|
1109
|
+
/** What the caller asked for, so `chunks < topK` is readable as "the corpus ran out". */
|
|
1110
|
+
topK: number;
|
|
1111
|
+
/** How many passages came back. */
|
|
1112
|
+
chunks: number;
|
|
1113
|
+
/**
|
|
1114
|
+
* `chunks === 0`. Carried as its own flag rather than left to be derived, because the zero-hit RATE
|
|
1115
|
+
* is the headline number and deriving it means every consumer re-deriving the same predicate.
|
|
1116
|
+
*/
|
|
1117
|
+
zeroHit: boolean;
|
|
1118
|
+
/** Best score in the result, rounded to 4dp. Absent on a zero-hit. */
|
|
1119
|
+
topScore?: number;
|
|
1120
|
+
/** Mean score across the result, rounded to 4dp. Absent on a zero-hit. */
|
|
1121
|
+
meanScore?: number;
|
|
1122
|
+
/**
|
|
1123
|
+
* The retrieval threw. Reported rather than dropped because a failed retrieval and an empty one
|
|
1124
|
+
* look identical from the agent's side — both become "I couldn't find anything" — so a channel
|
|
1125
|
+
* that only carried successes would go quiet exactly when retrieval broke.
|
|
1126
|
+
*/
|
|
1127
|
+
failed: boolean;
|
|
1128
|
+
/** The error message, when `failed`. */
|
|
1129
|
+
error?: string;
|
|
1130
|
+
}
|
|
1131
|
+
/** Publish one retrieval event. `durationMs` rides the envelope; see {@link RagRetrievalEvent}. */
|
|
1132
|
+
declare function emitRagRetrieval(event: RagRetrievalEvent, durationMs: number): void;
|
|
1133
|
+
interface InstrumentRetrieverOptions {
|
|
1134
|
+
/**
|
|
1135
|
+
* Override the auto-detected {@link RetrievalDescriptor}, field by field. Needed for a retriever or
|
|
1136
|
+
* store from outside this package (which reports `retriever: 'unknown'` and no store), and for a
|
|
1137
|
+
* host that wants its own naming.
|
|
1138
|
+
*/
|
|
1139
|
+
describe?: RetrievalDescriptor;
|
|
1140
|
+
/**
|
|
1141
|
+
* The logical collection this retrieval searched, when the store namespace is not it. Pass a
|
|
1142
|
+
* function to read it off the call's metadata filter — the multi-tenant shape, where one index
|
|
1143
|
+
* holds every collection and the filter picks one:
|
|
1144
|
+
*
|
|
1145
|
+
* ```ts
|
|
1146
|
+
* instrumentRetriever(retriever, {
|
|
1147
|
+
* collection: (filter) => (typeof filter?.collectionId === 'string' ? filter.collectionId : undefined),
|
|
1148
|
+
* })
|
|
1149
|
+
* ```
|
|
1150
|
+
*
|
|
1151
|
+
* Returning `undefined` falls back to the store namespace, which is the right answer for a query
|
|
1152
|
+
* scoped to many collections at once: a breakdown panel needs ONE label per retrieval, and
|
|
1153
|
+
* inventing a synthetic `"a+b+c"` bucket would produce a chart whose slices are combinations
|
|
1154
|
+
* rather than collections.
|
|
1155
|
+
*/
|
|
1156
|
+
collection?: string | ((filter: Record<string, unknown> | undefined) => string | undefined);
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Wrap a retriever so every `retrieve` publishes a {@link RagRetrievalEvent} on
|
|
1160
|
+
* {@link RAG_RETRIEVAL_CHANNEL}. Wrap the retriever you actually hand to the agent — the outermost
|
|
1161
|
+
* one — and nothing else needs changing:
|
|
1162
|
+
*
|
|
1163
|
+
* ```ts
|
|
1164
|
+
* const retriever = instrumentRetriever(
|
|
1165
|
+
* new HybridRetriever([new EmbeddingRetriever(embedder, store), new LexicalRetriever(store)]),
|
|
1166
|
+
* );
|
|
1167
|
+
* ```
|
|
1168
|
+
*
|
|
1169
|
+
* {@link createRetrievalTool} already does this for the tool it builds, so agentic retrieval is
|
|
1170
|
+
* instrumented with no host change at all; call this directly for inject-mode retrieval
|
|
1171
|
+
* (`AgentModule.forRoot({ retrieval })`) or for a host that calls `retrieve` itself. Wrapping twice
|
|
1172
|
+
* is harmless — see the composed-retrieval section above.
|
|
1173
|
+
*/
|
|
1174
|
+
declare function instrumentRetriever(retriever: Retriever, options?: InstrumentRetrieverOptions): Retriever;
|
|
1175
|
+
|
|
935
1176
|
interface RetrievalToolOptions {
|
|
936
1177
|
/** Tool name the model sees. Default `search_knowledge`. */
|
|
937
1178
|
name?: string;
|
|
938
1179
|
description?: string;
|
|
939
1180
|
/** Passages per search. Default lets the retriever decide (typically 5). */
|
|
940
1181
|
topK?: number;
|
|
1182
|
+
/**
|
|
1183
|
+
* Retrieval telemetry (`aviary:rag:retrieval` — duration, chunk count, score distribution, store
|
|
1184
|
+
* and collection). **On by default**, because this tool is the once-per-retrieval seam in agentic
|
|
1185
|
+
* mode: instrumenting here is what makes the RAG panels work for a host that only ever calls
|
|
1186
|
+
* `createRetrievalTool`, with no wiring at all. It costs nothing when nobody subscribes (see
|
|
1187
|
+
* {@link instrumentRetriever}), and cannot double-count when the host has already wrapped the
|
|
1188
|
+
* retriever itself.
|
|
1189
|
+
*
|
|
1190
|
+
* Pass `false` to opt a single tool out — a host that reports retrieval its own way, or one whose
|
|
1191
|
+
* corpus is small enough that the events are noise.
|
|
1192
|
+
*/
|
|
1193
|
+
telemetry?: boolean | InstrumentRetrieverOptions;
|
|
941
1194
|
}
|
|
942
1195
|
/** A functional tool (`{ spec, handler }`) — pass it to nestjs `provideAgentTool`. */
|
|
943
1196
|
interface RetrievalTool {
|
|
@@ -949,10 +1202,14 @@ interface RetrievalTool {
|
|
|
949
1202
|
* decides it needs context. Its output `{ passages }` persists as the tool call's result, so sources
|
|
950
1203
|
* flow to the frontend and telescope through the normal tool-call machinery (the citation surface).
|
|
951
1204
|
*
|
|
1205
|
+
* The retrieval ITSELF is also instrumented (`aviary:rag:retrieval`) unless `telemetry: false` — the
|
|
1206
|
+
* tool-call row says a retrieval happened, the retrieval event says how long it took, how much came
|
|
1207
|
+
* back and how good it was. See {@link instrumentRetriever}.
|
|
1208
|
+
*
|
|
952
1209
|
* ```ts
|
|
953
1210
|
* providers: [provideAgentTool(createRetrievalTool(retriever))]
|
|
954
1211
|
* ```
|
|
955
1212
|
*/
|
|
956
1213
|
declare function createRetrievalTool(retriever: Retriever, options?: RetrievalToolOptions): RetrievalTool;
|
|
957
1214
|
|
|
958
|
-
export { type ChunkOptions, type ChunkRecord, EmbeddingRetriever, type EmbeddingRetrieverOptions, FilteredRetriever, HybridRetriever, type HybridRetrieverOptions, type IndexedDocument, type IngestChunksOptions, type IngestDocument, type IngestOptions, KeywordRetriever, type KeywordRetrieverOptions, LexicalRetriever, type LexicalVectorStore, type ListChunksOptions, MemoryVectorStore, type MetadataPatch, type PgClient, PgVectorStore, type PgVectorStoreOptions, type RedisSearchClient, RedisVectorSchemaMismatchError, RedisVectorStore, type RedisVectorStoreOptions, RerankingRetriever, type RerankingRetrieverOptions, type RetrievalTool, type RetrievalToolOptions, type StoredChunk, UnsafeRemovalError, type VectorRecord, type VectorSearchOptions, type VectorStore, applyMetadataPatch, chunkDocuments, chunkIndexOf, chunkText, createRetrievalTool, documentIdOf, ingestChunks, ingestDocuments, isLexicalVectorStore };
|
|
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 };
|