万字详解京东开源多智能体产品(JoyAgent-JDGenie)
摘要
JoyAgent-JDGenie 是京东开源的业界首个完整端到端多智能体产品,采用分层架构设计,融合了多层级思考模式、双模式工作流、数字员工系统等创新技术。本报告深入分析其技术架构、核心特性、实现机制和创新点,为智能体系统的设计与实现提供参考。
1. 项目概述
1.1 基本信息
- 项目名称: JoyAgent-JDGenie
- 开发公司: 京东
- 开源性质: 完全开源
- 定位: 解决快速构建多智能体产品的最后一公里问题
- 特点: 轻量化、通用型、开箱即用
1.2 核心价值
- 完整产品: 不同于SDK或框架,提供端到端完整解决方案
- 性能优越: GAIA榜单Validation集准确率75.15%,Test集65.12%
- 轻量独立: 不依赖特定云平台,部署灵活
- 技术先进: 多层级思考模式和工具自动进化
2. 技术架构分析
2.1 整体架构设计
2.1.1 四层架构模型
┌─────────────────────────────────────┐│ 表现层 (UI) ││ React + TypeScript + Vite │└─────────────────────────────────────┘ ↓┌─────────────────────────────────────┐│ 应用层 (Backend) ││ Java + Spring Boot + OpenAPI │└─────────────────────────────────────┘ ↓┌─────────────────────────────────────┐│ 工具层 (Python) ││ FastAPI + 工具服务 + MCP协议 │└─────────────────────────────────────┘ ↓┌─────────────────────────────────────┐│ 模型层 (LLM) ││ GPT/Claude/DeepSeek等多种模型 │└─────────────────────────────────────┘
2.1.2 核心组件关系图
用户请求 → MultiAgentService → AgentHandlerFactory ↓智能体选择 (Planning/Executor/ReAct/Summary) ↓BaseAgent.run() → think() → act() → observe() ↓ToolCollection.execute() → 工具执行 → 结果返回 ↓Memory.update() → 状态更新 → 下一步决策 ↓流式响应 → 前端展示 → 任务完成
2.2 智能体层次结构
2.2.1 Agent继承体系
BaseAgent (抽象基类)├── ReActAgent (ReAct模式基类)│ ├── PlanningAgent (规划代理)│ ├── ExecutorAgent (执行代理)│ └── ReactImplAgent (ReAct实现代理)└── SummaryAgent (总结代理)
2.2.2 核心抽象设计
public abstract class BaseAgent { // 核心属性 private String name; private String systemPrompt; private ToolCollection availableTools; private Memory memory; protected LLM llm; private AgentState state; // 抽象方法 public abstract boolean think(); public abstract boolean act(); // 模板方法 public final String run(String query) { initialize(); while (!isFinished() && currentStep < maxSteps) { if (think()) { act(); } observe(); } return finalize(); }}
2.3 设计模式应用
2.3.1 主要设计模式
- 代理模式: 多种智能体类型的统一接口
- 策略模式: 工具调用策略的选择
- 工厂模式: AgentHandlerFactory创建处理器
- 观察者模式: SSE流式响应机制
- 模板方法模式: BaseAgent的执行流程
- 装饰器模式: 工具功能的动态扩展
2.3.2 模式优势分析
- 可扩展性: 新增Agent类型只需继承BaseAgent
- 灵活性: 工具调用策略可动态切换
- 可维护性: 各组件职责明确,耦合度低
- 可测试性: 依赖注入和接口抽象便于测试
3. 核心技术特性分析
3.1 多层级思考模式
3.1.1 Work Level(工作层级)
核心职责: 战略层面思考和任务规划
实现机制:
public class PlanningAgent extends ReActAgent { @Override public boolean think() { // 1. 构建上下文信息 String context = buildPlanningContext(); // 2. 调用LLM进行规划思考 CompletableFuture<LLM.ToolCallResponse> future = getLlm().askTool( context, memory.getMessages(), systemPrompt, availableTools, ToolChoice.AUTO, null, isStream, timeout ); // 3. 处理规划结果 LLM.ToolCallResponse response = future.get(); return processPlanningResult(response); } private String buildPlanningContext() { StringBuilder context = new StringBuilder(); context.append(\"当前日期: \").append(getCurrentDate()).append(\"\\n\"); context.append(\"可用文件: \").append(formatAvailableFiles()).append(\"\\n\"); context.append(\"历史对话: \").append(formatHistoryDialogue()).append(\"\\n\"); context.append(\"用户任务: \").append(getUserQuery()).append(\"\\n\"); return context.toString(); }}
关键特性:
- 全局视角: 考虑整体任务目标和约束条件
- 任务分解: 将复杂任务拆解为可管理的子任务
- 依赖关系: 分析子任务间的逻辑依赖关系
- 资源评估: 评估所需工具和资源
3.1.2 Task Level(任务层级)
核心职责: 战术层面任务执行和结果分析
实现机制:
public class ExecutorAgent extends ReActAgent { @Override public boolean act() { // 1. 分析当前任务 Task currentTask = getCurrentTask(); // 2. 选择执行策略 ExecutionStrategy strategy = selectExecutionStrategy(currentTask); // 3. 执行任务 ExecutionResult result = strategy.execute(currentTask); // 4. 处理执行结果 return processExecutionResult(result); }}
关键特性:
- 精确执行: 按照规划精确执行具体任务
- 异常处理: 处理执行过程中的异常情况
- 结果验证: 验证执行结果的正确性
- 进度跟踪: 跟踪任务执行进度
3.2 双模式工作流
3.2.1 Plan & Executor模式
流程图:
用户输入 → PlanningAgent → 任务拆解 → 计划生成 ↓ExecutorAgent → 工具调用 → 结果分析 → 任务完成 ↓计划更新 → 下一个任务 → 循环执行 → 最终汇总
实现机制:
public class PlanExecutorWorkflow { public WorkflowResult execute(String query) { // 1. 规划阶段 Plan plan = planningAgent.createPlan(query); workflowContext.setPlan(plan); // 2. 执行阶段 for (Task task : plan.getTasks()) { if (task.getStatus() == TaskStatus.NOT_STARTED) { executeTask(task); plan.updateProgress(task.getId()); } } // 3. 汇总阶段 return summarizeResults(plan); }}
适用场景:
- 复杂的多步骤任务
- 需要严格进度控制的任务
- 涉及多个子任务的复合任务
- 需要中间结果反馈的任务
3.2.2 ReAct模式
流程图:
思考(Reasoning) → 行动(Action) → 观察(Observation) → 反思(Critique) ↑ ↓ └────────────── 循环执行 ←──────────────────────┘
实现机制:
public class ReActWorkflow { public WorkflowResult execute(String query) { ReActState state = new ReActState(); state.setQuery(query); while (!state.isFinished() && state.getStepCount() < maxSteps) { // 思考阶段 String reasoning = agent.reason(state); state.addReasoning(reasoning); // 行动阶段 Action action = agent.act(state); if (action != null) { Observation observation = executeAction(action); state.addObservation(observation); } // 反思阶段 String critique = agent.critique(state); state.addCritique(critique); state.incrementStep(); } return state.getResult(); }}
适用场景:
- 简单的直接任务
- 需要灵活调整的任务
- 探索性任务
- 实时交互任务
3.3 数字员工系统
3.3.1 系统概念
核心思想: 为每个工具分配专业角色名称,使工具调用更加专业化和场景化
实现机制:
public class DigitalEmployeeSystem { public JSONObject generateDigitalEmployees(String task, String toolUsageContext) { // 1. 构建提示词 String prompt = buildDigitalEmployeePrompt(task, toolUsageContext); // 2. 调用LLM生成角色映射 Message userMessage = Message.userMessage(prompt, null); CompletableFuture<String> response = llm.ask( context, Collections.singletonList(userMessage), Collections.emptyList(), false, 0.01 ); // 3. 解析并返回结果 String llmResponse = response.get(); return parseDigitalEmployeeResponse(llmResponse); } private String buildDigitalEmployeePrompt(String task, String toolUsageContext) { return String.format(\"\"\" ## 说明 你是一位专业的数字员工命名专家,精通根据工具的使用场景精准匹配贴合其用途和能力的专业名称。 ## 要求 - 每一个工具都要有一个对应的数字员工名称,仅输出工具名称:数字员工的名称,以、进行分割 - 输出标准的json格式,能够使用json.loads()进行加载。 ## 命名规范 - 名称长度严格限制在6字以内 - 命名需精准体现工具功能与使用场景的关联性 ## 输入 ### 用户的原始任务是 %s ### 当前工具使用的场景是: %s ### 工具名称及描述如下: %s ## 输出 输出: \"\"\", task, toolUsageContext, getToolsDescription()); }}
角色映射示例:
{ \"file_tool\": \"数据记录员\", \"deep_search_tool\": \"市场洞察专员\", \"code_interpreter\": \"算法专家\", \"report_tool\": \"报告撰写专家\"}
核心优势:
- 专业化: 工具调用更加专业和准确
- 场景化: 根据任务场景动态调整角色
- 可理解性: 用户更容易理解工具功能
- 一致性: 保持工具调用的语义一致性
3.4 工具调用机制
3.4.1 工具分类体系
基础工具:
- PlanningTool: 任务规划和进度管理
- FileTool: 文件读写和管理
- ReportTool: 多格式报告生成
- CodeInterpreterTool: 代码执行和分析
MCP工具:
- DeepSearchTool: 深度网络搜索
- 外部工具: 通过MCP协议调用的第三方工具
3.4.2 工具调用架构
public class ToolCollection { private Map<String, BaseTool> tools; private Map<String, McpToolInfo> mcpTools; private JSONObject digitalEmployees; public Object execute(String toolName, Object input) { // 1. 工具查找 BaseTool tool = tools.get(toolName); if (tool != null) { return executeBaseTool(tool, input); } // 2. MCP工具查找 McpToolInfo mcpTool = mcpTools.get(toolName); if (mcpTool != null) { return executeMcpTool(mcpTool, input); } throw new ToolNotFoundException(\"Tool not found: \" + toolName); } private Object executeBaseTool(BaseTool tool, Object input) { try { // 参数验证 validateInput(tool, input); // 权限检查 checkPermission(tool, input); // 执行工具 Object result = tool.execute(input); // 结果处理 return processResult(result); } catch (Exception e) { handleToolException(tool, input, e); throw e; } }}
3.4.3 多模式调用策略
Function Call模式:
public class FunctionCallStrategy implements ToolCallStrategy { @Override public ToolCallResult callTool(LLM llm, List<Message> messages, List<ToolDefinition> tools, String query) { // 使用OpenAI标准的function calling格式 ChatCompletionRequest request = ChatCompletionRequest.builder() .messages(messages) .tools(convertToOpenAITools(tools)) .tool_choice(ToolChoice.AUTO) .build(); ChatCompletionResponse response = llm.chatCompletion(request); return extractToolCallResult(response); }}
Struct Parse模式:
public class StructParseStrategy implements ToolCallStrategy { @Override public ToolCallResult callTool(LLM llm, List<Message> messages, List<ToolDefinition> tools, String query) { // 使用结构化解析模式,支持更多模型 String prompt = buildStructParsePrompt(tools, query); Message userMessage = Message.userMessage(prompt, null); String response = llm.ask(messages, userMessage); return parseStructResponse(response, tools); }}
3.5 记忆管理系统
3.5.1 三层记忆架构
会话级记忆:
public class ConversationMemory { private List<Message> messages; private int maxTokenLimit; public void addMessage(Message message) { messages.add(message); enforceTokenLimit(); } private void enforceTokenLimit() { while (calculateTotalTokens() > maxTokenLimit) { // 保留系统消息和最近的用户消息 removeOldestUserMessage(); } }}
任务级记忆:
public class TaskMemory { private Plan plan; private Map<String, TaskResult> taskResults; private List<TaskExecution> executionHistory; public void updateTaskResult(String taskId, TaskResult result) { taskResults.put(taskId, result); plan.updateTaskStatus(taskId, result.getStatus()); // 记录执行历史 TaskExecution execution = new TaskExecution(taskId, result); executionHistory.add(execution); }}
文件级记忆:
public class FileMemory { private String storagePath; private Map<String, FileInfo> fileIndex; public void saveFile(String filename, String content, String description) { // 保存文件 String filePath = storagePath + \"/\" + filename; Files.write(Paths.get(filePath), content.getBytes()); // 更新索引 FileInfo fileInfo = new FileInfo(filename, filePath, description); fileIndex.put(filename, fileInfo); } public String readFile(String filename) { FileInfo fileInfo = fileIndex.get(filename); if (fileInfo != null) { return Files.readString(Paths.get(fileInfo.getFilePath())); } return null; }}
3.5.2 上下文管理策略
public class ContextManager { public void manageContext(Memory memory) { // 1. 清理工具上下文 clearToolContext(memory); // 2. 压缩重复内容 compressDuplicateContent(memory); // 3. 保留关键信息 preserveKeyInformation(memory); // 4. 维护时间顺序 maintainChronologicalOrder(memory); } private void clearToolContext(Memory memory) { Iterator<Message> iterator = memory.getMessages().iterator(); while (iterator.hasNext()) { Message message = iterator.next(); if (message.getRole() == RoleType.TOOL) { iterator.remove(); } } }}
3.6 流式响应系统
3.6.1 流式模式设计
public enum StreamMode { GENERAL, // 通用模式:按完整内容流式输出 TOKEN, // Token模式:按token数分批输出 TIME // 时间模式:按时间间隔分批输出}
3.6.2 流式响应实现
public class StreamingResponseService { public void streamResponse(String query, StreamMode mode, PrintWriter writer) { // 1. 创建流式上下文 StreamingContext context = new StreamingContext(query, mode); // 2. 启动异步处理 CompletableFuture<String> future = processAsync(context); // 3. 流式输出结果 while (!future.isDone()) { String partialResult = context.getPartialResult(); if (partialResult != null) { writer.write(\"data: \" + partialResult + \"\\n\\n\"); writer.flush(); } Thread.sleep(getSleepTime(mode)); } // 4. 输出最终结果 String finalResult = future.get(); writer.write(\"data: \" + finalResult + \"\\n\\n\"); writer.write(\"data: [DONE]\\n\\n\"); writer.flush(); }}
4. 核心数据结构
4.1 消息数据结构
public class Message { private RoleType role; // USER, SYSTEM, ASSISTANT, TOOL private String content; // 消息内容 private String base64Image; // 图片内容(base64编码) private List<ToolCall> toolCalls; // 工具调用信息 private String toolCallId; // 工具调用ID private String name; // 工具名称 private Long timestamp; // 时间戳 // 构建器模式 public static Message userMessage(String content, String base64Image) { return new Message(RoleType.USER, content, base64Image, null, null, null); } public static Message systemMessage(String content) { return new Message(RoleType.SYSTEM, content, null, null, null, null); } public static Message assistantMessage(String content, List<ToolCall> toolCalls) { return new Message(RoleType.ASSISTANT, content, null, toolCalls, null, null); } public static Message toolMessage(String content, String toolCallId, String name) { return new Message(RoleType.TOOL, content, null, null, toolCallId, name); }}
4.2 任务计划数据结构
public class Plan { private String title; // 计划标题 private List<String> steps; // 任务步骤列表 private List<String> stepStatus; // 步骤状态列表 private List<String> stepNotes; // 步骤备注列表 private int currentStepIndex; // 当前步骤索引 private PlanStatus status; // 计划状态 // 计划推进方法 public void stepPlan() { if (currentStepIndex < steps.size()) { // 标记当前步骤完成 stepStatus.set(currentStepIndex, \"completed\"); // 推进到下一步 if (currentStepIndex + 1 < steps.size()) { currentStepIndex++; stepStatus.set(currentStepIndex, \"in_progress\"); } else { status = PlanStatus.COMPLETED; } } } // 获取当前任务 public String getCurrentTask() { if (currentStepIndex < steps.size()) { return steps.get(currentStepIndex); } return null; } // 获取当前任务状态 public String getCurrentTaskStatus() { if (currentStepIndex < stepStatus.size()) { return stepStatus.get(currentStepIndex); } return \"not_started\"; }}
4.3 工具定义数据结构
public class ToolDefinition { private String name; // 工具名称 private String description; // 工具描述 private Map