agent-scene-toolkit 0.1.2 → 0.1.4
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 +110 -0
- package/dist/index.cjs +120 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -6
- package/dist/index.d.ts +87 -6
- package/dist/index.js +120 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -2,6 +2,7 @@ import { StructuredToolInterface } from '@langchain/core/tools';
|
|
|
2
2
|
import * as _langchain_langgraph from '@langchain/langgraph';
|
|
3
3
|
import { BaseCheckpointSaver } from '@langchain/langgraph';
|
|
4
4
|
import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
|
|
5
|
+
import { EmbeddingsInterface } from '@langchain/core/embeddings';
|
|
5
6
|
import { RequestHandler } from 'express';
|
|
6
7
|
import * as _langchain_core_utils_stream from '@langchain/core/utils/stream';
|
|
7
8
|
import * as langchain from 'langchain';
|
|
@@ -72,6 +73,40 @@ interface Scene {
|
|
|
72
73
|
/** 工具调用完成后的生命周期回调 */
|
|
73
74
|
readonly onToolEnd?: (toolName: string, result: any) => void;
|
|
74
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* 知识库 — 纯文本数据 + 语义检索描述。
|
|
78
|
+
*
|
|
79
|
+
* 库内部自动将文本向量化并包装为 LangChain Tool,AI 根据 `description` 自主决定何时检索。
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* const faqKB = defineKnowledgeBase({
|
|
84
|
+
* name: 'faq',
|
|
85
|
+
* description: '产品常见问题,当用户问功能、价格、退款等问题时检索',
|
|
86
|
+
* documents: ['7天内无理由退款', '基础版99元/月'],
|
|
87
|
+
* })
|
|
88
|
+
*
|
|
89
|
+
* // 也支持异步加载
|
|
90
|
+
* const dynamicKB = defineKnowledgeBase({
|
|
91
|
+
* name: 'dynamic-docs',
|
|
92
|
+
* description: '从数据库动态加载的文档',
|
|
93
|
+
* documents: async () => {
|
|
94
|
+
* const res = await fetch('/api/docs')
|
|
95
|
+
* return res.json()
|
|
96
|
+
* },
|
|
97
|
+
* })
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
interface KnowledgeBase {
|
|
101
|
+
/** 知识库唯一标识,也作为 Tool 名称 */
|
|
102
|
+
readonly name: string;
|
|
103
|
+
/** 描述知识库用途,AI 据此判断何时检索 */
|
|
104
|
+
readonly description: string;
|
|
105
|
+
/** 纯文本数据:静态数组或异步加载函数 */
|
|
106
|
+
readonly documents: string[] | (() => Promise<string[]>);
|
|
107
|
+
/** 返回最相关的前 K 条结果(默认 3) */
|
|
108
|
+
readonly topK?: number;
|
|
109
|
+
}
|
|
75
110
|
/**
|
|
76
111
|
* `createAgent()` 配置项。
|
|
77
112
|
*
|
|
@@ -106,6 +141,10 @@ interface AgentOptions {
|
|
|
106
141
|
maxMessages?: number;
|
|
107
142
|
/** LangChain Callbacks */
|
|
108
143
|
callbacks?: BaseCallbackHandler[];
|
|
144
|
+
/** 知识库列表,有值则启用 RAG(检索增强生成) */
|
|
145
|
+
knowledgeBases?: KnowledgeBase[];
|
|
146
|
+
/** 嵌入模型实例,当 knowledgeBases 存在时必填 */
|
|
147
|
+
embeddings?: EmbeddingsInterface;
|
|
109
148
|
/** OpenAI 兼容网关配置(如中转商) */
|
|
110
149
|
llm?: {
|
|
111
150
|
/** 兼容 OpenAI 的 base URL,例如 https://api.bltcy.ai */
|
|
@@ -223,6 +262,38 @@ declare function defineToolKit(input: ToolKit): Readonly<ToolKit>;
|
|
|
223
262
|
*/
|
|
224
263
|
declare function defineScene(input: Scene): Readonly<Scene>;
|
|
225
264
|
|
|
265
|
+
/**
|
|
266
|
+
* 定义一个知识库。
|
|
267
|
+
*
|
|
268
|
+
* 校验必填字段后返回不可变对象。
|
|
269
|
+
* 库内部自动将文本向量化并包装为 LangChain Tool,AI 根据 `description` 自主决定何时检索。
|
|
270
|
+
*
|
|
271
|
+
* @param input - 知识库配置
|
|
272
|
+
* @returns 冻结的 KnowledgeBase 对象
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```ts
|
|
276
|
+
* // 静态文本
|
|
277
|
+
* const faqKB = defineKnowledgeBase({
|
|
278
|
+
* name: 'faq',
|
|
279
|
+
* description: '产品常见问题,当用户问功能、价格、退款等问题时检索',
|
|
280
|
+
* documents: ['7天内无理由退款', '基础版99元/月', '支持微信支付宝付款'],
|
|
281
|
+
* topK: 3,
|
|
282
|
+
* })
|
|
283
|
+
*
|
|
284
|
+
* // 从数据库/API 动态加载
|
|
285
|
+
* const dynamicKB = defineKnowledgeBase({
|
|
286
|
+
* name: 'dynamic-docs',
|
|
287
|
+
* description: '从数据库动态加载的文档',
|
|
288
|
+
* documents: async () => {
|
|
289
|
+
* const res = await fetch('/api/docs')
|
|
290
|
+
* return res.json()
|
|
291
|
+
* },
|
|
292
|
+
* })
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
declare function defineKnowledgeBase(input: KnowledgeBase): Readonly<KnowledgeBase>;
|
|
296
|
+
|
|
226
297
|
/**
|
|
227
298
|
* Agent 实例的内部已解析配置类型。
|
|
228
299
|
*
|
|
@@ -243,7 +314,18 @@ interface ResolvedOptions extends AgentOptions {
|
|
|
243
314
|
declare class Agent {
|
|
244
315
|
/** @internal */
|
|
245
316
|
readonly options: ResolvedOptions;
|
|
317
|
+
/** RAG 知识库转换而来的 DynamicTool 列表 */
|
|
318
|
+
private knowledgeTools;
|
|
319
|
+
/** 异步初始化 Promise(向量化知识库等) */
|
|
320
|
+
private readyPromise;
|
|
246
321
|
constructor(options: AgentOptions);
|
|
322
|
+
/**
|
|
323
|
+
* 异步初始化 — 向量化知识库并构建检索 Tool。
|
|
324
|
+
*
|
|
325
|
+
* 在构造函数中启动,chat() 首次调用时 await 确保完成。
|
|
326
|
+
* 若无 knowledgeBases,立即 resolve。
|
|
327
|
+
*/
|
|
328
|
+
private init;
|
|
247
329
|
/**
|
|
248
330
|
* 发起对话,返回标准化 SSE 事件的异步生成器。
|
|
249
331
|
*
|
|
@@ -314,13 +396,12 @@ declare function createAgent(options: AgentOptions): Agent;
|
|
|
314
396
|
declare function createExpressHandler(agent: Agent): RequestHandler;
|
|
315
397
|
|
|
316
398
|
/**
|
|
317
|
-
* 构建
|
|
399
|
+
* 构建 3 层 Prompt 拼接链。
|
|
318
400
|
*
|
|
319
401
|
* ```
|
|
320
|
-
* ①
|
|
321
|
-
* ②
|
|
322
|
-
* ③
|
|
323
|
-
* ④ Scene — scene.prompt(sceneContext)(仅绑定 Scene 时)
|
|
402
|
+
* ① Profile — agent.systemPrompt(角色身份)
|
|
403
|
+
* ② ToolKit — 当前场景激活的 ToolKit.prompt(0~N 个)
|
|
404
|
+
* ③ Scene — scene.prompt(sceneContext)(仅绑定 Scene 时)
|
|
324
405
|
* ```
|
|
325
406
|
*
|
|
326
407
|
* 各层以 `\n\n` 拼接,合并为单条 SystemMessage 字符串。
|
|
@@ -460,4 +541,4 @@ declare function transformStream(stream: AsyncIterable<any>, onToolEnd?: (toolNa
|
|
|
460
541
|
*/
|
|
461
542
|
declare function formatSSE(event: SSEEvent): string;
|
|
462
543
|
|
|
463
|
-
export { Agent, type AgentOptions, type AgentProfile, type ChatOptions, type SSEEvent, type Scene, type ToolKit, buildPromptChain, buildSingleGraph, buildSupervisorGraph, createAgent, createExpressHandler, defineProfile, defineScene, defineToolKit, formatSSE, transformStream };
|
|
544
|
+
export { Agent, type AgentOptions, type AgentProfile, type ChatOptions, type KnowledgeBase, type SSEEvent, type Scene, type ToolKit, buildPromptChain, buildSingleGraph, buildSupervisorGraph, createAgent, createExpressHandler, defineKnowledgeBase, defineProfile, defineScene, defineToolKit, formatSSE, transformStream };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { StructuredToolInterface } from '@langchain/core/tools';
|
|
|
2
2
|
import * as _langchain_langgraph from '@langchain/langgraph';
|
|
3
3
|
import { BaseCheckpointSaver } from '@langchain/langgraph';
|
|
4
4
|
import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
|
|
5
|
+
import { EmbeddingsInterface } from '@langchain/core/embeddings';
|
|
5
6
|
import { RequestHandler } from 'express';
|
|
6
7
|
import * as _langchain_core_utils_stream from '@langchain/core/utils/stream';
|
|
7
8
|
import * as langchain from 'langchain';
|
|
@@ -72,6 +73,40 @@ interface Scene {
|
|
|
72
73
|
/** 工具调用完成后的生命周期回调 */
|
|
73
74
|
readonly onToolEnd?: (toolName: string, result: any) => void;
|
|
74
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* 知识库 — 纯文本数据 + 语义检索描述。
|
|
78
|
+
*
|
|
79
|
+
* 库内部自动将文本向量化并包装为 LangChain Tool,AI 根据 `description` 自主决定何时检索。
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* const faqKB = defineKnowledgeBase({
|
|
84
|
+
* name: 'faq',
|
|
85
|
+
* description: '产品常见问题,当用户问功能、价格、退款等问题时检索',
|
|
86
|
+
* documents: ['7天内无理由退款', '基础版99元/月'],
|
|
87
|
+
* })
|
|
88
|
+
*
|
|
89
|
+
* // 也支持异步加载
|
|
90
|
+
* const dynamicKB = defineKnowledgeBase({
|
|
91
|
+
* name: 'dynamic-docs',
|
|
92
|
+
* description: '从数据库动态加载的文档',
|
|
93
|
+
* documents: async () => {
|
|
94
|
+
* const res = await fetch('/api/docs')
|
|
95
|
+
* return res.json()
|
|
96
|
+
* },
|
|
97
|
+
* })
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
interface KnowledgeBase {
|
|
101
|
+
/** 知识库唯一标识,也作为 Tool 名称 */
|
|
102
|
+
readonly name: string;
|
|
103
|
+
/** 描述知识库用途,AI 据此判断何时检索 */
|
|
104
|
+
readonly description: string;
|
|
105
|
+
/** 纯文本数据:静态数组或异步加载函数 */
|
|
106
|
+
readonly documents: string[] | (() => Promise<string[]>);
|
|
107
|
+
/** 返回最相关的前 K 条结果(默认 3) */
|
|
108
|
+
readonly topK?: number;
|
|
109
|
+
}
|
|
75
110
|
/**
|
|
76
111
|
* `createAgent()` 配置项。
|
|
77
112
|
*
|
|
@@ -106,6 +141,10 @@ interface AgentOptions {
|
|
|
106
141
|
maxMessages?: number;
|
|
107
142
|
/** LangChain Callbacks */
|
|
108
143
|
callbacks?: BaseCallbackHandler[];
|
|
144
|
+
/** 知识库列表,有值则启用 RAG(检索增强生成) */
|
|
145
|
+
knowledgeBases?: KnowledgeBase[];
|
|
146
|
+
/** 嵌入模型实例,当 knowledgeBases 存在时必填 */
|
|
147
|
+
embeddings?: EmbeddingsInterface;
|
|
109
148
|
/** OpenAI 兼容网关配置(如中转商) */
|
|
110
149
|
llm?: {
|
|
111
150
|
/** 兼容 OpenAI 的 base URL,例如 https://api.bltcy.ai */
|
|
@@ -223,6 +262,38 @@ declare function defineToolKit(input: ToolKit): Readonly<ToolKit>;
|
|
|
223
262
|
*/
|
|
224
263
|
declare function defineScene(input: Scene): Readonly<Scene>;
|
|
225
264
|
|
|
265
|
+
/**
|
|
266
|
+
* 定义一个知识库。
|
|
267
|
+
*
|
|
268
|
+
* 校验必填字段后返回不可变对象。
|
|
269
|
+
* 库内部自动将文本向量化并包装为 LangChain Tool,AI 根据 `description` 自主决定何时检索。
|
|
270
|
+
*
|
|
271
|
+
* @param input - 知识库配置
|
|
272
|
+
* @returns 冻结的 KnowledgeBase 对象
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```ts
|
|
276
|
+
* // 静态文本
|
|
277
|
+
* const faqKB = defineKnowledgeBase({
|
|
278
|
+
* name: 'faq',
|
|
279
|
+
* description: '产品常见问题,当用户问功能、价格、退款等问题时检索',
|
|
280
|
+
* documents: ['7天内无理由退款', '基础版99元/月', '支持微信支付宝付款'],
|
|
281
|
+
* topK: 3,
|
|
282
|
+
* })
|
|
283
|
+
*
|
|
284
|
+
* // 从数据库/API 动态加载
|
|
285
|
+
* const dynamicKB = defineKnowledgeBase({
|
|
286
|
+
* name: 'dynamic-docs',
|
|
287
|
+
* description: '从数据库动态加载的文档',
|
|
288
|
+
* documents: async () => {
|
|
289
|
+
* const res = await fetch('/api/docs')
|
|
290
|
+
* return res.json()
|
|
291
|
+
* },
|
|
292
|
+
* })
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
declare function defineKnowledgeBase(input: KnowledgeBase): Readonly<KnowledgeBase>;
|
|
296
|
+
|
|
226
297
|
/**
|
|
227
298
|
* Agent 实例的内部已解析配置类型。
|
|
228
299
|
*
|
|
@@ -243,7 +314,18 @@ interface ResolvedOptions extends AgentOptions {
|
|
|
243
314
|
declare class Agent {
|
|
244
315
|
/** @internal */
|
|
245
316
|
readonly options: ResolvedOptions;
|
|
317
|
+
/** RAG 知识库转换而来的 DynamicTool 列表 */
|
|
318
|
+
private knowledgeTools;
|
|
319
|
+
/** 异步初始化 Promise(向量化知识库等) */
|
|
320
|
+
private readyPromise;
|
|
246
321
|
constructor(options: AgentOptions);
|
|
322
|
+
/**
|
|
323
|
+
* 异步初始化 — 向量化知识库并构建检索 Tool。
|
|
324
|
+
*
|
|
325
|
+
* 在构造函数中启动,chat() 首次调用时 await 确保完成。
|
|
326
|
+
* 若无 knowledgeBases,立即 resolve。
|
|
327
|
+
*/
|
|
328
|
+
private init;
|
|
247
329
|
/**
|
|
248
330
|
* 发起对话,返回标准化 SSE 事件的异步生成器。
|
|
249
331
|
*
|
|
@@ -314,13 +396,12 @@ declare function createAgent(options: AgentOptions): Agent;
|
|
|
314
396
|
declare function createExpressHandler(agent: Agent): RequestHandler;
|
|
315
397
|
|
|
316
398
|
/**
|
|
317
|
-
* 构建
|
|
399
|
+
* 构建 3 层 Prompt 拼接链。
|
|
318
400
|
*
|
|
319
401
|
* ```
|
|
320
|
-
* ①
|
|
321
|
-
* ②
|
|
322
|
-
* ③
|
|
323
|
-
* ④ Scene — scene.prompt(sceneContext)(仅绑定 Scene 时)
|
|
402
|
+
* ① Profile — agent.systemPrompt(角色身份)
|
|
403
|
+
* ② ToolKit — 当前场景激活的 ToolKit.prompt(0~N 个)
|
|
404
|
+
* ③ Scene — scene.prompt(sceneContext)(仅绑定 Scene 时)
|
|
324
405
|
* ```
|
|
325
406
|
*
|
|
326
407
|
* 各层以 `\n\n` 拼接,合并为单条 SystemMessage 字符串。
|
|
@@ -460,4 +541,4 @@ declare function transformStream(stream: AsyncIterable<any>, onToolEnd?: (toolNa
|
|
|
460
541
|
*/
|
|
461
542
|
declare function formatSSE(event: SSEEvent): string;
|
|
462
543
|
|
|
463
|
-
export { Agent, type AgentOptions, type AgentProfile, type ChatOptions, type SSEEvent, type Scene, type ToolKit, buildPromptChain, buildSingleGraph, buildSupervisorGraph, createAgent, createExpressHandler, defineProfile, defineScene, defineToolKit, formatSSE, transformStream };
|
|
544
|
+
export { Agent, type AgentOptions, type AgentProfile, type ChatOptions, type KnowledgeBase, type SSEEvent, type Scene, type ToolKit, buildPromptChain, buildSingleGraph, buildSupervisorGraph, createAgent, createExpressHandler, defineKnowledgeBase, defineProfile, defineScene, defineToolKit, formatSSE, transformStream };
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { createAgent, createMiddleware } from 'langchain';
|
|
|
4
4
|
import { HumanMessage, AIMessageChunk, ToolMessage } from '@langchain/core/messages';
|
|
5
5
|
import { createReactAgent } from '@langchain/langgraph/prebuilt';
|
|
6
6
|
import { createSupervisor } from '@langchain/langgraph-supervisor';
|
|
7
|
+
import { DynamicTool } from '@langchain/core/tools';
|
|
7
8
|
|
|
8
9
|
// src/profile.ts
|
|
9
10
|
function defineProfile(input) {
|
|
@@ -29,26 +30,29 @@ function defineScene(input) {
|
|
|
29
30
|
return Object.freeze({ ...input });
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
// src/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
// src/knowledge.ts
|
|
34
|
+
function defineKnowledgeBase(input) {
|
|
35
|
+
if (!input.name) throw new Error("KnowledgeBase name is required");
|
|
36
|
+
if (!input.description) throw new Error("KnowledgeBase description is required");
|
|
37
|
+
if (!input.documents) throw new Error("KnowledgeBase documents is required");
|
|
38
|
+
if (typeof input.documents !== "function" && !Array.isArray(input.documents)) {
|
|
39
|
+
throw new Error("KnowledgeBase documents must be a string[] or () => Promise<string[]>");
|
|
40
|
+
}
|
|
41
|
+
if (Array.isArray(input.documents) && input.documents.length === 0) {
|
|
42
|
+
throw new Error("KnowledgeBase documents must not be empty");
|
|
43
|
+
}
|
|
44
|
+
if (input.topK !== void 0 && (typeof input.topK !== "number" || input.topK < 1)) {
|
|
45
|
+
throw new Error("KnowledgeBase topK must be a positive number");
|
|
46
|
+
}
|
|
47
|
+
return Object.freeze({ ...input });
|
|
48
|
+
}
|
|
40
49
|
|
|
41
|
-
|
|
42
|
-
- Respond in the same language as the user.
|
|
43
|
-
- Follow tool parameter schemas strictly \u2014 do not invent or omit required fields.
|
|
44
|
-
- When multiple tools are available, choose the most relevant one for the current step.`;
|
|
50
|
+
// src/prompt.ts
|
|
45
51
|
function buildPromptChain(params) {
|
|
46
52
|
const layers = [
|
|
47
|
-
// ①
|
|
48
|
-
BASE_PROMPT,
|
|
49
|
-
// ② Profile — 角色身份提示词
|
|
53
|
+
// ① Profile — 角色身份提示词
|
|
50
54
|
params.profile.systemPrompt,
|
|
51
|
-
//
|
|
55
|
+
// ② ToolKit — 当前场景激活的能力包提示词
|
|
52
56
|
...params.toolkitPrompts
|
|
53
57
|
];
|
|
54
58
|
if (params.scene) {
|
|
@@ -401,11 +405,81 @@ function createExpressHandler(agent) {
|
|
|
401
405
|
}
|
|
402
406
|
};
|
|
403
407
|
}
|
|
408
|
+
function cosineSimilarity(a, b) {
|
|
409
|
+
let dot = 0;
|
|
410
|
+
let normA = 0;
|
|
411
|
+
let normB = 0;
|
|
412
|
+
for (let i = 0; i < a.length; i++) {
|
|
413
|
+
dot += a[i] * b[i];
|
|
414
|
+
normA += a[i] * a[i];
|
|
415
|
+
normB += b[i] * b[i];
|
|
416
|
+
}
|
|
417
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
418
|
+
return denom === 0 ? 0 : dot / denom;
|
|
419
|
+
}
|
|
420
|
+
async function initVectorStores(knowledgeBases, embeddings) {
|
|
421
|
+
const stores = [];
|
|
422
|
+
for (const kb of knowledgeBases) {
|
|
423
|
+
try {
|
|
424
|
+
const docs = typeof kb.documents === "function" ? await kb.documents() : kb.documents;
|
|
425
|
+
if (!docs.length) {
|
|
426
|
+
console.warn(`[initVectorStores] "${kb.name}" has no documents, skipping`);
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
console.log(`[initVectorStores] Embedding "${kb.name}" (${docs.length} documents)...`);
|
|
430
|
+
const vectors = await embeddings.embedDocuments(docs);
|
|
431
|
+
const records = docs.map((text, i) => ({
|
|
432
|
+
text,
|
|
433
|
+
vector: vectors[i]
|
|
434
|
+
}));
|
|
435
|
+
stores.push({ kb, records });
|
|
436
|
+
console.log(`[initVectorStores] "${kb.name}" ready (${records.length} vectors, dim=${vectors[0]?.length ?? 0})`);
|
|
437
|
+
} catch (error) {
|
|
438
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
439
|
+
console.error(`[initVectorStores] Failed to embed "${kb.name}":`, message);
|
|
440
|
+
throw new Error(`Failed to initialize knowledge base "${kb.name}": ${message}`);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return stores;
|
|
444
|
+
}
|
|
445
|
+
async function searchVectorStore(store, query, embeddings) {
|
|
446
|
+
const topK = store.kb.topK ?? 3;
|
|
447
|
+
const queryVector = await embeddings.embedQuery(query);
|
|
448
|
+
const scored = store.records.map((record) => ({
|
|
449
|
+
text: record.text,
|
|
450
|
+
score: cosineSimilarity(queryVector, record.vector)
|
|
451
|
+
}));
|
|
452
|
+
scored.sort((a, b) => b.score - a.score);
|
|
453
|
+
return scored.slice(0, topK).map((item) => item.text);
|
|
454
|
+
}
|
|
455
|
+
function buildKnowledgeTools(stores, embeddings) {
|
|
456
|
+
return stores.map((store) => new DynamicTool({
|
|
457
|
+
name: store.kb.name,
|
|
458
|
+
description: store.kb.description,
|
|
459
|
+
func: async (query) => {
|
|
460
|
+
try {
|
|
461
|
+
const results = await searchVectorStore(store, query, embeddings);
|
|
462
|
+
if (results.length === 0) {
|
|
463
|
+
return "No relevant information found.";
|
|
464
|
+
}
|
|
465
|
+
return results.join("\n\n---\n\n");
|
|
466
|
+
} catch (error) {
|
|
467
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
468
|
+
console.error(`[buildKnowledgeTools] Search failed for "${store.kb.name}":`, message);
|
|
469
|
+
return `Search failed: ${message}`;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}));
|
|
473
|
+
}
|
|
404
474
|
|
|
405
475
|
// src/agent.ts
|
|
406
476
|
var Agent = class {
|
|
407
477
|
/** @internal */
|
|
408
478
|
options;
|
|
479
|
+
/** RAG 知识库转换而来的 DynamicTool 列表 */
|
|
480
|
+
knowledgeTools = [];
|
|
481
|
+
/** 异步初始化 Promise(向量化知识库等) */
|
|
482
|
+
readyPromise;
|
|
409
483
|
constructor(options) {
|
|
410
484
|
this.options = {
|
|
411
485
|
maxMessages: 50,
|
|
@@ -414,6 +488,26 @@ var Agent = class {
|
|
|
414
488
|
...options
|
|
415
489
|
};
|
|
416
490
|
this.validate();
|
|
491
|
+
this.readyPromise = this.init();
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* 异步初始化 — 向量化知识库并构建检索 Tool。
|
|
495
|
+
*
|
|
496
|
+
* 在构造函数中启动,chat() 首次调用时 await 确保完成。
|
|
497
|
+
* 若无 knowledgeBases,立即 resolve。
|
|
498
|
+
*/
|
|
499
|
+
async init() {
|
|
500
|
+
const { knowledgeBases, embeddings } = this.options;
|
|
501
|
+
if (!knowledgeBases?.length || !embeddings) return;
|
|
502
|
+
try {
|
|
503
|
+
const stores = await initVectorStores(knowledgeBases, embeddings);
|
|
504
|
+
this.knowledgeTools = buildKnowledgeTools(stores, embeddings);
|
|
505
|
+
console.log(`[Agent] ${this.knowledgeTools.length} knowledge tool(s) ready`);
|
|
506
|
+
} catch (error) {
|
|
507
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
508
|
+
console.error("[Agent] Knowledge base initialization failed:", message);
|
|
509
|
+
throw error;
|
|
510
|
+
}
|
|
417
511
|
}
|
|
418
512
|
/**
|
|
419
513
|
* 发起对话,返回标准化 SSE 事件的异步生成器。
|
|
@@ -431,6 +525,7 @@ var Agent = class {
|
|
|
431
525
|
*/
|
|
432
526
|
async *chat(chatOptions) {
|
|
433
527
|
try {
|
|
528
|
+
await this.readyPromise;
|
|
434
529
|
if (!chatOptions.message) {
|
|
435
530
|
yield { type: "error", message: "message is required" };
|
|
436
531
|
yield { type: "done" };
|
|
@@ -443,7 +538,11 @@ var Agent = class {
|
|
|
443
538
|
}
|
|
444
539
|
const scene = this.options.scene;
|
|
445
540
|
const activeToolkits = scene ? this.options.toolkits.filter((tk) => scene.toolkits.includes(tk.name)) : this.options.toolkits;
|
|
446
|
-
const tools =
|
|
541
|
+
const tools = [
|
|
542
|
+
...activeToolkits.flatMap((tk) => tk.tools),
|
|
543
|
+
...this.knowledgeTools
|
|
544
|
+
// RAG 知识库 Tool 注入
|
|
545
|
+
];
|
|
447
546
|
const toolkitPrompts = activeToolkits.map((tk) => tk.prompt);
|
|
448
547
|
const isMultiAgent = this.options.agents.length > 1 && !!this.options.supervisor;
|
|
449
548
|
let stream;
|
|
@@ -546,12 +645,15 @@ ${err.stack}` : ""}` : String(err);
|
|
|
546
645
|
}
|
|
547
646
|
}
|
|
548
647
|
}
|
|
648
|
+
if (this.options.knowledgeBases?.length && !this.options.embeddings) {
|
|
649
|
+
throw new Error("embeddings is required when knowledgeBases is provided");
|
|
650
|
+
}
|
|
549
651
|
}
|
|
550
652
|
};
|
|
551
653
|
function createAgent2(options) {
|
|
552
654
|
return new Agent(options);
|
|
553
655
|
}
|
|
554
656
|
|
|
555
|
-
export { Agent, buildPromptChain, buildSingleGraph, buildSupervisorGraph, createAgent2 as createAgent, createExpressHandler, defineProfile, defineScene, defineToolKit, formatSSE, transformStream };
|
|
657
|
+
export { Agent, buildPromptChain, buildSingleGraph, buildSupervisorGraph, createAgent2 as createAgent, createExpressHandler, defineKnowledgeBase, defineProfile, defineScene, defineToolKit, formatSSE, transformStream };
|
|
556
658
|
//# sourceMappingURL=index.js.map
|
|
557
659
|
//# sourceMappingURL=index.js.map
|