@mcp-abap-adt/llm-agent 6.0.2 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/llm-providers/anthropic.d.ts +1 -0
- package/dist/llm-providers/anthropic.d.ts.map +1 -1
- package/dist/llm-providers/anthropic.js +3 -0
- package/dist/llm-providers/anthropic.js.map +1 -1
- package/dist/llm-providers/base.d.ts +4 -0
- package/dist/llm-providers/base.d.ts.map +1 -1
- package/dist/llm-providers/base.js.map +1 -1
- package/dist/llm-providers/deepseek.d.ts +1 -0
- package/dist/llm-providers/deepseek.d.ts.map +1 -1
- package/dist/llm-providers/deepseek.js +3 -0
- package/dist/llm-providers/deepseek.js.map +1 -1
- package/dist/llm-providers/openai.d.ts +1 -0
- package/dist/llm-providers/openai.d.ts.map +1 -1
- package/dist/llm-providers/openai.js +6 -0
- package/dist/llm-providers/openai.js.map +1 -1
- package/dist/llm-providers/sap-core-ai.d.ts +6 -0
- package/dist/llm-providers/sap-core-ai.d.ts.map +1 -1
- package/dist/llm-providers/sap-core-ai.js +13 -2
- package/dist/llm-providers/sap-core-ai.js.map +1 -1
- package/dist/smart-agent/adapters/llm-adapter.d.ts +4 -2
- package/dist/smart-agent/adapters/llm-adapter.d.ts.map +1 -1
- package/dist/smart-agent/adapters/llm-adapter.js +26 -0
- package/dist/smart-agent/adapters/llm-adapter.js.map +1 -1
- package/dist/smart-agent/agent.d.ts +27 -1
- package/dist/smart-agent/agent.d.ts.map +1 -1
- package/dist/smart-agent/agent.js +79 -20
- package/dist/smart-agent/agent.js.map +1 -1
- package/dist/smart-agent/builder.d.ts.map +1 -1
- package/dist/smart-agent/builder.js +18 -5
- package/dist/smart-agent/builder.js.map +1 -1
- package/dist/smart-agent/config.d.ts +1 -1
- package/dist/smart-agent/config.d.ts.map +1 -1
- package/dist/smart-agent/config.js +1 -1
- package/dist/smart-agent/interfaces/model-provider.d.ts +7 -1
- package/dist/smart-agent/interfaces/model-provider.d.ts.map +1 -1
- package/dist/smart-agent/interfaces/pipeline.d.ts +7 -0
- package/dist/smart-agent/interfaces/pipeline.d.ts.map +1 -1
- package/dist/smart-agent/interfaces/query-embedding.d.ts +3 -0
- package/dist/smart-agent/interfaces/query-embedding.d.ts.map +1 -1
- package/dist/smart-agent/interfaces/rag.d.ts +9 -2
- package/dist/smart-agent/interfaces/rag.d.ts.map +1 -1
- package/dist/smart-agent/interfaces/rag.js.map +1 -1
- package/dist/smart-agent/pipeline/context.d.ts +2 -0
- package/dist/smart-agent/pipeline/context.d.ts.map +1 -1
- package/dist/smart-agent/pipeline/default-pipeline.d.ts +5 -2
- package/dist/smart-agent/pipeline/default-pipeline.d.ts.map +1 -1
- package/dist/smart-agent/pipeline/default-pipeline.js +24 -5
- package/dist/smart-agent/pipeline/default-pipeline.js.map +1 -1
- package/dist/smart-agent/pipeline/handlers/classify.d.ts.map +1 -1
- package/dist/smart-agent/pipeline/handlers/classify.js +10 -1
- package/dist/smart-agent/pipeline/handlers/classify.js.map +1 -1
- package/dist/smart-agent/pipeline/handlers/rag-query.d.ts.map +1 -1
- package/dist/smart-agent/pipeline/handlers/rag-query.js +16 -0
- package/dist/smart-agent/pipeline/handlers/rag-query.js.map +1 -1
- package/dist/smart-agent/pipeline/handlers/tool-loop.js +1 -1
- package/dist/smart-agent/pipeline/handlers/tool-loop.js.map +1 -1
- package/dist/smart-agent/pipeline/handlers/tool-select.js +1 -1
- package/dist/smart-agent/pipeline/handlers/tool-select.js.map +1 -1
- package/dist/smart-agent/providers.d.ts +8 -0
- package/dist/smart-agent/providers.d.ts.map +1 -1
- package/dist/smart-agent/providers.js +21 -1
- package/dist/smart-agent/providers.js.map +1 -1
- package/dist/smart-agent/rag/in-memory-rag.d.ts +7 -0
- package/dist/smart-agent/rag/in-memory-rag.d.ts.map +1 -1
- package/dist/smart-agent/rag/in-memory-rag.js +21 -5
- package/dist/smart-agent/rag/in-memory-rag.js.map +1 -1
- package/dist/smart-agent/rag/index.d.ts +4 -0
- package/dist/smart-agent/rag/index.d.ts.map +1 -1
- package/dist/smart-agent/rag/index.js +2 -0
- package/dist/smart-agent/rag/index.js.map +1 -1
- package/dist/smart-agent/rag/ollama-rag.d.ts +3 -3
- package/dist/smart-agent/rag/ollama-rag.d.ts.map +1 -1
- package/dist/smart-agent/rag/ollama-rag.js +2 -2
- package/dist/smart-agent/rag/ollama-rag.js.map +1 -1
- package/dist/smart-agent/rag/openai-embedder.d.ts +3 -3
- package/dist/smart-agent/rag/openai-embedder.d.ts.map +1 -1
- package/dist/smart-agent/rag/openai-embedder.js +19 -2
- package/dist/smart-agent/rag/openai-embedder.js.map +1 -1
- package/dist/smart-agent/rag/preprocessor.d.ts +82 -0
- package/dist/smart-agent/rag/preprocessor.d.ts.map +1 -0
- package/dist/smart-agent/rag/preprocessor.js +203 -0
- package/dist/smart-agent/rag/preprocessor.js.map +1 -0
- package/dist/smart-agent/rag/qdrant-rag.js +1 -1
- package/dist/smart-agent/rag/qdrant-rag.js.map +1 -1
- package/dist/smart-agent/rag/query-embedding.d.ts +4 -2
- package/dist/smart-agent/rag/query-embedding.d.ts.map +1 -1
- package/dist/smart-agent/rag/query-embedding.js +10 -4
- package/dist/smart-agent/rag/query-embedding.js.map +1 -1
- package/dist/smart-agent/rag/sap-ai-core-embedder.d.ts +3 -3
- package/dist/smart-agent/rag/sap-ai-core-embedder.d.ts.map +1 -1
- package/dist/smart-agent/rag/sap-ai-core-embedder.js +4 -4
- package/dist/smart-agent/rag/sap-ai-core-embedder.js.map +1 -1
- package/dist/smart-agent/rag/search-strategy.d.ts +89 -0
- package/dist/smart-agent/rag/search-strategy.d.ts.map +1 -0
- package/dist/smart-agent/rag/search-strategy.js +200 -0
- package/dist/smart-agent/rag/search-strategy.js.map +1 -0
- package/dist/smart-agent/rag/tool-indexing-strategy.d.ts +58 -0
- package/dist/smart-agent/rag/tool-indexing-strategy.d.ts.map +1 -0
- package/dist/smart-agent/rag/tool-indexing-strategy.js +130 -0
- package/dist/smart-agent/rag/tool-indexing-strategy.js.map +1 -0
- package/dist/smart-agent/rag/vector-rag.d.ts +11 -5
- package/dist/smart-agent/rag/vector-rag.d.ts.map +1 -1
- package/dist/smart-agent/rag/vector-rag.js +55 -46
- package/dist/smart-agent/rag/vector-rag.js.map +1 -1
- package/dist/smart-agent/resilience/circuit-breaker-embedder.d.ts +3 -3
- package/dist/smart-agent/resilience/circuit-breaker-embedder.d.ts.map +1 -1
- package/dist/smart-agent/smart-server.d.ts.map +1 -1
- package/dist/smart-agent/smart-server.js +29 -1
- package/dist/smart-agent/smart-server.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Module-private helpers (reused by all strategies in this file)
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
function cosine(a, b) {
|
|
5
|
+
let dot = 0;
|
|
6
|
+
let na = 0;
|
|
7
|
+
let nb = 0;
|
|
8
|
+
for (let i = 0; i < a.length; i++) {
|
|
9
|
+
dot += a[i] * b[i];
|
|
10
|
+
na += a[i] ** 2;
|
|
11
|
+
nb += b[i] ** 2;
|
|
12
|
+
}
|
|
13
|
+
return dot / (Math.sqrt(na) * Math.sqrt(nb) || 1);
|
|
14
|
+
}
|
|
15
|
+
function bm25(queryTokens, docText, context) {
|
|
16
|
+
const docTokens = context.tokenize(docText);
|
|
17
|
+
if (queryTokens.length === 0 || docTokens.length === 0)
|
|
18
|
+
return 0;
|
|
19
|
+
const avgDocLength = context.index.avgDocLength || 1;
|
|
20
|
+
const n = context.index.docCount || 1;
|
|
21
|
+
const k1 = 1.2;
|
|
22
|
+
const b = 0.75;
|
|
23
|
+
let score = 0;
|
|
24
|
+
for (const token of new Set(queryTokens)) {
|
|
25
|
+
const df = context.index.getDocFrequency(token);
|
|
26
|
+
const idf = Math.log((n - df + 0.5) / (df + 0.5) + 1);
|
|
27
|
+
const tf = docTokens.filter((t) => t === token).length;
|
|
28
|
+
const tfScored = (tf * (k1 + 1)) /
|
|
29
|
+
(tf + k1 * (1 - b + b * (docTokens.length / avgDocLength)));
|
|
30
|
+
score += idf * tfScored;
|
|
31
|
+
}
|
|
32
|
+
return Math.min(score / 5, 1.0);
|
|
33
|
+
}
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// WeightedFusionStrategy
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
export class WeightedFusionStrategy {
|
|
38
|
+
name = 'weighted-fusion';
|
|
39
|
+
vectorWeight;
|
|
40
|
+
keywordWeight;
|
|
41
|
+
constructor(config) {
|
|
42
|
+
this.vectorWeight = config?.vectorWeight ?? 0.7;
|
|
43
|
+
this.keywordWeight = config?.keywordWeight ?? 0.3;
|
|
44
|
+
}
|
|
45
|
+
score(query, candidates, context) {
|
|
46
|
+
const queryTokens = context.tokenize(query.text);
|
|
47
|
+
return candidates
|
|
48
|
+
.map((c) => ({
|
|
49
|
+
text: c.text,
|
|
50
|
+
metadata: c.metadata,
|
|
51
|
+
score: cosine(query.vector, c.vector) * this.vectorWeight +
|
|
52
|
+
bm25(queryTokens, c.text, context) * this.keywordWeight,
|
|
53
|
+
}))
|
|
54
|
+
.sort((a, b) => b.score - a.score);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// RrfStrategy
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
/**
|
|
61
|
+
* Reciprocal Rank Fusion: combines vector and BM25 rankings using
|
|
62
|
+
* `score(doc) = 1/(k + rank_vector) + 1/(k + rank_bm25)`.
|
|
63
|
+
*
|
|
64
|
+
* RRF is rank-based — it doesn't depend on raw score magnitudes,
|
|
65
|
+
* which makes it more stable than weighted sum when vector and BM25
|
|
66
|
+
* score distributions differ.
|
|
67
|
+
*/
|
|
68
|
+
export class RrfStrategy {
|
|
69
|
+
name = 'rrf';
|
|
70
|
+
k;
|
|
71
|
+
constructor(config) {
|
|
72
|
+
this.k = config?.k ?? 60;
|
|
73
|
+
}
|
|
74
|
+
score(query, candidates, context) {
|
|
75
|
+
const queryTokens = context.tokenize(query.text);
|
|
76
|
+
// Score by each method independently
|
|
77
|
+
const vectorScores = candidates.map((c, i) => ({
|
|
78
|
+
idx: i,
|
|
79
|
+
score: cosine(query.vector, c.vector),
|
|
80
|
+
}));
|
|
81
|
+
const bm25Scores = candidates.map((c, i) => ({
|
|
82
|
+
idx: i,
|
|
83
|
+
score: bm25(queryTokens, c.text, context),
|
|
84
|
+
}));
|
|
85
|
+
// Sort each list desc to get ranks
|
|
86
|
+
vectorScores.sort((a, b) => b.score - a.score);
|
|
87
|
+
bm25Scores.sort((a, b) => b.score - a.score);
|
|
88
|
+
// Build rank maps (0-indexed rank)
|
|
89
|
+
const vectorRank = new Map();
|
|
90
|
+
const bm25Rank = new Map();
|
|
91
|
+
for (let i = 0; i < vectorScores.length; i++)
|
|
92
|
+
vectorRank.set(vectorScores[i].idx, i);
|
|
93
|
+
for (let i = 0; i < bm25Scores.length; i++)
|
|
94
|
+
bm25Rank.set(bm25Scores[i].idx, i);
|
|
95
|
+
// Compute RRF score
|
|
96
|
+
return candidates
|
|
97
|
+
.map((c, i) => ({
|
|
98
|
+
text: c.text,
|
|
99
|
+
metadata: c.metadata,
|
|
100
|
+
score: 1 / (this.k + (vectorRank.get(i) ?? candidates.length)) +
|
|
101
|
+
1 / (this.k + (bm25Rank.get(i) ?? candidates.length)),
|
|
102
|
+
}))
|
|
103
|
+
.sort((a, b) => b.score - a.score);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// VectorOnlyStrategy
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
/**
|
|
110
|
+
* Pure vector cosine similarity. No keyword component.
|
|
111
|
+
* Useful as a baseline or when BM25 tokenization doesn't match the domain.
|
|
112
|
+
*/
|
|
113
|
+
export class VectorOnlyStrategy {
|
|
114
|
+
name = 'vector-only';
|
|
115
|
+
score(query, candidates, _context) {
|
|
116
|
+
return candidates
|
|
117
|
+
.map((c) => ({
|
|
118
|
+
text: c.text,
|
|
119
|
+
metadata: c.metadata,
|
|
120
|
+
score: cosine(query.vector, c.vector),
|
|
121
|
+
}))
|
|
122
|
+
.sort((a, b) => b.score - a.score);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// Bm25OnlyStrategy
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
/**
|
|
129
|
+
* Pure BM25 lexical scoring. No vector component.
|
|
130
|
+
* Useful when embedder is unavailable or for exact-match-heavy domains.
|
|
131
|
+
*/
|
|
132
|
+
export class Bm25OnlyStrategy {
|
|
133
|
+
name = 'bm25-only';
|
|
134
|
+
score(query, candidates, context) {
|
|
135
|
+
const queryTokens = context.tokenize(query.text);
|
|
136
|
+
return candidates
|
|
137
|
+
.map((c) => ({
|
|
138
|
+
text: c.text,
|
|
139
|
+
metadata: c.metadata,
|
|
140
|
+
score: bm25(queryTokens, c.text, context),
|
|
141
|
+
}))
|
|
142
|
+
.sort((a, b) => b.score - a.score);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Combines multiple strategies via weighted Reciprocal Rank Fusion.
|
|
147
|
+
*
|
|
148
|
+
* Each child strategy scores all candidates independently.
|
|
149
|
+
* Results are merged using: `score(doc) = Σ weight_i / (k + rank_i)`
|
|
150
|
+
*
|
|
151
|
+
* All child strategies run synchronously on the same candidates —
|
|
152
|
+
* no I/O, pure CPU, single event-loop tick.
|
|
153
|
+
*/
|
|
154
|
+
export class CompositeStrategy {
|
|
155
|
+
name;
|
|
156
|
+
entries;
|
|
157
|
+
k;
|
|
158
|
+
constructor(entries, config) {
|
|
159
|
+
this.entries = entries;
|
|
160
|
+
this.k = config?.k ?? 60;
|
|
161
|
+
this.name = `composite(${entries.map((e) => e.strategy.name).join('+')})`;
|
|
162
|
+
}
|
|
163
|
+
score(query, candidates, context) {
|
|
164
|
+
if (candidates.length === 0)
|
|
165
|
+
return [];
|
|
166
|
+
// Run all strategies on the same candidates
|
|
167
|
+
const rankedLists = this.entries.map((entry) => {
|
|
168
|
+
const scored = entry.strategy.score(query, candidates, context);
|
|
169
|
+
// Build rank map: metadata.id → rank (0-indexed)
|
|
170
|
+
const rankMap = new Map();
|
|
171
|
+
for (let i = 0; i < scored.length; i++) {
|
|
172
|
+
const id = scored[i].metadata.id;
|
|
173
|
+
// For dual-index: same tool may appear multiple times.
|
|
174
|
+
// Keep best rank (first occurrence = highest score).
|
|
175
|
+
if (!rankMap.has(id))
|
|
176
|
+
rankMap.set(id, i);
|
|
177
|
+
}
|
|
178
|
+
return { rankMap, weight: entry.weight };
|
|
179
|
+
});
|
|
180
|
+
// Compute weighted RRF per candidate
|
|
181
|
+
const scoreMap = new Map();
|
|
182
|
+
for (const c of candidates) {
|
|
183
|
+
const id = c.metadata.id;
|
|
184
|
+
if (scoreMap.has(id))
|
|
185
|
+
continue; // dedup by id — take first occurrence
|
|
186
|
+
let totalScore = 0;
|
|
187
|
+
for (const { rankMap, weight } of rankedLists) {
|
|
188
|
+
const rank = rankMap.get(id) ?? candidates.length;
|
|
189
|
+
totalScore += weight / (this.k + rank);
|
|
190
|
+
}
|
|
191
|
+
scoreMap.set(id, {
|
|
192
|
+
text: c.text,
|
|
193
|
+
metadata: c.metadata,
|
|
194
|
+
score: totalScore,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return [...scoreMap.values()].sort((a, b) => b.score - a.score);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=search-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-strategy.js","sourceRoot":"","sources":["../../../src/smart-agent/rag/search-strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ILlm } from '../interfaces/llm.js';
|
|
2
|
+
import type { IRequestLogger } from '../interfaces/request-logger.js';
|
|
3
|
+
import type { CallOptions } from '../interfaces/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* A tool description to be indexed in RAG.
|
|
6
|
+
*/
|
|
7
|
+
export interface IToolDescriptor {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A text variant to upsert into RAG. Each variant gets its own embedding.
|
|
13
|
+
* Multiple variants per tool = broader recall.
|
|
14
|
+
*/
|
|
15
|
+
export interface IToolIndexEntry {
|
|
16
|
+
/** RAG record id. Format: tool:<name>[:<suffix>] */
|
|
17
|
+
id: string;
|
|
18
|
+
/** Text to embed and store. */
|
|
19
|
+
text: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generates text variants for tool indexing in RAG.
|
|
23
|
+
* Each strategy produces one or more entries per tool.
|
|
24
|
+
* Strategies can be combined — builder upserts all entries from all strategies.
|
|
25
|
+
*/
|
|
26
|
+
export interface IToolIndexingStrategy {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
prepare(tool: IToolDescriptor, options?: CallOptions): Promise<IToolIndexEntry[]>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Indexes the raw tool description as-is.
|
|
32
|
+
* This is the current default behavior.
|
|
33
|
+
*/
|
|
34
|
+
export declare class OriginalToolIndexing implements IToolIndexingStrategy {
|
|
35
|
+
readonly name = "original";
|
|
36
|
+
prepare(tool: IToolDescriptor): Promise<IToolIndexEntry[]>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* LLM generates concise intent keywords for the tool.
|
|
40
|
+
* Indexed alongside the original for broader keyword coverage.
|
|
41
|
+
*/
|
|
42
|
+
export declare class IntentToolIndexing implements IToolIndexingStrategy {
|
|
43
|
+
private readonly llm;
|
|
44
|
+
private readonly requestLogger?;
|
|
45
|
+
readonly name = "intent";
|
|
46
|
+
constructor(llm: ILlm, requestLogger?: IRequestLogger | undefined);
|
|
47
|
+
prepare(tool: IToolDescriptor, options?: CallOptions): Promise<IToolIndexEntry[]>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Adds action verb synonyms to the tool description.
|
|
51
|
+
* E.g. "ReadClass" → also indexed with "show class, display class, view class".
|
|
52
|
+
* Purely deterministic — no LLM needed.
|
|
53
|
+
*/
|
|
54
|
+
export declare class SynonymToolIndexing implements IToolIndexingStrategy {
|
|
55
|
+
readonly name = "synonym";
|
|
56
|
+
prepare(tool: IToolDescriptor): Promise<IToolIndexEntry[]>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=tool-indexing-strategy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-indexing-strategy.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/rag/tool-indexing-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,oDAAoD;IACpD,EAAE,EAAE,MAAM,CAAC;IACX,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CACL,IAAI,EAAE,eAAe,EACrB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;CAC/B;AAMD;;;GAGG;AACH,qBAAa,oBAAqB,YAAW,qBAAqB;IAChE,QAAQ,CAAC,IAAI,cAAc;IAErB,OAAO,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAQjE;AAmBD;;;GAGG;AACH,qBAAa,kBAAmB,YAAW,qBAAqB;IAI5D,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IAJjC,QAAQ,CAAC,IAAI,YAAY;gBAGN,GAAG,EAAE,IAAI,EACT,aAAa,CAAC,EAAE,cAAc,YAAA;IAG3C,OAAO,CACX,IAAI,EAAE,eAAe,EACrB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,eAAe,EAAE,CAAC;CAqC9B;AAmBD;;;;GAIG;AACH,qBAAa,mBAAoB,YAAW,qBAAqB;IAC/D,QAAQ,CAAC,IAAI,aAAa;IAEpB,OAAO,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CA6BjE"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Original — current behavior: "Tool: name — description"
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
/**
|
|
5
|
+
* Indexes the raw tool description as-is.
|
|
6
|
+
* This is the current default behavior.
|
|
7
|
+
*/
|
|
8
|
+
export class OriginalToolIndexing {
|
|
9
|
+
name = 'original';
|
|
10
|
+
async prepare(tool) {
|
|
11
|
+
return [
|
|
12
|
+
{
|
|
13
|
+
id: `tool:${tool.name}`,
|
|
14
|
+
text: `${tool.name}: ${tool.description}`,
|
|
15
|
+
},
|
|
16
|
+
];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Intent — LLM generates concise keyword phrases
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
const INTENT_PROMPT = `You receive a tool description with its name and parameters.
|
|
23
|
+
Extract the core INTENT in 3-5 short keyword phrases that a user would type when needing this tool.
|
|
24
|
+
Focus on WHAT the tool does, not HOW. Use simple action words.
|
|
25
|
+
|
|
26
|
+
Format: return ONLY the keyword phrases separated by commas, no explanation.
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
- Input: "GetTableContents: Retrieve contents (data preview) of an ABAP database table or CDS view."
|
|
30
|
+
Output: table data preview, read table contents, SE16 data, select from table, show table rows
|
|
31
|
+
|
|
32
|
+
- Input: "SearchObject: Find, search, locate, or check if an ABAP repository object exists by name or wildcard pattern."
|
|
33
|
+
Output: search object by name, find ABAP object, locate program class table, does object exist, wildcard search`;
|
|
34
|
+
/**
|
|
35
|
+
* LLM generates concise intent keywords for the tool.
|
|
36
|
+
* Indexed alongside the original for broader keyword coverage.
|
|
37
|
+
*/
|
|
38
|
+
export class IntentToolIndexing {
|
|
39
|
+
llm;
|
|
40
|
+
requestLogger;
|
|
41
|
+
name = 'intent';
|
|
42
|
+
constructor(llm, requestLogger) {
|
|
43
|
+
this.llm = llm;
|
|
44
|
+
this.requestLogger = requestLogger;
|
|
45
|
+
}
|
|
46
|
+
async prepare(tool, options) {
|
|
47
|
+
const inputText = `${tool.name}: ${tool.description}`;
|
|
48
|
+
try {
|
|
49
|
+
const chatStart = Date.now();
|
|
50
|
+
const res = await this.llm.chat([
|
|
51
|
+
{ role: 'system', content: INTENT_PROMPT },
|
|
52
|
+
{ role: 'user', content: inputText },
|
|
53
|
+
], [], options);
|
|
54
|
+
if (this.requestLogger) {
|
|
55
|
+
this.requestLogger.logLlmCall({
|
|
56
|
+
component: 'helper',
|
|
57
|
+
model: this.llm.model ?? 'unknown',
|
|
58
|
+
promptTokens: res.ok ? (res.value.usage?.promptTokens ?? 0) : 0,
|
|
59
|
+
completionTokens: res.ok
|
|
60
|
+
? (res.value.usage?.completionTokens ?? 0)
|
|
61
|
+
: 0,
|
|
62
|
+
totalTokens: res.ok ? (res.value.usage?.totalTokens ?? 0) : 0,
|
|
63
|
+
durationMs: Date.now() - chatStart,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (!res.ok || !res.value.content.trim())
|
|
67
|
+
return [];
|
|
68
|
+
return [
|
|
69
|
+
{
|
|
70
|
+
id: `tool:${tool.name}:intent`,
|
|
71
|
+
text: `${tool.name}: ${res.value.content.trim()}`,
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
// Synonym — adds action verb synonyms
|
|
82
|
+
// ---------------------------------------------------------------------------
|
|
83
|
+
const ACTION_SYNONYMS = {
|
|
84
|
+
read: ['show', 'display', 'view', 'get', 'retrieve'],
|
|
85
|
+
create: ['add', 'new', 'make', 'generate'],
|
|
86
|
+
update: ['modify', 'change', 'edit', 'set'],
|
|
87
|
+
delete: ['remove', 'drop', 'destroy'],
|
|
88
|
+
search: ['find', 'locate', 'lookup', 'discover'],
|
|
89
|
+
list: ['show all', 'enumerate', 'browse'],
|
|
90
|
+
run: ['execute', 'start', 'launch', 'trigger'],
|
|
91
|
+
check: ['validate', 'verify', 'test', 'inspect'],
|
|
92
|
+
get: ['read', 'fetch', 'retrieve', 'show'],
|
|
93
|
+
activate: ['enable', 'publish', 'deploy'],
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Adds action verb synonyms to the tool description.
|
|
97
|
+
* E.g. "ReadClass" → also indexed with "show class, display class, view class".
|
|
98
|
+
* Purely deterministic — no LLM needed.
|
|
99
|
+
*/
|
|
100
|
+
export class SynonymToolIndexing {
|
|
101
|
+
name = 'synonym';
|
|
102
|
+
async prepare(tool) {
|
|
103
|
+
const nameLower = tool.name.toLowerCase();
|
|
104
|
+
const synonymPhrases = [];
|
|
105
|
+
for (const [verb, synonyms] of Object.entries(ACTION_SYNONYMS)) {
|
|
106
|
+
if (nameLower.startsWith(verb)) {
|
|
107
|
+
const objectPart = tool.name
|
|
108
|
+
.replace(/^[A-Z][a-z]+/, '') // Remove first word (the verb)
|
|
109
|
+
.replace(/([A-Z])/g, ' $1') // CamelCase to spaces
|
|
110
|
+
.trim()
|
|
111
|
+
.toLowerCase();
|
|
112
|
+
if (objectPart) {
|
|
113
|
+
for (const syn of synonyms) {
|
|
114
|
+
synonymPhrases.push(`${syn} ${objectPart}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (synonymPhrases.length === 0)
|
|
121
|
+
return [];
|
|
122
|
+
return [
|
|
123
|
+
{
|
|
124
|
+
id: `tool:${tool.name}:synonym`,
|
|
125
|
+
text: `${tool.name}: ${synonymPhrases.join(', ')}`,
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=tool-indexing-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-indexing-strategy.js","sourceRoot":"","sources":["../../../src/smart-agent/rag/tool-indexing-strategy.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { IQueryEmbedding } from '../interfaces/query-embedding.js';
|
|
2
2
|
import type { IEmbedder, IPrecomputedVectorRag } from '../interfaces/rag.js';
|
|
3
3
|
import { type CallOptions, RagError, type RagMetadata, type RagResult, type Result } from '../interfaces/types.js';
|
|
4
|
+
import type { IDocumentEnricher, IQueryPreprocessor } from './preprocessor.js';
|
|
5
|
+
import type { ISearchStrategy } from './search-strategy.js';
|
|
4
6
|
export interface VectorRagConfig {
|
|
5
7
|
/** Cosine similarity threshold for dedup. Default: 0.92 */
|
|
6
8
|
dedupThreshold?: number;
|
|
@@ -10,6 +12,12 @@ export interface VectorRagConfig {
|
|
|
10
12
|
vectorWeight?: number;
|
|
11
13
|
/** Weight for keyword search (0..1). Default: 0.3 */
|
|
12
14
|
keywordWeight?: number;
|
|
15
|
+
/** Search scoring strategy. Default: WeightedFusionStrategy with the configured weights. */
|
|
16
|
+
strategy?: ISearchStrategy;
|
|
17
|
+
/** Query preprocessors (translate, expand, etc.). Applied in order before embedding. */
|
|
18
|
+
queryPreprocessors?: IQueryPreprocessor[];
|
|
19
|
+
/** Document enrichers. Applied in order before embedding on upsert. */
|
|
20
|
+
documentEnrichers?: IDocumentEnricher[];
|
|
13
21
|
}
|
|
14
22
|
export declare class VectorRag implements IPrecomputedVectorRag {
|
|
15
23
|
private readonly embedder;
|
|
@@ -19,6 +27,9 @@ export declare class VectorRag implements IPrecomputedVectorRag {
|
|
|
19
27
|
private readonly namespace?;
|
|
20
28
|
private vectorWeight;
|
|
21
29
|
private keywordWeight;
|
|
30
|
+
private strategy;
|
|
31
|
+
private readonly queryPreprocessors;
|
|
32
|
+
private readonly documentEnrichers;
|
|
22
33
|
constructor(embedder: IEmbedder, config?: VectorRagConfig);
|
|
23
34
|
/** Update hybrid search weights at runtime (hot-reload). */
|
|
24
35
|
updateWeights(config: {
|
|
@@ -27,11 +38,6 @@ export declare class VectorRag implements IPrecomputedVectorRag {
|
|
|
27
38
|
}): void;
|
|
28
39
|
private tokenize;
|
|
29
40
|
private cosine;
|
|
30
|
-
/**
|
|
31
|
-
* BM25 Lexical Scorer.
|
|
32
|
-
* Uses pre-built InvertedIndex for O(1) DF lookups.
|
|
33
|
-
*/
|
|
34
|
-
private bm25Score;
|
|
35
41
|
private upsertKnownVector;
|
|
36
42
|
upsert(text: string, metadata: RagMetadata, options?: CallOptions): Promise<Result<void, RagError>>;
|
|
37
43
|
upsertPrecomputed(text: string, vector: number[], metadata: RagMetadata, _options?: CallOptions): Promise<Result<void, RagError>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vector-rag.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/rag/vector-rag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EACL,KAAK,WAAW,EAChB,QAAQ,EACR,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,MAAM,EACZ,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"vector-rag.d.ts","sourceRoot":"","sources":["../../../src/smart-agent/rag/vector-rag.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EACL,KAAK,WAAW,EAChB,QAAQ,EACR,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,MAAM,EACZ,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE/E,OAAO,KAAK,EAIV,eAAe,EAChB,MAAM,sBAAsB,CAAC;AAS9B,MAAM,WAAW,eAAe;IAC9B,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,wFAAwF;IACxF,kBAAkB,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAC1C,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,iBAAiB,EAAE,CAAC;CACzC;AAED,qBAAa,SAAU,YAAW,qBAAqB;IAYnD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAX3B,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;IAC7C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IACpC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAuB;IAC1D,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAsB;gBAGrC,QAAQ,EAAE,SAAS,EACpC,MAAM,GAAE,eAAoB;IAgB9B,4DAA4D;IAC5D,aAAa,CAAC,MAAM,EAAE;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,GAAG,IAAI;IAaR,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,MAAM;IAYd,OAAO,CAAC,iBAAiB;IA0CnB,MAAM,CACV,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,WAAW,EACrB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IA2B5B,iBAAiB,CACrB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EAAE,EAChB,QAAQ,EAAE,WAAW,EACrB,QAAQ,CAAC,EAAE,WAAW,GACrB,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAS5B,KAAK,CACT,SAAS,EAAE,eAAe,EAC1B,CAAC,EAAE,MAAM,EACT,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,QAAQ,CAAC,CAAC;IAgEnC,WAAW,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAezE,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RagError, } from '../interfaces/types.js';
|
|
2
2
|
import { InvertedIndex } from './inverted-index.js';
|
|
3
|
-
import { FallbackQueryEmbedding } from './query-embedding.js';
|
|
3
|
+
import { FallbackQueryEmbedding, QueryEmbedding } from './query-embedding.js';
|
|
4
|
+
import { WeightedFusionStrategy } from './search-strategy.js';
|
|
4
5
|
export class VectorRag {
|
|
5
6
|
embedder;
|
|
6
7
|
records = [];
|
|
@@ -9,12 +10,23 @@ export class VectorRag {
|
|
|
9
10
|
namespace;
|
|
10
11
|
vectorWeight;
|
|
11
12
|
keywordWeight;
|
|
13
|
+
strategy;
|
|
14
|
+
queryPreprocessors;
|
|
15
|
+
documentEnrichers;
|
|
12
16
|
constructor(embedder, config = {}) {
|
|
13
17
|
this.embedder = embedder;
|
|
14
18
|
this.dedupThreshold = config.dedupThreshold ?? 0.92;
|
|
15
19
|
this.namespace = config.namespace;
|
|
16
20
|
this.vectorWeight = config.vectorWeight ?? 0.7;
|
|
17
21
|
this.keywordWeight = config.keywordWeight ?? 0.3;
|
|
22
|
+
this.strategy =
|
|
23
|
+
config.strategy ??
|
|
24
|
+
new WeightedFusionStrategy({
|
|
25
|
+
vectorWeight: this.vectorWeight,
|
|
26
|
+
keywordWeight: this.keywordWeight,
|
|
27
|
+
});
|
|
28
|
+
this.queryPreprocessors = config.queryPreprocessors ?? [];
|
|
29
|
+
this.documentEnrichers = config.documentEnrichers ?? [];
|
|
18
30
|
}
|
|
19
31
|
/** Update hybrid search weights at runtime (hot-reload). */
|
|
20
32
|
updateWeights(config) {
|
|
@@ -22,6 +34,12 @@ export class VectorRag {
|
|
|
22
34
|
this.vectorWeight = config.vectorWeight;
|
|
23
35
|
if (config.keywordWeight !== undefined)
|
|
24
36
|
this.keywordWeight = config.keywordWeight;
|
|
37
|
+
if (this.strategy.name === 'weighted-fusion') {
|
|
38
|
+
this.strategy = new WeightedFusionStrategy({
|
|
39
|
+
vectorWeight: this.vectorWeight,
|
|
40
|
+
keywordWeight: this.keywordWeight,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
25
43
|
}
|
|
26
44
|
tokenize(s) {
|
|
27
45
|
return s
|
|
@@ -40,31 +58,6 @@ export class VectorRag {
|
|
|
40
58
|
}
|
|
41
59
|
return dot / (Math.sqrt(na) * Math.sqrt(nb) || 1);
|
|
42
60
|
}
|
|
43
|
-
/**
|
|
44
|
-
* BM25 Lexical Scorer.
|
|
45
|
-
* Uses pre-built InvertedIndex for O(1) DF lookups.
|
|
46
|
-
*/
|
|
47
|
-
bm25Score(query, text) {
|
|
48
|
-
const queryTokens = this.tokenize(query);
|
|
49
|
-
const docTokens = this.tokenize(text);
|
|
50
|
-
if (queryTokens.length === 0 || docTokens.length === 0)
|
|
51
|
-
return 0;
|
|
52
|
-
const avgDocLength = this.index.avgDocLength || 1;
|
|
53
|
-
const n = this.index.docCount || 1;
|
|
54
|
-
const k1 = 1.2;
|
|
55
|
-
const b = 0.75;
|
|
56
|
-
let score = 0;
|
|
57
|
-
for (const token of new Set(queryTokens)) {
|
|
58
|
-
const df = this.index.getDocFrequency(token);
|
|
59
|
-
const idf = Math.log((n - df + 0.5) / (df + 0.5) + 1);
|
|
60
|
-
const tf = docTokens.filter((t) => t === token).length;
|
|
61
|
-
const tfScored = (tf * (k1 + 1)) /
|
|
62
|
-
(tf + k1 * (1 - b + b * (docTokens.length / avgDocLength)));
|
|
63
|
-
score += idf * tfScored;
|
|
64
|
-
}
|
|
65
|
-
// Normalize to [0, 1] range (rough approximation for fusion)
|
|
66
|
-
return Math.min(score / 5, 1.0);
|
|
67
|
-
}
|
|
68
61
|
upsertKnownVector(text, vector, metadata) {
|
|
69
62
|
const newTokens = this.tokenize(text);
|
|
70
63
|
// Idempotent upsert: if metadata.id matches, replace in-place
|
|
@@ -109,8 +102,14 @@ export class VectorRag {
|
|
|
109
102
|
return { ok: true, value: undefined };
|
|
110
103
|
}
|
|
111
104
|
try {
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
let enrichedText = text;
|
|
106
|
+
for (const enricher of this.documentEnrichers) {
|
|
107
|
+
const eResult = await enricher.enrich(enrichedText, options);
|
|
108
|
+
if (eResult.ok)
|
|
109
|
+
enrichedText = eResult.value;
|
|
110
|
+
}
|
|
111
|
+
const { vector } = await this.embedder.embed(enrichedText, options);
|
|
112
|
+
return this.upsertKnownVector(enrichedText, vector, metadata);
|
|
114
113
|
}
|
|
115
114
|
catch (err) {
|
|
116
115
|
if (err instanceof RagError)
|
|
@@ -134,15 +133,22 @@ export class VectorRag {
|
|
|
134
133
|
}
|
|
135
134
|
try {
|
|
136
135
|
const text = embedding.text;
|
|
136
|
+
let searchText = text;
|
|
137
|
+
for (const pp of this.queryPreprocessors) {
|
|
138
|
+
const ppResult = await pp.process(searchText, options);
|
|
139
|
+
if (ppResult.ok)
|
|
140
|
+
searchText = ppResult.value;
|
|
141
|
+
}
|
|
137
142
|
const nowSecs = Date.now() / 1000;
|
|
138
|
-
|
|
139
|
-
const
|
|
143
|
+
// If preprocessors transformed the text, embed the transformed version
|
|
144
|
+
const effectiveEmbedding = searchText !== text
|
|
145
|
+
? new QueryEmbedding(searchText, this.embedder, options)
|
|
146
|
+
: new FallbackQueryEmbedding(embedding, this.embedder);
|
|
147
|
+
const queryVector = await effectiveEmbedding.toVector();
|
|
140
148
|
const targetNamespace = options?.ragFilter?.namespace;
|
|
141
|
-
const
|
|
142
|
-
.filter((r) => {
|
|
149
|
+
const filtered = this.records.filter((r) => {
|
|
143
150
|
if (r.metadata.ttl !== undefined && r.metadata.ttl < nowSecs)
|
|
144
151
|
return false;
|
|
145
|
-
// Apply dynamic filter from CallOptions
|
|
146
152
|
if (targetNamespace !== undefined &&
|
|
147
153
|
r.metadata.namespace !== targetNamespace)
|
|
148
154
|
return false;
|
|
@@ -151,19 +157,22 @@ export class VectorRag {
|
|
|
151
157
|
r.metadata.namespace !== this.namespace)
|
|
152
158
|
return false;
|
|
153
159
|
return true;
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
160
|
+
});
|
|
161
|
+
const candidates = filtered.map((r) => ({
|
|
162
|
+
text: r.text,
|
|
163
|
+
vector: r.vector,
|
|
164
|
+
metadata: r.metadata,
|
|
165
|
+
}));
|
|
166
|
+
const searchQuery = {
|
|
167
|
+
text: searchText,
|
|
168
|
+
vector: queryVector,
|
|
169
|
+
};
|
|
170
|
+
const context = {
|
|
171
|
+
index: this.index,
|
|
172
|
+
tokenize: this.tokenize.bind(this),
|
|
173
|
+
};
|
|
174
|
+
const scored = this.strategy
|
|
175
|
+
.score(searchQuery, candidates, context)
|
|
167
176
|
.slice(0, k);
|
|
168
177
|
return { ok: true, value: scored };
|
|
169
178
|
}
|