reagentbuilder
Version:
An enterprise-grade AI agent framework based on LangChain and LangGraph, featuring dynamic tools, interceptors, breakpoints, and performance monitoring.
574 lines • 28.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ReAgentBuilder = void 0;
const langgraph_1 = require("@langchain/langgraph");
const langgraph_2 = require("@langchain/langgraph");
const messages_1 = require("@langchain/core/messages");
const tools_1 = require("@langchain/core/tools");
const chat_models_1 = require("@langchain/core/language_models/chat_models");
const zod_1 = require("zod");
const index_js_1 = require("../types/index.js");
const index_js_2 = require("../core/index.js");
const interceptor_manager_js_1 = require("./interceptor-manager.js");
const breakpoint_manager_js_1 = require("./breakpoint-manager.js");
// ============ 智能体构建器 ============
class ReAgentBuilder {
constructor(config = {}) {
this.toolMap = new Map();
this.messageCache = new Map();
this.MAX_CACHE_SIZE = 50;
this.cleanupHandlers = [];
if (!config) {
throw index_js_2.ErrorHandler.createError('智能体配置不能为空', index_js_2.ErrorType.CONFIGURATION, index_js_2.ErrorSeverity.CRITICAL, { component: 'ReAgentBuilder', operation: 'constructor' });
}
if (!config.name) {
throw index_js_2.ErrorHandler.createError('必须提供智能体名称(name)', index_js_2.ErrorType.CONFIGURATION, index_js_2.ErrorSeverity.HIGH, { component: 'ReAgentBuilder', operation: 'constructor' });
}
if (!config.llm) {
throw index_js_2.ErrorHandler.createError('必须提供LLM配置(llm)', index_js_2.ErrorType.CONFIGURATION, index_js_2.ErrorSeverity.CRITICAL, { component: 'ReAgentBuilder', operation: 'constructor' });
}
this.config = {
memory: config.memory !== undefined ? config.memory : true,
...config
};
// 初始化ReAct配置 - 默认启用且无限制
this.reactConfig = {
enabled: config.react?.enabled ?? true, // 默认启用ReAct模式
maxIterations: config.react?.maxIterations ?? 0, // 默认无限制
thinkingPrompt: config.react?.thinkingPrompt ?? ""
};
// maxIterations为0表示无限制,设为一个很大的数
if (this.reactConfig.maxIterations === 0) {
this.reactConfig.maxIterations = Number.MAX_SAFE_INTEGER;
}
const interceptorConcurrency = config.concurrency?.interceptors || 10;
const breakpointConcurrency = config.concurrency?.breakpoints || 5;
this.interceptorManager = new interceptor_manager_js_1.InterceptorManager(config.interceptors || { enabled: false }, interceptorConcurrency);
this.breakpointManager = new breakpoint_manager_js_1.BreakpointManager(config.breakpoints || { enabled: false }, breakpointConcurrency);
this.initializeLLM();
this.setupTools();
this.buildWorkflow();
index_js_2.perfMonitor.startMonitoring();
index_js_2.perfMonitor.incrementCounter('agent.created');
}
initializeLLM() {
if (this.config.llm instanceof chat_models_1.BaseChatModel) {
this.llm = this.config.llm;
}
else {
this.llm = index_js_2.LLMFactory.create(this.config.llm);
}
}
setupTools() {
if (this.config.tools) {
this.config.tools.forEach(tool => {
this.toolMap.set(tool.name, tool);
});
}
}
async callModel(state) {
await this.breakpointManager.breakBeforeModelCall(state);
// ReAct模式下更新迭代计数
if (this.reactConfig.enabled) {
const currentIteration = (state.reactIteration || 0) + 1;
index_js_2.logger.debug(`[${this.config.name}] ReAct模式: 第 ${currentIteration} 次迭代`);
// 更新状态中的迭代计数
state.reactIteration = currentIteration;
state.reactMaxIterations = this.reactConfig.maxIterations;
}
const messages = [...state.messages];
const hasSystemMessage = messages.some(msg => msg.getType() === 'system');
if (this.config.systemPrompt && !hasSystemMessage) {
messages.unshift(new messages_1.SystemMessage(this.config.systemPrompt));
}
let finalMessages = await this.interceptorManager.interceptBeforeModelInvoke(messages, state);
await this.breakpointManager.breakBeforeModelInvoke(finalMessages, state);
const tools = Array.from(this.toolMap.values());
const modelWithTools = tools.length > 0 ? this.llm?.bindTools?.(tools) || this.llm : this.llm;
if (!modelWithTools) {
throw new Error('模型初始化失败');
}
const response = await modelWithTools.invoke(finalMessages);
index_js_2.logger.info(`[${this.config.name}] 🔍 模型完整返回:`, {
type: response.getType(),
content: response.content,
tool_calls: response.tool_calls || [],
tool_calls_count: (response.tool_calls || []).length
});
await this.breakpointManager.breakAfterModelCall(response, state);
return {
messages: [response],
reactIteration: this.reactConfig.enabled ? state.reactIteration : undefined,
reactMaxIterations: this.reactConfig.enabled ? state.reactMaxIterations : undefined
};
}
async executeTools(state) {
const lastMessage = state.messages[state.messages.length - 1];
const toolCalls = lastMessage.tool_calls || [];
if (toolCalls.length === 0) {
return { messages: [] };
}
const validToolCalls = [];
const invalidToolCalls = [];
for (const toolCall of toolCalls) {
if (this.toolMap.has(toolCall.name)) {
validToolCalls.push(toolCall);
}
else {
invalidToolCalls.push(toolCall);
}
}
// 如果存在无效工具,先记录错误
if (invalidToolCalls.length > 0) {
index_js_2.logger.warn(`检测到 ${invalidToolCalls.length} 个无效工具调用: ${invalidToolCalls.map(tc => tc.name).join(', ')}`);
}
const allToolMessages = [];
// 处理无效工具调用,快速生成错误消息
for (const [index, toolCall] of invalidToolCalls.entries()) {
const executionId = toolCall.id || index_js_2.perfUtils.generateId(`invalid-${index}`);
const errorMessage = `Unknown tool: ${toolCall.name}`;
allToolMessages.push(new messages_1.ToolMessage({
content: errorMessage,
tool_call_id: executionId,
}));
}
// 只对有效工具执行并行处理
if (validToolCalls.length === 0) {
return { messages: allToolMessages };
}
const toolExecutionTasks = validToolCalls.map(async (toolCall, index) => {
const executionId = toolCall.id || index_js_2.perfUtils.generateId(`exec-${index}`);
const timerName = `tool.${toolCall.name}`;
index_js_2.perfMonitor.startTimer(timerName);
index_js_2.perfMonitor.incrementCounter('tool.executions');
index_js_2.perfMonitor.incrementCounter(`tool.${toolCall.name}.executions`);
try {
let globalInterceptResult = await this.interceptorManager.interceptBeforeToolCall(toolCall, state);
try {
await this.breakpointManager.breakBeforeToolCall(toolCall, state);
}
catch (error) {
index_js_2.logger.warn(`全局工具前断点失败: ${error}`);
}
let finalInterceptResult = globalInterceptResult;
if (!globalInterceptResult.shortCircuit) {
finalInterceptResult = await this.interceptorManager.interceptSpecificToolCall(globalInterceptResult.modifiedInput, state);
}
try {
await this.breakpointManager.breakBeforeSpecificToolCall(toolCall, state);
}
catch (error) {
index_js_2.logger.warn(`特定工具前断点失败: ${error}`);
}
let result;
if (finalInterceptResult.shortCircuit) {
result = finalInterceptResult.result;
index_js_2.logger.info(`[${this.config.name}] 工具调用被短路: ${toolCall.name} (ID: ${executionId})`);
}
else {
const tool = this.toolMap.get(toolCall.name);
index_js_2.logger.info(`[${this.config.name}] 并行执行工具: ${toolCall.name} (ID: ${executionId})`);
const modifiedToolCall = finalInterceptResult.modifiedInput;
result = await tool.invoke(modifiedToolCall.args);
}
const specificProcessedResult = await this.interceptorManager.interceptSpecificToolResult(result, toolCall, state);
try {
await this.breakpointManager.breakAfterSpecificToolCall(specificProcessedResult, toolCall, state);
}
catch (error) {
index_js_2.logger.warn(`特定工具后断点失败: ${error}`);
}
const finalResult = await this.interceptorManager.interceptAfterToolCall(specificProcessedResult, toolCall, state);
try {
await this.breakpointManager.breakAfterToolCall(finalResult, toolCall, state);
}
catch (error) {
index_js_2.logger.warn(`全局工具后断点失败: ${error}`);
}
const duration = index_js_2.perfMonitor.endTimer(timerName);
index_js_2.perfMonitor.recordToolExecution(toolCall.name, duration, true);
index_js_2.perfMonitor.incrementCounter('tool.successes');
return {
message: new messages_1.ToolMessage({
content: String(finalResult),
tool_call_id: executionId,
}),
isError: false
};
}
catch (error) {
const errorMessage = `Error executing tool ${toolCall.name}: ${error instanceof Error ? error.message : String(error)}`;
index_js_2.logger.error(`工具执行失败 (ID: ${executionId}): ${errorMessage}`);
const duration = index_js_2.perfMonitor.endTimer(timerName);
index_js_2.perfMonitor.recordToolExecution(toolCall.name, duration, false);
index_js_2.perfMonitor.incrementCounter('tool.failures');
index_js_2.perfMonitor.recordError(`tool.${toolCall.name}.error`);
return {
message: new messages_1.ToolMessage({
content: errorMessage,
tool_call_id: executionId,
}),
isError: true
};
}
});
index_js_2.logger.info(`[${this.config.name}] 开始并行执行 ${validToolCalls.length} 个有效工具...`);
const executionResults = await Promise.allSettled(toolExecutionTasks);
const toolMessages = [...allToolMessages]; // 包含无效工具的错误消息
const errorMessages = [...allToolMessages.filter(msg => String(msg.content).startsWith('Unknown tool:'))]; // 只统计无效工具错误
executionResults.forEach((result, index) => {
if (result.status === 'fulfilled') {
const { message, isError } = result.value;
toolMessages.push(message);
if (isError) {
errorMessages.push(message);
}
}
else {
const toolCall = validToolCalls[index];
const errorMessage = `Critical error executing tool ${toolCall?.name || 'unknown'}: ${result.reason}`;
index_js_2.logger.error(`工具并行执行严重失败: ${errorMessage}`);
const errorToolMessage = new messages_1.ToolMessage({
content: errorMessage,
tool_call_id: toolCall?.id || index_js_2.perfUtils.generateId(`error-${index}`),
});
toolMessages.push(errorToolMessage);
errorMessages.push(errorToolMessage);
}
});
const totalTools = toolCalls.length; // 包括无效工具
const successCount = toolMessages.length - errorMessages.length;
index_js_2.logger.info(`[${this.config.name}] 并行执行完成: 成功 ${successCount}/${totalTools}, 失败 ${errorMessages.length}/${totalTools}`);
if (errorMessages.length > Math.floor(totalTools / 2)) {
index_js_2.logger.warn(`检测到过多工具错误 (${errorMessages.length}/${totalTools}),可能存在系统性问题`);
}
return { messages: toolMessages };
}
shouldContinue(state) {
const lastMessage = state.messages[state.messages.length - 1];
// 如果启用了ReAct模式
if (this.reactConfig.enabled) {
const currentIteration = state.reactIteration || 0;
const maxIterations = state.reactMaxIterations || this.reactConfig.maxIterations;
// 检查是否超过最大迭代次数
if (currentIteration >= maxIterations) {
index_js_2.logger.info(`[${this.config.name}] ReAct模式: 达到最大迭代次数 ${maxIterations}`);
return langgraph_1.END;
}
// 标准ReAct逻辑:完全按照LangChain的实现
// if there's no function call, we finish
if (!(0, messages_1.isAIMessage)(lastMessage) || !lastMessage.tool_calls?.length) {
index_js_2.logger.info(`[${this.config.name}] ReAct模式: AI未调用工具,推理完成`);
return langgraph_1.END;
}
// there are function calls, we continue
return index_js_1.NODES.TOOLS;
}
// 原始逻辑:有工具调用则执行工具,否则结束
if ((0, messages_1.isAIMessage)(lastMessage) && lastMessage.tool_calls?.length) {
return index_js_1.NODES.TOOLS;
}
return langgraph_1.END;
}
buildWorkflow() {
this.workflow = new langgraph_1.StateGraph(index_js_1.AgentState);
this.workflow.addNode(index_js_1.NODES.AGENT, this.callModel.bind(this));
this.workflow.addNode(index_js_1.NODES.TOOLS, this.executeTools.bind(this));
this.workflow.addEdge(langgraph_1.START, index_js_1.NODES.AGENT);
this.workflow.addConditionalEdges(index_js_1.NODES.AGENT, this.shouldContinue.bind(this));
this.workflow.addEdge(index_js_1.NODES.TOOLS, index_js_1.NODES.AGENT);
}
cacheMessages(key, messages) {
if (this.messageCache.size >= this.MAX_CACHE_SIZE) {
const oldestKey = this.messageCache.keys().next().value;
if (oldestKey !== undefined) {
this.messageCache.delete(oldestKey);
}
}
this.messageCache.set(key, messages);
}
getCachedMessages(key) {
return this.messageCache.get(key);
}
clearMessageCache() {
this.messageCache.clear();
}
async run(userInput, threadId) {
index_js_2.perfMonitor.startTimer('agent.run');
index_js_2.perfMonitor.incrementCounter('agent.runs');
const memory = this.config.memory ? new langgraph_2.MemorySaver() : undefined;
const app = this.workflow.compile({
checkpointer: memory
});
const config = threadId ? { configurable: { thread_id: threadId } } : {};
const messages = Array.isArray(userInput)
? userInput
: [new messages_1.HumanMessage(userInput)];
// 初始化ReAct状态
const input = {
messages,
...(this.reactConfig.enabled ? {
reactIteration: 0,
reactMaxIterations: this.reactConfig.maxIterations
} : {})
};
index_js_2.logger.info(`[${this.config.name}] 开始执行${this.reactConfig.enabled ? ' (ReAct模式)' : ''}...`);
const stream = await app.stream(input, {
...config,
streamMode: "values",
});
let finalState = null;
for await (const chunk of stream) {
if ((0, index_js_1.isAgentState)(chunk)) {
finalState = chunk;
const lastMessage = finalState.messages[finalState.messages.length - 1];
if (lastMessage?.content) {
index_js_2.logger.info(`[${this.config.name}] 消息: ${typeof lastMessage.content === 'string' ? lastMessage.content : JSON.stringify(lastMessage.content)}`);
}
if (lastMessage && "tool_calls" in lastMessage) {
const aiMessage = lastMessage;
if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {
index_js_2.logger.info(`[${this.config.name}] 工具调用: ${aiMessage.tool_calls.map(tc => tc.name).join(', ')}`);
}
}
// ReAct模式下显示迭代信息
if (this.reactConfig.enabled && finalState.reactIteration) {
index_js_2.logger.debug(`[${this.config.name}] ReAct迭代: ${finalState.reactIteration}/${finalState.reactMaxIterations === Number.MAX_SAFE_INTEGER ? '∞' : finalState.reactMaxIterations}`);
}
}
}
if (finalState) {
finalState = await this.interceptorManager.interceptAfterAgentComplete(finalState);
await this.breakpointManager.breakAfterAgentComplete(finalState);
const duration = index_js_2.perfMonitor.endTimer('agent.run');
index_js_2.perfMonitor.incrementCounter('agent.run.success');
index_js_2.logger.debug(`智能体运行完成,耗时: ${duration.toFixed(2)}ms`);
if (this.reactConfig.enabled) {
index_js_2.logger.info(`[${this.config.name}] ReAct模式完成,总迭代次数: ${finalState.reactIteration || 0}`);
}
}
else {
index_js_2.perfMonitor.endTimer('agent.run');
index_js_2.perfMonitor.incrementCounter('agent.run.failure');
index_js_2.perfMonitor.recordError('agent.run.no_final_state');
}
return finalState;
}
async *runStream(userInput, threadId) {
index_js_2.perfMonitor.startTimer('agent.runStream');
index_js_2.perfMonitor.incrementCounter('agent.runs');
const memory = this.config.memory ? new langgraph_2.MemorySaver() : undefined;
const app = this.workflow.compile({
checkpointer: memory
});
const config = threadId ? { configurable: { thread_id: threadId } } : {};
const messages = Array.isArray(userInput)
? userInput
: [new messages_1.HumanMessage(userInput)];
// 初始化ReAct状态
const input = {
messages,
...(this.reactConfig.enabled ? {
reactIteration: 0,
reactMaxIterations: this.reactConfig.maxIterations
} : {})
};
index_js_2.logger.info(`[${this.config.name}] 开始流式执行${this.reactConfig.enabled ? ' (ReAct模式)' : ''}...`);
const stream = await app.stream(input, {
...config,
streamMode: "values",
});
let finalState = null;
for await (const chunk of stream) {
if ((0, index_js_1.isAgentState)(chunk)) {
finalState = chunk;
const lastMessage = finalState.messages[finalState.messages.length - 1];
if (lastMessage?.content) {
index_js_2.logger.info(`[${this.config.name}] 消息: ${typeof lastMessage.content === 'string' ? lastMessage.content : JSON.stringify(lastMessage.content)}`);
}
if (lastMessage && "tool_calls" in lastMessage) {
const aiMessage = lastMessage;
if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {
index_js_2.logger.info(`[${this.config.name}] 工具调用: ${aiMessage.tool_calls.map(tc => tc.name).join(', ')}`);
}
}
// ReAct模式下显示迭代信息
if (this.reactConfig.enabled && finalState.reactIteration) {
index_js_2.logger.debug(`[${this.config.name}] ReAct迭代: ${finalState.reactIteration}/${finalState.reactMaxIterations === Number.MAX_SAFE_INTEGER ? '∞' : finalState.reactMaxIterations}`);
}
// 流式输出当前状态
yield finalState;
}
}
if (finalState) {
finalState = await this.interceptorManager.interceptAfterAgentComplete(finalState);
await this.breakpointManager.breakAfterAgentComplete(finalState);
const duration = index_js_2.perfMonitor.endTimer('agent.runStream');
index_js_2.perfMonitor.incrementCounter('agent.run.success');
index_js_2.logger.debug(`智能体流式运行完成,耗时: ${duration.toFixed(2)}ms`);
if (this.reactConfig.enabled) {
index_js_2.logger.info(`[${this.config.name}] ReAct模式完成,总迭代次数: ${finalState.reactIteration || 0}`);
}
}
else {
index_js_2.perfMonitor.endTimer('agent.runStream');
index_js_2.perfMonitor.incrementCounter('agent.run.failure');
index_js_2.perfMonitor.recordError('agent.runStream.no_final_state');
}
return finalState;
}
getLLMInfo() {
const modelInfo = this.llm && 'model' in this.llm ? this.llm.model : 'unknown';
return `${this.config.name} 使用的模型: ${modelInfo}`;
}
async cleanup() {
try {
index_js_2.logger.debug(`清理智能体资源: ${this.config.name}`);
await Promise.allSettled([
this.interceptorManager.cleanup(),
this.breakpointManager.cleanup(),
(async () => {
if (this.llm && 'cleanup' in this.llm && typeof this.llm.cleanup === 'function') {
await this.llm.cleanup();
}
})(),
// 执行自定义清理处理器
...this.cleanupHandlers.map(handler => Promise.resolve(handler())),
// 清理所有映射和缓存
(async () => {
this.toolMap.clear();
this.clearMessageCache();
this.cleanupHandlers.length = 0; // 清空数组但保持引用
})(),
// 清理工具类缓存
(async () => {
index_js_2.perfUtils.cleanup();
index_js_2.perfMonitor.cleanup();
})(),
// 最后刷新日志
(async () => {
index_js_2.logger.flush();
})()
]);
// 强制垃圾回收
if (global.gc) {
global.gc();
}
index_js_2.logger.debug(`智能体资源清理完成: ${this.config.name}`);
}
catch (error) {
index_js_2.logger.error(`清理智能体资源失败: ${this.config.name}`, { error: String(error) });
}
}
getConcurrencyStatus() {
return {
activeInterceptors: this.interceptorManager.getActiveTaskCount(),
activeBreakpoints: this.breakpointManager.getActiveBreakpointCount(),
toolMapSize: this.toolMap.size
};
}
getPerformanceReport() {
const report = index_js_2.perfMonitor.getReport();
report.agent = {
name: this.config.name,
toolsCount: this.toolMap.size,
concurrency: this.getConcurrencyStatus(),
memoryCache: {
size: this.messageCache.size,
maxSize: this.MAX_CACHE_SIZE
}
};
return report;
}
resetPerformanceStats() {
index_js_2.perfMonitor.reset();
index_js_2.logger.info(`[${this.config.name}] 性能统计已重置`);
}
// 将 ReAgentBuilder 转换为标准的 @langchain/core/tools 工具
toTool(name, description) {
return (0, tools_1.tool)(async (input) => {
const typedInput = input;
try {
index_js_2.logger.debug(`[${this.config.name}] 作为工具被调用,用户提示: ${typedInput.prompt}`);
const result = await this.run(typedInput.prompt);
if (result) {
const lastMessage = result.messages[result.messages.length - 1];
return String(lastMessage.content || '');
}
return '无响应';
}
catch (error) {
const errorMessage = `ReAgentBuilder工具执行失败: ${error instanceof Error ? error.message : String(error)}`;
index_js_2.logger.error(errorMessage, { error: String(error) });
return errorMessage;
}
}, {
name,
schema: zod_1.z.object({
prompt: zod_1.z.string().describe("用户提示词,传递给智能体进行处理")
}),
description,
});
}
// 实时添加工具
addTool(tool) {
if (!tool || !tool.name) {
throw index_js_2.ErrorHandler.createError('工具不能为空且必须有名称', index_js_2.ErrorType.VALIDATION, index_js_2.ErrorSeverity.HIGH, { component: 'ReAgentBuilder', operation: 'addTool', toolName: tool?.name });
}
if (this.toolMap.has(tool.name)) {
index_js_2.logger.warn(`工具 ${tool.name} 已存在,将被覆盖`, {
component: 'ReAgentBuilder',
operation: 'addTool',
agentName: this.config.name,
toolName: tool.name
});
}
this.toolMap.set(tool.name, tool);
index_js_2.logger.debug(`成功添加工具: ${tool.name}`, {
component: 'ReAgentBuilder',
operation: 'addTool',
agentName: this.config.name,
toolName: tool.name
});
index_js_2.perfMonitor.incrementCounter('tools.added');
}
// 获取当前工具
getTool(toolName) {
if (toolName) {
const tool = this.toolMap.get(toolName);
if (!tool) {
index_js_2.logger.debug(`[${this.config.name}] 工具 ${toolName} 未找到`);
}
return tool;
}
return Array.from(this.toolMap.values());
}
// 传入数组覆盖当前工具设置
setTool(tools) {
if (!Array.isArray(tools)) {
throw index_js_2.ErrorHandler.createError('工具列表必须是数组', index_js_2.ErrorType.VALIDATION, index_js_2.ErrorSeverity.HIGH, { component: 'ReAgentBuilder', operation: 'setTool', toolsType: typeof tools });
}
const oldToolCount = this.toolMap.size;
this.toolMap.clear();
const context = {
component: 'ReAgentBuilder',
operation: 'setTool',
agentName: this.config.name
};
for (const tool of tools) {
if (!tool || !tool.name) {
index_js_2.logger.warn('跳过无效工具', { ...context, invalidTool: tool });
continue;
}
this.toolMap.set(tool.name, tool);
}
const newToolCount = this.toolMap.size;
index_js_2.logger.info(`工具设置已更新: ${oldToolCount} -> ${newToolCount} 个工具`, context);
index_js_2.perfMonitor.incrementCounter('tools.set');
if (newToolCount === 0) {
index_js_2.logger.warn('当前没有可用工具', context);
}
}
}
exports.ReAgentBuilder = ReAgentBuilder;
//# sourceMappingURL=agent-builder.js.map