UNPKG

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
"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