@cogitator-ai/rag 0.1.9 → 0.2.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 +66 -31
- package/dist/chunkers/create-chunker.js.map +1 -1
- package/dist/chunkers/index.d.ts.map +1 -1
- package/dist/chunkers/index.js.map +1 -1
- package/dist/chunkers/recursive-chunker.d.ts +2 -3
- package/dist/chunkers/recursive-chunker.d.ts.map +1 -1
- package/dist/chunkers/recursive-chunker.js +89 -118
- package/dist/chunkers/recursive-chunker.js.map +1 -1
- package/dist/chunkers/semantic-chunker.d.ts +2 -0
- package/dist/chunkers/semantic-chunker.d.ts.map +1 -1
- package/dist/chunkers/semantic-chunker.js +72 -38
- package/dist/chunkers/semantic-chunker.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/loaders/csv-loader.d.ts.map +1 -1
- package/dist/loaders/csv-loader.js +12 -4
- package/dist/loaders/csv-loader.js.map +1 -1
- package/dist/loaders/html-loader.d.ts +4 -0
- package/dist/loaders/html-loader.d.ts.map +1 -1
- package/dist/loaders/html-loader.js +26 -2
- package/dist/loaders/html-loader.js.map +1 -1
- package/dist/loaders/index.d.ts.map +1 -1
- package/dist/loaders/index.js.map +1 -1
- package/dist/loaders/json-loader.d.ts +1 -0
- package/dist/loaders/json-loader.d.ts.map +1 -1
- package/dist/loaders/json-loader.js +15 -3
- package/dist/loaders/json-loader.js.map +1 -1
- package/dist/loaders/markdown-loader.d.ts.map +1 -1
- package/dist/loaders/markdown-loader.js +8 -4
- package/dist/loaders/markdown-loader.js.map +1 -1
- package/dist/loaders/pdf-loader.d.ts +1 -0
- package/dist/loaders/pdf-loader.d.ts.map +1 -1
- package/dist/loaders/pdf-loader.js +22 -3
- package/dist/loaders/pdf-loader.js.map +1 -1
- package/dist/loaders/text-loader.js +1 -1
- package/dist/loaders/text-loader.js.map +1 -1
- package/dist/loaders/web-loader.d.ts +33 -0
- package/dist/loaders/web-loader.d.ts.map +1 -1
- package/dist/loaders/web-loader.js +262 -8
- package/dist/loaders/web-loader.js.map +1 -1
- package/dist/rag-builder.d.ts +10 -1
- package/dist/rag-builder.d.ts.map +1 -1
- package/dist/rag-builder.js +71 -6
- package/dist/rag-builder.js.map +1 -1
- package/dist/rag-pipeline.d.ts +2 -1
- package/dist/rag-pipeline.d.ts.map +1 -1
- package/dist/rag-pipeline.js +58 -23
- package/dist/rag-pipeline.js.map +1 -1
- package/dist/rerankers/cohere-reranker.d.ts +2 -2
- package/dist/rerankers/cohere-reranker.d.ts.map +1 -1
- package/dist/rerankers/cohere-reranker.js +5 -0
- package/dist/rerankers/cohere-reranker.js.map +1 -1
- package/dist/rerankers/index.d.ts.map +1 -1
- package/dist/rerankers/index.js.map +1 -1
- package/dist/rerankers/llm-reranker.d.ts +1 -1
- package/dist/rerankers/llm-reranker.d.ts.map +1 -1
- package/dist/rerankers/llm-reranker.js +26 -13
- package/dist/rerankers/llm-reranker.js.map +1 -1
- package/dist/retrievers/chunk-indexer.d.ts +19 -0
- package/dist/retrievers/chunk-indexer.d.ts.map +1 -0
- package/dist/retrievers/chunk-indexer.js +8 -0
- package/dist/retrievers/chunk-indexer.js.map +1 -0
- package/dist/retrievers/create-retriever.d.ts +2 -0
- package/dist/retrievers/create-retriever.d.ts.map +1 -1
- package/dist/retrievers/create-retriever.js +6 -0
- package/dist/retrievers/create-retriever.js.map +1 -1
- package/dist/retrievers/hybrid-retriever.d.ts +8 -1
- package/dist/retrievers/hybrid-retriever.d.ts.map +1 -1
- package/dist/retrievers/hybrid-retriever.js +18 -5
- package/dist/retrievers/hybrid-retriever.js.map +1 -1
- package/dist/retrievers/index.d.ts +2 -0
- package/dist/retrievers/index.d.ts.map +1 -1
- package/dist/retrievers/index.js +1 -0
- package/dist/retrievers/index.js.map +1 -1
- package/dist/retrievers/mmr-retriever.d.ts +5 -0
- package/dist/retrievers/mmr-retriever.d.ts.map +1 -1
- package/dist/retrievers/mmr-retriever.js +34 -8
- package/dist/retrievers/mmr-retriever.js.map +1 -1
- package/dist/retrievers/multi-query-retriever.d.ts +14 -1
- package/dist/retrievers/multi-query-retriever.d.ts.map +1 -1
- package/dist/retrievers/multi-query-retriever.js +50 -6
- package/dist/retrievers/multi-query-retriever.js.map +1 -1
- package/dist/retrievers/similarity-retriever.d.ts.map +1 -1
- package/dist/retrievers/similarity-retriever.js +2 -1
- package/dist/retrievers/similarity-retriever.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +16 -2
- package/dist/schema.js.map +1 -1
- package/dist/tools.d.ts +11 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +43 -9
- package/dist/tools.js.map +1 -1
- package/package.json +5 -5
package/dist/rag-pipeline.js
CHANGED
|
@@ -1,35 +1,45 @@
|
|
|
1
1
|
import { RAGPipelineConfigSchema } from './schema.js';
|
|
2
|
+
import { isChunkIndexer } from './retrievers/chunk-indexer.js';
|
|
3
|
+
const STORE_CONCURRENCY = 16;
|
|
4
|
+
function definedEntries(value) {
|
|
5
|
+
if (!value)
|
|
6
|
+
return {};
|
|
7
|
+
return Object.fromEntries(Object.entries(value).filter(([, v]) => v !== undefined));
|
|
8
|
+
}
|
|
2
9
|
export class RAGPipeline {
|
|
3
10
|
config;
|
|
4
11
|
deps;
|
|
5
12
|
stats = { documentsIngested: 0, chunksStored: 0, queriesProcessed: 0 };
|
|
6
|
-
constructor(config, deps) {
|
|
7
|
-
this.config = RAGPipelineConfigSchema.parse(config);
|
|
13
|
+
constructor(config, deps, alreadyParsed = false) {
|
|
14
|
+
this.config = alreadyParsed ? config : RAGPipelineConfigSchema.parse(config);
|
|
8
15
|
this.deps = deps;
|
|
9
16
|
}
|
|
10
17
|
async ingest(source) {
|
|
11
18
|
const documents = await this.deps.loader.load(source);
|
|
12
19
|
let totalChunks = 0;
|
|
20
|
+
let ingestedDocuments = 0;
|
|
13
21
|
for (const doc of documents) {
|
|
14
22
|
const chunks = await this.chunkDocument(doc);
|
|
15
|
-
if (chunks.length
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
await this.storeChunk(chunks[i], vectors[i], doc);
|
|
23
|
+
if (chunks.length > 0) {
|
|
24
|
+
const vectors = await this.deps.embeddingService.embedBatch(chunks.map((c) => c.content));
|
|
25
|
+
if (vectors.length !== chunks.length) {
|
|
26
|
+
throw new Error(`Embedding count mismatch: got ${vectors.length} vectors for ${chunks.length} chunks`);
|
|
27
|
+
}
|
|
28
|
+
await this.storeChunks(chunks, vectors, doc);
|
|
29
|
+
totalChunks += chunks.length;
|
|
30
|
+
this.stats.chunksStored += chunks.length;
|
|
24
31
|
}
|
|
25
|
-
|
|
32
|
+
ingestedDocuments++;
|
|
33
|
+
this.stats.documentsIngested++;
|
|
26
34
|
}
|
|
27
|
-
|
|
28
|
-
this.stats.chunksStored += totalChunks;
|
|
29
|
-
return { documents: documents.length, chunks: totalChunks };
|
|
35
|
+
return { documents: ingestedDocuments, chunks: totalChunks };
|
|
30
36
|
}
|
|
31
37
|
async query(text, options) {
|
|
32
|
-
const
|
|
38
|
+
const merged = {
|
|
39
|
+
...this.config.retrieval,
|
|
40
|
+
...definedEntries(options),
|
|
41
|
+
};
|
|
42
|
+
const results = await this.deps.retriever.retrieve(text, merged);
|
|
33
43
|
this.stats.queriesProcessed++;
|
|
34
44
|
if (this.deps.reranker && this.config.reranking?.enabled) {
|
|
35
45
|
return this.deps.reranker.rerank(text, results, this.config.reranking.topN);
|
|
@@ -40,24 +50,49 @@ export class RAGPipeline {
|
|
|
40
50
|
return { ...this.stats };
|
|
41
51
|
}
|
|
42
52
|
async chunkDocument(doc) {
|
|
43
|
-
|
|
53
|
+
const chunks = await this.deps.chunker.chunk(doc.content, doc.id);
|
|
54
|
+
return chunks.filter((chunk) => chunk.content.trim().length > 0);
|
|
55
|
+
}
|
|
56
|
+
async storeChunks(chunks, vectors, doc) {
|
|
57
|
+
let next = 0;
|
|
58
|
+
const worker = async () => {
|
|
59
|
+
while (next < chunks.length) {
|
|
60
|
+
const index = next++;
|
|
61
|
+
await this.storeChunk(chunks[index], vectors[index], doc);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
await Promise.all(Array.from({ length: Math.min(STORE_CONCURRENCY, chunks.length) }, () => worker()));
|
|
44
65
|
}
|
|
45
66
|
async storeChunk(chunk, vector, doc) {
|
|
67
|
+
const metadata = {
|
|
68
|
+
...doc.metadata,
|
|
69
|
+
...chunk.metadata,
|
|
70
|
+
documentId: doc.id,
|
|
71
|
+
source: doc.source,
|
|
72
|
+
sourceType: doc.sourceType,
|
|
73
|
+
order: chunk.order,
|
|
74
|
+
startOffset: chunk.startOffset,
|
|
75
|
+
endOffset: chunk.endOffset,
|
|
76
|
+
};
|
|
46
77
|
const result = await this.deps.embeddingAdapter.addEmbedding({
|
|
47
78
|
sourceId: chunk.id,
|
|
48
79
|
sourceType: 'document',
|
|
49
80
|
vector,
|
|
50
81
|
content: chunk.content,
|
|
51
|
-
metadata
|
|
52
|
-
...chunk.metadata,
|
|
53
|
-
documentId: doc.id,
|
|
54
|
-
source: doc.source,
|
|
55
|
-
order: chunk.order,
|
|
56
|
-
},
|
|
82
|
+
metadata,
|
|
57
83
|
});
|
|
58
84
|
if (!result.success) {
|
|
59
85
|
throw new Error(result.error);
|
|
60
86
|
}
|
|
87
|
+
if (isChunkIndexer(this.deps.retriever)) {
|
|
88
|
+
this.deps.retriever.indexChunk({
|
|
89
|
+
embeddingId: result.data.id,
|
|
90
|
+
chunkId: chunk.id,
|
|
91
|
+
documentId: doc.id,
|
|
92
|
+
content: chunk.content,
|
|
93
|
+
metadata,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
61
96
|
}
|
|
62
97
|
}
|
|
63
98
|
//# sourceMappingURL=rag-pipeline.js.map
|
package/dist/rag-pipeline.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rag-pipeline.js","sourceRoot":"","sources":["../src/rag-pipeline.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,uBAAuB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"rag-pipeline.js","sourceRoot":"","sources":["../src/rag-pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,8 +4,8 @@ export interface CohereRerankerConfig {
|
|
|
4
4
|
model?: string;
|
|
5
5
|
}
|
|
6
6
|
export declare class CohereReranker implements Reranker {
|
|
7
|
-
private apiKey;
|
|
8
|
-
private model;
|
|
7
|
+
private readonly apiKey;
|
|
8
|
+
private readonly model;
|
|
9
9
|
constructor(config: CohereRerankerConfig);
|
|
10
10
|
rerank(query: string, results: RetrievalResult[], topN?: number): Promise<RetrievalResult[]>;
|
|
11
11
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cohere-reranker.d.ts","sourceRoot":"","sources":["../../src/rerankers/cohere-reranker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"cohere-reranker.d.ts","sourceRoot":"","sources":["../../src/rerankers/cohere-reranker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAaD,qBAAa,cAAe,YAAW,QAAQ;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAEnB,MAAM,EAAE,oBAAoB;IAKlC,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,eAAe,EAAE,EAC1B,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,eAAe,EAAE,CAAC;CAwC9B"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const DEFAULT_MODEL = 'rerank-v3.5';
|
|
2
2
|
const COHERE_RERANK_URL = 'https://api.cohere.com/v2/rerank';
|
|
3
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
3
4
|
export class CohereReranker {
|
|
4
5
|
apiKey;
|
|
5
6
|
model;
|
|
@@ -23,12 +24,16 @@ export class CohereReranker {
|
|
|
23
24
|
documents: results.map((r) => r.content),
|
|
24
25
|
top_n: n,
|
|
25
26
|
}),
|
|
27
|
+
signal: AbortSignal.timeout(DEFAULT_TIMEOUT_MS),
|
|
26
28
|
});
|
|
27
29
|
if (!response.ok) {
|
|
28
30
|
const text = await response.text();
|
|
29
31
|
throw new Error(`Cohere rerank failed (${response.status}): ${text}`);
|
|
30
32
|
}
|
|
31
33
|
const data = (await response.json());
|
|
34
|
+
if (!Array.isArray(data.results)) {
|
|
35
|
+
throw new Error('Cohere rerank returned unexpected response: missing results array');
|
|
36
|
+
}
|
|
32
37
|
const mapped = data.results
|
|
33
38
|
.filter(({ index }) => index >= 0 && index < results.length)
|
|
34
39
|
.map(({ index, relevance_score }) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cohere-reranker.js","sourceRoot":"","sources":["../../src/rerankers/cohere-reranker.ts"],"names":[],"mappings":"AAcA,MAAM,aAAa,GAAG,aAAa,CAAC;AACpC,MAAM,iBAAiB,GAAG,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"cohere-reranker.js","sourceRoot":"","sources":["../../src/rerankers/cohere-reranker.ts"],"names":[],"mappings":"AAcA,MAAM,aAAa,GAAG,aAAa,CAAC;AACpC,MAAM,iBAAiB,GAAG,kCAAkC,CAAC;AAC7D,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC,MAAM,OAAO,cAAc;IACR,MAAM,CAAS;IACf,KAAK,CAAS;IAE/B,YAAY,MAA4B;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,aAAa,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,MAAM,CACV,KAAa,EACb,OAA0B,EAC1B,IAAa;QAEb,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAEpC,MAAM,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;QAEjC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,iBAAiB,EAAE;YAC9C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;aACvC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,KAAK;gBACL,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;gBACxC,KAAK,EAAE,CAAC;aACT,CAAC;YACF,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC;SAChD,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,CAAC,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAyB,CAAC;QAE7D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,mEAAmE,CAAC,CAAC;QACvF,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO;aACxB,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;aAC3D,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC,CAAC;YACpC,GAAG,OAAO,CAAC,KAAK,CAAC;YACjB,KAAK,EAAE,eAAe;SACvB,CAAC,CAAC,CAAC;QAEN,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rerankers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rerankers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rerankers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0B,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rerankers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0B,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,cAAc,EAA6B,MAAM,sBAAsB,CAAC"}
|
|
@@ -3,7 +3,7 @@ export interface LLMRerankerConfig {
|
|
|
3
3
|
generateFn: (prompt: string) => Promise<string>;
|
|
4
4
|
}
|
|
5
5
|
export declare class LLMReranker implements Reranker {
|
|
6
|
-
private generateFn;
|
|
6
|
+
private readonly generateFn;
|
|
7
7
|
constructor(config: LLMRerankerConfig);
|
|
8
8
|
rerank(query: string, results: RetrievalResult[], topN?: number): Promise<RetrievalResult[]>;
|
|
9
9
|
private buildPrompt;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-reranker.d.ts","sourceRoot":"","sources":["../../src/rerankers/llm-reranker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACjD;
|
|
1
|
+
{"version":3,"file":"llm-reranker.d.ts","sourceRoot":"","sources":["../../src/rerankers/llm-reranker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAErE,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACjD;AAID,qBAAa,WAAY,YAAW,QAAQ;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAsC;gBAErD,MAAM,EAAE,iBAAiB;IAI/B,MAAM,CACV,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,eAAe,EAAE,EAC1B,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,eAAe,EAAE,CAAC;IA2B7B,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,WAAW;CA2BpB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const MAX_DOCUMENTS_IN_PROMPT = 50;
|
|
1
2
|
export class LLMReranker {
|
|
2
3
|
generateFn;
|
|
3
4
|
constructor(config) {
|
|
@@ -21,13 +22,15 @@ export class LLMReranker {
|
|
|
21
22
|
}));
|
|
22
23
|
return topN ? reranked.slice(0, topN) : reranked;
|
|
23
24
|
}
|
|
24
|
-
catch {
|
|
25
|
+
catch (error) {
|
|
26
|
+
console.warn('[LLMReranker] Reranking failed, returning original order:', error);
|
|
25
27
|
const fallback = [...results];
|
|
26
28
|
return topN ? fallback.slice(0, topN) : fallback;
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
31
|
buildPrompt(query, results) {
|
|
30
|
-
const
|
|
32
|
+
const limited = results.slice(0, MAX_DOCUMENTS_IN_PROMPT);
|
|
33
|
+
const docs = limited.map((r, i) => `[${i}] ${r.content}`).join('\n\n');
|
|
31
34
|
return [
|
|
32
35
|
"Score each document's relevance to the query on a scale of 0-10.",
|
|
33
36
|
'Return ONLY a JSON array: [{ "index": number, "score": number }]',
|
|
@@ -39,18 +42,28 @@ export class LLMReranker {
|
|
|
39
42
|
].join('\n');
|
|
40
43
|
}
|
|
41
44
|
parseScores(response, count) {
|
|
42
|
-
const
|
|
43
|
-
if (!
|
|
45
|
+
const candidates = response.match(/\[[\s\S]*?\]/g);
|
|
46
|
+
if (!candidates)
|
|
44
47
|
throw new Error('No JSON array found in response');
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
for (let i = candidates.length - 1; i >= 0; i--) {
|
|
49
|
+
try {
|
|
50
|
+
const parsed = JSON.parse(candidates[i]);
|
|
51
|
+
if (!Array.isArray(parsed))
|
|
52
|
+
continue;
|
|
53
|
+
const scores = parsed.filter((item) => typeof item === 'object' &&
|
|
54
|
+
item !== null &&
|
|
55
|
+
typeof item.index === 'number' &&
|
|
56
|
+
typeof item.score === 'number' &&
|
|
57
|
+
item.index >= 0 &&
|
|
58
|
+
item.index < count);
|
|
59
|
+
if (scores.length > 0)
|
|
60
|
+
return scores;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
throw new Error('No valid JSON array found in response');
|
|
54
67
|
}
|
|
55
68
|
}
|
|
56
69
|
//# sourceMappingURL=llm-reranker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-reranker.js","sourceRoot":"","sources":["../../src/rerankers/llm-reranker.ts"],"names":[],"mappings":"AAMA,MAAM,OAAO,WAAW;
|
|
1
|
+
{"version":3,"file":"llm-reranker.js","sourceRoot":"","sources":["../../src/rerankers/llm-reranker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Retriever } from '@cogitator-ai/types';
|
|
2
|
+
export interface IndexedChunk {
|
|
3
|
+
embeddingId: string;
|
|
4
|
+
chunkId: string;
|
|
5
|
+
documentId: string;
|
|
6
|
+
content: string;
|
|
7
|
+
metadata: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A retriever that maintains its own index alongside the vector store
|
|
11
|
+
* (e.g. a local BM25 index). `RAGPipeline.ingest()` calls `indexChunk()` for
|
|
12
|
+
* every stored chunk.
|
|
13
|
+
*/
|
|
14
|
+
export interface ChunkIndexer {
|
|
15
|
+
indexChunk(chunk: IndexedChunk): void;
|
|
16
|
+
}
|
|
17
|
+
export declare function isChunkIndexer(retriever: Retriever): retriever is Retriever & ChunkIndexer;
|
|
18
|
+
export declare function resultSource(metadata: Record<string, unknown> | undefined, fallback: string): string;
|
|
19
|
+
//# sourceMappingURL=chunk-indexer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-indexer.d.ts","sourceRoot":"","sources":["../../src/retrievers/chunk-indexer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;CACvC;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,SAAS,GAAG,SAAS,IAAI,SAAS,GAAG,YAAY,CAE1F;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,UAG3F"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function isChunkIndexer(retriever) {
|
|
2
|
+
return typeof retriever.indexChunk === 'function';
|
|
3
|
+
}
|
|
4
|
+
export function resultSource(metadata, fallback) {
|
|
5
|
+
const source = metadata?.source;
|
|
6
|
+
return typeof source === 'string' ? source : fallback;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=chunk-indexer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunk-indexer.js","sourceRoot":"","sources":["../../src/retrievers/chunk-indexer.ts"],"names":[],"mappings":"AAmBA,MAAM,UAAU,cAAc,CAAC,SAAoB;IACjD,OAAO,OAAQ,SAAmC,CAAC,UAAU,KAAK,UAAU,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAA6C,EAAE,QAAgB;IAC1F,MAAM,MAAM,GAAG,QAAQ,EAAE,MAAM,CAAC;IAChC,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACxD,CAAC"}
|
|
@@ -26,6 +26,8 @@ interface MultiQueryDeps {
|
|
|
26
26
|
strategy: 'multi-query';
|
|
27
27
|
baseRetriever: Retriever;
|
|
28
28
|
expandQuery: (query: string) => Promise<string[]>;
|
|
29
|
+
topK?: number;
|
|
30
|
+
maxQueries?: number;
|
|
29
31
|
}
|
|
30
32
|
export type CreateRetrieverConfig = SimilarityDeps | MMRDeps | HybridDeps | MultiQueryDeps;
|
|
31
33
|
export declare function createRetriever(config: CreateRetrieverConfig): Retriever;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-retriever.d.ts","sourceRoot":"","sources":["../../src/retrievers/create-retriever.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAMzD,UAAU,iBAAiB;IACzB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED,UAAU,cAAe,SAAQ,iBAAiB;IAChD,QAAQ,EAAE,YAAY,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,OAAQ,SAAQ,iBAAiB;IACzC,QAAQ,EAAE,KAAK,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,UAAU;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;IAC3B,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,cAAc;IACtB,QAAQ,EAAE,aAAa,CAAC;IACxB,aAAa,EAAE,SAAS,CAAC;IACzB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"create-retriever.d.ts","sourceRoot":"","sources":["../../src/retrievers/create-retriever.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAMzD,UAAU,iBAAiB;IACzB,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED,UAAU,cAAe,SAAQ,iBAAiB;IAChD,QAAQ,EAAE,YAAY,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,OAAQ,SAAQ,iBAAiB;IACzC,QAAQ,EAAE,KAAK,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,UAAU;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,YAAY,CAAC;IAC3B,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,cAAc;IACtB,QAAQ,EAAE,aAAa,CAAC;IACxB,aAAa,EAAE,SAAS,CAAC;IACzB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG,OAAO,GAAG,UAAU,GAAG,cAAc,CAAC;AAE3F,wBAAgB,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,SAAS,CAwCxE"}
|
|
@@ -30,7 +30,13 @@ export function createRetriever(config) {
|
|
|
30
30
|
return new MultiQueryRetriever({
|
|
31
31
|
baseRetriever: config.baseRetriever,
|
|
32
32
|
expandQuery: config.expandQuery,
|
|
33
|
+
defaultTopK: config.topK,
|
|
34
|
+
defaultMaxQueries: config.maxQueries,
|
|
33
35
|
});
|
|
36
|
+
default: {
|
|
37
|
+
const _exhaustive = config;
|
|
38
|
+
throw new Error(`Unknown retriever strategy: ${JSON.stringify(_exhaustive)}`);
|
|
39
|
+
}
|
|
34
40
|
}
|
|
35
41
|
}
|
|
36
42
|
//# sourceMappingURL=create-retriever.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-retriever.js","sourceRoot":"","sources":["../../src/retrievers/create-retriever.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"create-retriever.js","sourceRoot":"","sources":["../../src/retrievers/create-retriever.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAsCjE,MAAM,UAAU,eAAe,CAAC,MAA6B;IAC3D,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,KAAK,YAAY;YACf,OAAO,IAAI,mBAAmB,CAAC;gBAC7B,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;gBACzC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;gBACzC,WAAW,EAAE,MAAM,CAAC,IAAI;gBACxB,gBAAgB,EAAE,MAAM,CAAC,SAAS;aACnC,CAAC,CAAC;QAEL,KAAK,KAAK;YACR,OAAO,IAAI,YAAY,CAAC;gBACtB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;gBACzC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;gBACzC,aAAa,EAAE,MAAM,CAAC,MAAM;gBAC5B,WAAW,EAAE,MAAM,CAAC,IAAI;gBACxB,gBAAgB,EAAE,MAAM,CAAC,SAAS;aACnC,CAAC,CAAC;QAEL,KAAK,QAAQ;YACX,OAAO,IAAI,eAAe,CAAC;gBACzB,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,cAAc,EAAE,MAAM,CAAC,OAAO;gBAC9B,WAAW,EAAE,MAAM,CAAC,IAAI;gBACxB,gBAAgB,EAAE,MAAM,CAAC,SAAS;aACnC,CAAC,CAAC;QAEL,KAAK,aAAa;YAChB,OAAO,IAAI,mBAAmB,CAAC;gBAC7B,aAAa,EAAE,MAAM,CAAC,aAAa;gBACnC,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,WAAW,EAAE,MAAM,CAAC,IAAI;gBACxB,iBAAiB,EAAE,MAAM,CAAC,UAAU;aACrC,CAAC,CAAC;QAEL,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,WAAW,GAAU,MAAM,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import type { Retriever, RetrievalConfig, RetrievalResult, HybridSearchWeights } from '@cogitator-ai/types';
|
|
2
2
|
import type { HybridSearch } from '@cogitator-ai/memory';
|
|
3
|
+
import { type ChunkIndexer, type IndexedChunk } from './chunk-indexer.js';
|
|
3
4
|
export interface HybridRetrieverConfig {
|
|
4
5
|
hybridSearch: HybridSearch;
|
|
5
6
|
defaultWeights?: HybridSearchWeights;
|
|
6
7
|
defaultTopK?: number;
|
|
7
8
|
defaultThreshold?: number;
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Vector + BM25 retrieval fused with reciprocal rank fusion. Chunks ingested through
|
|
12
|
+
* `RAGPipeline` are added to the HybridSearch keyword index automatically.
|
|
13
|
+
*/
|
|
14
|
+
export declare class HybridRetriever implements Retriever, ChunkIndexer {
|
|
10
15
|
private readonly hybridSearch;
|
|
11
16
|
private readonly defaultWeights?;
|
|
12
17
|
private readonly defaultTopK;
|
|
13
18
|
private readonly defaultThreshold;
|
|
19
|
+
private readonly indexed;
|
|
14
20
|
constructor(config: HybridRetrieverConfig);
|
|
21
|
+
indexChunk(chunk: IndexedChunk): void;
|
|
15
22
|
retrieve(query: string, options?: Partial<RetrievalConfig>): Promise<RetrievalResult[]>;
|
|
16
23
|
private toRetrievalResult;
|
|
17
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hybrid-retriever.d.ts","sourceRoot":"","sources":["../../src/retrievers/hybrid-retriever.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,eAAe,EACf,mBAAmB,EAEpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"hybrid-retriever.d.ts","sourceRoot":"","sources":["../../src/retrievers/hybrid-retriever.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,eAAe,EACf,mBAAmB,EAEpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAgB,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAExF,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAKD;;;GAGG;AACH,qBAAa,eAAgB,YAAW,SAAS,EAAE,YAAY;IAC7D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAsB;IACtD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;gBAE/C,MAAM,EAAE,qBAAqB;IAOzC,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAK/B,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAgB7F,OAAO,CAAC,iBAAiB;CAoB1B"}
|
|
@@ -1,16 +1,26 @@
|
|
|
1
|
+
import { resultSource } from './chunk-indexer.js';
|
|
1
2
|
const DEFAULT_TOP_K = 10;
|
|
2
3
|
const DEFAULT_THRESHOLD = 0.0;
|
|
4
|
+
/**
|
|
5
|
+
* Vector + BM25 retrieval fused with reciprocal rank fusion. Chunks ingested through
|
|
6
|
+
* `RAGPipeline` are added to the HybridSearch keyword index automatically.
|
|
7
|
+
*/
|
|
3
8
|
export class HybridRetriever {
|
|
4
9
|
hybridSearch;
|
|
5
10
|
defaultWeights;
|
|
6
11
|
defaultTopK;
|
|
7
12
|
defaultThreshold;
|
|
13
|
+
indexed = new Map();
|
|
8
14
|
constructor(config) {
|
|
9
15
|
this.hybridSearch = config.hybridSearch;
|
|
10
16
|
this.defaultWeights = config.defaultWeights;
|
|
11
17
|
this.defaultTopK = config.defaultTopK ?? DEFAULT_TOP_K;
|
|
12
18
|
this.defaultThreshold = config.defaultThreshold ?? DEFAULT_THRESHOLD;
|
|
13
19
|
}
|
|
20
|
+
indexChunk(chunk) {
|
|
21
|
+
this.indexed.set(chunk.embeddingId, chunk);
|
|
22
|
+
this.hybridSearch.indexDocument(chunk.embeddingId, chunk.content);
|
|
23
|
+
}
|
|
14
24
|
async retrieve(query, options) {
|
|
15
25
|
const result = await this.hybridSearch.search({
|
|
16
26
|
query,
|
|
@@ -25,16 +35,19 @@ export class HybridRetriever {
|
|
|
25
35
|
return result.data.map((entry) => this.toRetrievalResult(entry));
|
|
26
36
|
}
|
|
27
37
|
toRetrievalResult(entry) {
|
|
28
|
-
const
|
|
29
|
-
const
|
|
38
|
+
const known = this.indexed.get(entry.id);
|
|
39
|
+
const metadata = { ...known?.metadata, ...entry.metadata };
|
|
40
|
+
const rawDocId = metadata.documentId;
|
|
41
|
+
const chunkId = known?.chunkId ?? entry.sourceId;
|
|
42
|
+
const documentId = typeof rawDocId === 'string' ? rawDocId : chunkId;
|
|
30
43
|
return {
|
|
31
|
-
chunkId
|
|
44
|
+
chunkId,
|
|
32
45
|
documentId,
|
|
33
46
|
content: entry.content,
|
|
34
47
|
score: entry.score,
|
|
35
|
-
source: entry.sourceType,
|
|
48
|
+
source: resultSource(metadata, entry.sourceType),
|
|
36
49
|
metadata: {
|
|
37
|
-
...
|
|
50
|
+
...metadata,
|
|
38
51
|
vectorScore: entry.vectorScore,
|
|
39
52
|
keywordScore: entry.keywordScore,
|
|
40
53
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hybrid-retriever.js","sourceRoot":"","sources":["../../src/retrievers/hybrid-retriever.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hybrid-retriever.js","sourceRoot":"","sources":["../../src/retrievers/hybrid-retriever.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAwC,MAAM,oBAAoB,CAAC;AASxF,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAE9B;;;GAGG;AACH,MAAM,OAAO,eAAe;IACT,YAAY,CAAe;IAC3B,cAAc,CAAuB;IACrC,WAAW,CAAS;IACpB,gBAAgB,CAAS;IACzB,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;IAE3D,YAAY,MAA6B;QACvC,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;QACxC,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;QAC5C,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,aAAa,CAAC;QACvD,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,IAAI,iBAAiB,CAAC;IACvE,CAAC;IAED,UAAU,CAAC,KAAmB;QAC5B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QAC3C,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACpE,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAa,EAAE,OAAkC;QAC9D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;YAC5C,KAAK;YACL,QAAQ,EAAE,QAAQ;YAClB,OAAO,EAAE,IAAI,CAAC,cAAc;YAC5B,KAAK,EAAE,OAAO,EAAE,IAAI,IAAI,IAAI,CAAC,WAAW;YACxC,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI,CAAC,gBAAgB;SACvD,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAED,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,CAAC;IAEO,iBAAiB,CAAC,KAAmB;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,EAAE,GAAG,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3D,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC;QACrC,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,IAAI,KAAK,CAAC,QAAQ,CAAC;QACjD,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;QAErE,OAAO;YACL,OAAO;YACP,UAAU;YACV,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,MAAM,EAAE,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC;YAChD,QAAQ,EAAE;gBACR,GAAG,QAAQ;gBACX,WAAW,EAAE,KAAK,CAAC,WAAW;gBAC9B,YAAY,EAAE,KAAK,CAAC,YAAY;aACjC;SACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -8,4 +8,6 @@ export { MultiQueryRetriever } from './multi-query-retriever.js';
|
|
|
8
8
|
export type { MultiQueryRetrieverConfig } from './multi-query-retriever.js';
|
|
9
9
|
export { createRetriever } from './create-retriever.js';
|
|
10
10
|
export type { CreateRetrieverConfig } from './create-retriever.js';
|
|
11
|
+
export { isChunkIndexer } from './chunk-indexer.js';
|
|
12
|
+
export type { ChunkIndexer, IndexedChunk } from './chunk-indexer.js';
|
|
11
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/retrievers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/retrievers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,YAAY,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,YAAY,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/retrievers/index.js
CHANGED
|
@@ -3,4 +3,5 @@ export { MMRRetriever } from './mmr-retriever.js';
|
|
|
3
3
|
export { HybridRetriever } from './hybrid-retriever.js';
|
|
4
4
|
export { MultiQueryRetriever } from './multi-query-retriever.js';
|
|
5
5
|
export { createRetriever } from './create-retriever.js';
|
|
6
|
+
export { isChunkIndexer } from './chunk-indexer.js';
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/retrievers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/retrievers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -14,6 +14,11 @@ export declare class MMRRetriever implements Retriever {
|
|
|
14
14
|
private readonly defaultThreshold;
|
|
15
15
|
constructor(config: MMRRetrieverConfig);
|
|
16
16
|
retrieve(query: string, options?: Partial<RetrievalConfig>): Promise<RetrievalResult[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Some vector stores (e.g. Qdrant) do not return stored vectors from search.
|
|
19
|
+
* Missing candidate vectors are re-embedded so diversity can still be computed.
|
|
20
|
+
*/
|
|
21
|
+
private ensureVectors;
|
|
17
22
|
private selectMMR;
|
|
18
23
|
private toRetrievalResult;
|
|
19
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mmr-retriever.d.ts","sourceRoot":"","sources":["../../src/retrievers/mmr-retriever.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAEhB,SAAS,EACT,eAAe,EACf,eAAe,EAChB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"mmr-retriever.d.ts","sourceRoot":"","sources":["../../src/retrievers/mmr-retriever.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAEhB,SAAS,EACT,eAAe,EACf,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,kBAAkB;IACjC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAyBD,qBAAa,YAAa,YAAW,SAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;IAC7C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;gBAE9B,MAAM,EAAE,kBAAkB;IAQhC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAyB7F;;;OAGG;YACW,aAAa;IAsB3B,OAAO,CAAC,SAAS;IAuCjB,OAAO,CAAC,iBAAiB;CAa1B"}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import { resultSource } from './chunk-indexer.js';
|
|
1
2
|
const DEFAULT_TOP_K = 10;
|
|
2
3
|
const DEFAULT_THRESHOLD = 0.0;
|
|
3
4
|
const DEFAULT_LAMBDA = 0.7;
|
|
4
5
|
const CANDIDATE_MULTIPLIER = 3;
|
|
5
6
|
function cosineSimilarity(a, b) {
|
|
6
|
-
|
|
7
|
+
if (a.length !== b.length) {
|
|
8
|
+
throw new Error(`Vector dimension mismatch: ${a.length} vs ${b.length}`);
|
|
9
|
+
}
|
|
7
10
|
let dot = 0;
|
|
8
11
|
let normA = 0;
|
|
9
12
|
let normB = 0;
|
|
10
|
-
for (let i = 0; i <
|
|
13
|
+
for (let i = 0; i < a.length; i++) {
|
|
11
14
|
dot += a[i] * b[i];
|
|
12
15
|
normA += a[i] * a[i];
|
|
13
16
|
normB += b[i] * b[i];
|
|
@@ -44,11 +47,32 @@ export class MMRRetriever {
|
|
|
44
47
|
const candidates = result.data;
|
|
45
48
|
if (candidates.length === 0)
|
|
46
49
|
return [];
|
|
47
|
-
const
|
|
50
|
+
const lambda = options?.mmrLambda ?? this.defaultLambda;
|
|
51
|
+
const withVectors = await this.ensureVectors(candidates);
|
|
52
|
+
const selected = this.selectMMR(withVectors, topK, lambda);
|
|
48
53
|
return selected.map((entry) => this.toRetrievalResult(entry));
|
|
49
54
|
}
|
|
50
|
-
|
|
51
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Some vector stores (e.g. Qdrant) do not return stored vectors from search.
|
|
57
|
+
* Missing candidate vectors are re-embedded so diversity can still be computed.
|
|
58
|
+
*/
|
|
59
|
+
async ensureVectors(candidates) {
|
|
60
|
+
const missing = candidates
|
|
61
|
+
.map((candidate, index) => ({ candidate, index }))
|
|
62
|
+
.filter(({ candidate }) => !candidate.vector || candidate.vector.length === 0);
|
|
63
|
+
if (missing.length === 0)
|
|
64
|
+
return candidates;
|
|
65
|
+
const vectors = await this.embedding.embedBatch(missing.map(({ candidate }) => candidate.content));
|
|
66
|
+
if (vectors.length !== missing.length) {
|
|
67
|
+
throw new Error(`Embedding count mismatch: got ${vectors.length} vectors for ${missing.length} candidates`);
|
|
68
|
+
}
|
|
69
|
+
const result = [...candidates];
|
|
70
|
+
missing.forEach(({ candidate, index }, i) => {
|
|
71
|
+
result[index] = { ...candidate, vector: vectors[i] };
|
|
72
|
+
});
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
selectMMR(candidates, topK, lambda) {
|
|
52
76
|
const remaining = new Set(candidates.map((_, i) => i));
|
|
53
77
|
const selected = [];
|
|
54
78
|
while (selected.length < topK && remaining.size > 0) {
|
|
@@ -56,12 +80,14 @@ export class MMRRetriever {
|
|
|
56
80
|
let bestScore = -Infinity;
|
|
57
81
|
for (const idx of remaining) {
|
|
58
82
|
const relevance = candidates[idx].score;
|
|
59
|
-
let maxSelectedSim =
|
|
83
|
+
let maxSelectedSim = -Infinity;
|
|
60
84
|
for (const sel of selected) {
|
|
61
85
|
const sim = cosineSimilarity(candidates[idx].vector, sel.vector);
|
|
62
86
|
if (sim > maxSelectedSim)
|
|
63
87
|
maxSelectedSim = sim;
|
|
64
88
|
}
|
|
89
|
+
if (maxSelectedSim === -Infinity)
|
|
90
|
+
maxSelectedSim = 0;
|
|
65
91
|
const mmrScore = lambda * relevance - (1 - lambda) * maxSelectedSim;
|
|
66
92
|
if (mmrScore > bestScore) {
|
|
67
93
|
bestScore = mmrScore;
|
|
@@ -83,8 +109,8 @@ export class MMRRetriever {
|
|
|
83
109
|
documentId,
|
|
84
110
|
content: entry.content,
|
|
85
111
|
score: entry.mmrScore,
|
|
86
|
-
source: entry.sourceType,
|
|
87
|
-
metadata: entry.metadata,
|
|
112
|
+
source: resultSource(entry.metadata, entry.sourceType),
|
|
113
|
+
metadata: { ...entry.metadata, originalScore: entry.score },
|
|
88
114
|
};
|
|
89
115
|
}
|
|
90
116
|
}
|