《构建自我编程智能Agent:大模型开发实践指南(收藏版)》

张开发
2026/4/10 8:26:50 15 分钟阅读

分享文章

《构建自我编程智能Agent:大模型开发实践指南(收藏版)》
《构建自我编程智能Agent大模型开发实践指南收藏版》本文深入探讨了如何设计并实现一个具备自我编程能力的智能Agent涵盖了技术架构优化、记忆系统设计及上下文工程等关键要素。文章详细介绍了Agent的工程架构、运行质量提升策略及经验积累方法为想要学习大模型开发的读者提供了宝贵的实践经验和优化路径。核心内容包括感知记忆、短期记忆、长期记忆的设计以及代码驱动逻辑的实现展示了如何通过Python Executor和Py4j实现代码生成与执行并强调了上下文工程在Agent决策中的核心作用。此外文章还讨论了Agent的工程结构、记忆分层、代码执行机制和反思要点为开发高效、稳定的AI Agent提供了全面的指导。1、Agent系统设计Agent简介技术架构方面我们在 ReAct Agent 模式基础上进行了深度优化改造传统 JSON 组装调用方式基于Py4j实现 Code泛化调用 机制显著提升工具调用的灵活性和执行效率采用 Spring Boot 技术栈构建后端架构整合 Spring AI 生态及 Spring AI Alibaba 能力完成模型接入通过 内部评测平台 和 内部观测平台 实现全链路评测与观测底层工具采用 Mcp 协议实现业务能力补充基于 A2A 协议实现 Multi Agent 架构高效对接各子 Agent模型策略采用混合部署方案根据不同场景使用最优模型翻译/数据提取任务Qwen3-Turbo低延迟优先思考/动态代码生成Qwen3-Coder强化代码能力通用场景按需调用各个平台提供的Qwen、Deepseek等模型 Agent内部模块分布Agent内部模块分布Memory 记忆Short Term Memory 短期记忆: Session维度的记忆仅在当前Session内生效Sansory Memory 感知记忆: 通过悬浮球捕捉的页面、url等环境感知记忆Experience 经验: 来自配置、总结的经验主要用于指导Agent各个环节的内容生成Context 上下文System Prompt: 配置化、动态化的系统提示词可配置的平台介绍 角色定义 工作机制 输入格式说明 输出格式要求 可用工具 重要原则 使用经验来自记忆的文本Inference Segment 推理段落(User Prompt)Round “轮”: 在复杂任务执行时每轮会作为一个单独的Segment用作当前轮次的执行总结和后续轮次的目标定义Express 表达: Agent返回给用户的内容Thought 思考: Agent在每一步执行时的思考内容Code 代码: 代码也会作为一个段落出现在Prompt中其他: 如果后续有其他的环节将作为新的Segment加入到User Prompt中Code 代码Python Executor: Java中通过调用本地的Python进程Py4j: Python回调Java代码的时候使用此工具实现回调的泛化调用Toolkit 工具包Python语义化模板设计: 提供将Toolkit转化为Python代码的模板设计模式在Prompt中使用模板方法生成Python代码参与Prompt中泛化调用。核心Coding驱动逻辑在我们的Agent中Segment采用 [Segment]: [Content] 的结构通过组合不同的Segment来形成Prompt从而实现CoTChain of Thought推理。除了外界工具我们还为Agent提供了系统工具使其能够获取和控制自身能力。这些能力包括检查已发起的任务、查询掌握的技能、主动休眠、主动与用户对话、通过大模型进行深度思考以及利用大模型解析数据等。在实现上每个工具箱都被设计为Python的一个Class其中的各项工具则作为函数实现。我们将不同的描述和属性都相应地映射为Python中的各种定义。由此我们打造出了一个自我编程驱动的Agent。在运行时它不仅能够调用外部能力还可以充分利用Python的原生功能保障数据的确定性如字符串运算、数字运算、时间运算等。更重要的是它能够实现自我控制可以发起复杂任务并对自身能力进行检查评估。PS除了我们的“人类程序员”外AI在这次迭代功不可没凭感觉大概有50-60%的无修改代码来自AI编写尤其是《代码驱动》环节几乎有80%的代码来自AI编写Agent工程结构Agent在我们的系统中一个Agent是一个线程。在Agent运行过程中将会在线程池中同时运行各个Area和Act。其生命周期如下图所示Area —— 功能区介绍Area的最初设计是来自1.0向2.0演进时创造出来的概念。其设计理念来源于人类的大脑分区我们将Agent的逻辑区域分成了感知区、认知区、表达区、自我评估区、运动区将不同种类的Act收纳到Area中让整个架构体系看着更加的清晰也让相同能力的动作可以具备相互沟通的可能。各功能区关系和详细介绍1感知区主要负责接收外部信息包括但不限于用户发送的消息、用户点击的卡片事件、子Agent的异步返回结果等。在接收到消息后感知区还会调用内部的Act对数据进行系列处理、评估用户主语言解析模糊化解析场景分析用户问题的增强解析环境感知的数据解析附件的数据针对不同搜索场景的2认知区当感知区完成系列解析后会将解析数据传递到认知区由认知区的IntentPlanner来使用Segment机制处理用户需求并生成对应代码。生成代码后提交给Python执行引擎进行执行。IntentPlanner ├── SegmentBuilder (成员变量) │ ├── ListInferencePromptNewBuilder promptBuilders │ ├── InferencePromptConfigManager (prompt配置管理) │ ├── build(type, segments, context, config) - InferenceSegment │ └── 路由到具体的PromptBuilder │ └── PromptBuilder实现类 ├── BaseInferencePromptBuilder (抽象父类) │ └── 使用InferencePromptConfigManager获取配置化prompt ├── ThoughtPromptBuilder ├── CmdPromptBuilder └── 其他自定义PromptBuilder[Act] IntentPlanner 核心思想用户输入后仅执行一轮逻辑若存在复杂任务则将任务移交给运动区处理3运动区(高级认知区)在当前Agent系统中运动区作为一种高级认知区将会承担复杂任务。当认知区的无法处理的任务被提交过来后。运动区将会发起一个内部循环来使用Segment的机制逐步完成任务。[Act] TaskExecutor 核心思想根据传入的目标逐轮执行计划每轮重新制定子目标本轮完成后都会评估任务进度任务完成后汇报给感知区若未完成重新评估目标达成情况若无法完成可以选择放弃若目标判断可以达成继续制定下轮目标Round 1 Segments: [User, Context, Thought1, Plan1, Cmd1, Evaluation1, NextGoal1] Round 2 Segments: [User, Context, Thought1, Plan1, Cmd1, Evaluation1, NextGoal1, Thought2, Plan2, Cmd2, Evaluation2, NextGoal2] Round 3 Segments: [所有历史Segments Thought3, Plan3, Cmd3, Evaluation3, NextGoal3]4表达区表达区负责将内部信息传递给外部包括但不限于发送给用户的话、发送给用户的卡片、发送给用户的系列事件。在传递文本时表达区一般不做过多总结在传递数据时表达区会根据历史Segment机制依据数据回答当前表达诉求在传递表单、复杂数据时表达区将会直接向用户传递数据。5自我评估区当IntentPlanner、TaskExecutor执行完初始目标后。将触发自我评估区的SelfTaskCheck评估任务完成情况。如果发现任务失败或是能执行的那么将重新触发回来源。2、Context Engineering 上下文工程上下文 与 Prompt在Agent中上下文和Prompt体系是整个Agent决策的核心组件。该体系通过Segment机制统一管理不同类型的Prompt构建过程实现了配置化、模块化的上下文组装和Prompt生成机制。在Prompt和上下文拼装的过程主要代码结构和逻辑如下图所示Context上下文组成Segments当前SegmentsSegments : 当前轮次已生成的Segment集合作用 : 提供当前轮次的执行状态和中间结果动态更新 : 随着当前轮次的进行不断增加新的Segment历史SegmentsSegments : 来自历史轮次的所有Segment集合作用 : 为Agent提供长期记忆和上下文连续性内容 : 包含用户输入、思考过程、执行代码、结果反馈等完整历史调用经验成功案例 : 基于历史成功案例的工具使用经验失败总结 : 从历史失败中提取的经验教训最佳实践 : 经过验证的代码模式和调用方式知识增强动态知识检索 : 基于用户查询的实时知识获取领域知识注入 : 特定场景下的专业知识补充上下文关联 : 与当前任务相关的背景知识环境上下文ToolkitContext : 包含会话ID、追踪ID、租户信息、执行过程的变量存储等执行环境SegmentBuildConfig : 包含模型配置、功能开关、知识增强设置等Agent状态 : 当前Agent的内部状态和能力配置工具上下文可用工具清单 : 动态获取当前可用的工具包和API工具描述 : 自动生成的Python风格的工具使用说明Prompt组成架构Prompt示例为了更好地理解我们的Prompt设计这里展示一个基于Prompt拼接思路编写的案例1System Prompt示例## 平台介绍 你是一个Agent专注于阿里巴巴DevOps平台的智能助手能够操作DevOps的相关平台。 ## 角色定义 你是一个专业的DevOps智能助手具备代码生成、工具调用、任务执行等核心能力。 ## 工作机制 基于用户输入和上下文信息通过思考-执行-评估的循环模式完成任务。 ## 输入格式说明 用户输入可能包含自然语言描述、页面截图、URL信息等多模态内容。 ## 输出格式要求 代码将以Fill-in-Middle(FIM)格式提供,包含三个部分: - |fim_prefix| 前缀代码 |fim_suffix| 后缀代码 |fim_middle| 你需要在 |fim_middle| 处续写代码,使前缀代码和后缀代码能够正确连接并执行。 注意: - 仅在 |fim_middle| 处续写代码 - 确保续写的代码与前后文逻辑连贯 - 不要修改或重复前缀和后缀中的代码 ## 可用工具 classexample_toolkit: def get_project_info(project_id): 获取项目基本信息 pass def search_requirements(project_id, query): 搜索需求信息 pass def create_requirement(project_id, title, description): 创建新需求 pass class normandy_toolkit: def get_app_list(project_id): 获取应用列表 pass def deploy_app(app_id, version): 部署应用 pass def get_deploy_status(deploy_id): 获取部署状态 pass ## 重要原则 1. 严格按照FIM格式输出代码 2. 确保代码的安全性和正确性 3. 优先使用提供的工具包完成任务 4. 对于不确定的操作要进行二次确认 ## 补充的增强知识在后台配置的一些知识点比如DevOps各个子系统间的关系、变更和分支的关系等 %s ## 历史经验自动学习后台配置的一些代码示例基于知识库团队提供的检索能力进行相关性召回 %s2User Prompt示例User: 帮我查询项目123的需求信息关键词是登录功能 Context: 当前页面URL为https://example.com/project/123用户正在查看项目概览页面 Thought: 用户想要查询项目123中关于登录功能的需求信息。我需要使用example_toolkit的search_requirements方法来完成这个任务。 Python: |fim_prefix|# 查询项目需求信息 project_id 123 query 登录功能 try: |fim_suffix| except Exception as e: print(f查询过程中发生错误: {str(e)})|fim_middle|期望返回结果# 调用工具查询需求 result example_toolkit.search_requirements(id 123, keyword 登录功能) # 处理查询结果 if result and result.get(success): requirements result.get(data, []) if requirements: print(f找到 {len(requirements)} 个相关需求:) for req in requirements: print(f- {req.get(title)}: {req.get(description)}) else: print(未找到相关需求信息) else: print(查询失败请检查项目ID或网络连接)System Prompt 结构我们采用 配置化 动态化 的系统提示词设计主要包含以下模块基础配置## 平台介绍 基于OpsInferencePrompt配置的平台能力介绍 ## 角色定义 Agent的角色定位和核心职责描述 ## 工作机制 Agent的工作流程和决策机制说明规范相关## 输入格式说明 用户输入的解析规则和格式要求 ## 输出格式要求 不同PromptBuilder的专属输出格式定义 - ThoughtPromptBuilder: 思考过程的结构化输出 - CmdPromptBuilder: FIM格式的代码续写规范能力增强## 系统基础 Agent的基础能力和限制说明 ## 可用工具 动态生成的工具包描述和使用方法 - Python语义化模板设计 - 泛化调用接口说明 - 工具调用示例经验## 使用经验 基于历史成功案例的少样本示例 ## 重要原则 核心的执行原则和安全约束 ## 常见错误 常见问题的预防和处理方案User Prompt 结构Segment List用户提示词主要由Segment序列组成按时间顺序排列User Segment: 用户的原始输入 Context Segment: 环境感知数据页面信息、URL等 Thought Segment: Agent的思考过程 Command Segment: 生成的执行代码 Evaluation Segment: 执行结果评估 NextGoal Segment: 下一步目标规划 ...FIM格式 (Fill-In-Middle)我们使用FIM格式进行代码续写。FIM技术基于论文Efficient Training of Language Models to Fill in the Middle[ https://arxiv.org/abs/2207.14255 ]是一种专门针对代码生成优化的技术代码将以Fill-in-Middle(FIM)格式提供,包含三个部分: - |fim_prefix| 前缀代码 |fim_suffix| 后缀代码 |fim_middle| 你需要在 |fim_middle| 处续写代码,使前缀代码和后缀代码能够正确连接并执行。 注意: - 仅在 |fim_middle| 处续写代码 - 确保续写的代码与前后文逻辑连贯 - 不要修改或重复前缀和后缀中的代码FIM技术的核心优势 上下文感知 : 模型能够同时理解前缀和后缀代码的语义精准填充 : 专门训练用于中间代码片段的生成而非从头编写逻辑连贯 : 确保生成的代码能够与前后文完美衔接FIM格式的实际结构|fim_prefix| # 已有上下文和代码 # 包含函数定义、变量声明等前置逻辑 |fim_suffix| # 后续期望的代码结构 # 包含返回值处理、异常处理等后置逻辑 |fim_middle| # LLM需要在此处填充代码 # 生成连接前后文的核心业务逻辑在Agent中的应用场景 逻辑补全 : 在明确输入输出的前提下补全中间的处理逻辑。3、记忆记忆系统是构建真正智能Agent的关键组件。正如人类认知系统依赖于复杂的记忆机制来学习、推理和决策AI Agent也需要类似的记忆架构来维持长期对话状态 在多轮交互中保持上下文连贯性积累经验知识 从历史交互中学习和改进支持复杂推理 基于历史信息进行更深入的分析个性化服务 根据用户历史偏好提供定制化体验Agent在处理复杂任务时主要依赖于上下文窗口来维持对话状态和任务记忆这种方式存在明显的局限性上下文长度限制 上下文窗口有固定的token限制无法处理超长的历史信息记忆组织缺失 简单的上下文拼接无法有效组织和检索历史信息知识更新困难 静态的上下文无法动态更新和优化已有知识计算成本高昂 长上下文处理需要大量的计算资源为了解决这些问题需要在Agent工程侧开发各种Agent记忆系统旨在为AI Agent提供持久化、结构化、可检索的记忆能力它记录了Agent过往的所见所闻和互动历程。记忆分层按照存储时间的记忆分类法最早是在 1968 年发布的 Atkinson-Shiffrin Memory Model 中提出将记忆分为感知记忆Sensory Memory、短期记忆Short-term Memory和长期记忆Long-term Memory。感知记忆存储了人脑从环境中捕获的信息例如声音、视觉等信息在感知记忆区这类信息只能保留很短的时间短期记忆存储人脑在思考过程中所需要处理的信息也被称为工作记忆在 1974 年 Baddeley Hitch 模型中提出通常也只能保留很短的时间长期记忆是指Agent中存储时间较长的信息它类似于人类大脑中的记忆能够保留大量的数据和经验并且可以存储很长时间甚至是永久性的。长期记忆和短期记忆在Agent中是相互补充的。短期记忆可以快速访问和处理当前需要的信息而长期记忆则提供了丰富的背景知识和历史数据。Agent需要将短期记忆中的信息与长期记忆中的知识结合起来以实现更智能的行为和决策。┌─────────────────────────────────────────────────────────────┐ │ 记忆分层 ├─────────────────────────────────────────────────────────────┤ │ 感知记忆 - 标签页维度 ├─────────────────────────────────────────────────────────────┤ │ 短期记忆 - 会话纬度 │ ├─ 会话记忆 | ├─ 实体记忆 │ └─ 工作记忆 ├─────────────────────────────────────────────────────────────┤ │ 长期记忆 │ ├─ 用户偏好 (业务实体记忆,...) - 用户纬度 │ ├─ 历史会话 (历史会话记忆总结) │ ├─ 用户画像 (角色定位、技能标签、工作习惯) | ├─ 平台知识 │ └─ 经验 └─────────────────────────────────────────────────────────────┘环境感知记忆鱼的记忆只有 7 秒实际上人也有非常多的记忆过目就忘但不管怎样这个记忆始终存在过。环境感知记忆是最短期的记忆只在当下这一瞬间有效的数据不具有长期价值。在网页上的任意动作都会让前一瞬间的数据失效例如打开抽屉/弹窗时之前感知到的数据可能就没有意义了如果要记得之前看过哪些东西则需要转成工作记忆或者沉淀到长期记忆中。使用场景在答疑场景中用户打开对话时大概率是遇到了问题需要寻找对应的解决方案。这个时候需要用户编写一些文字向 Agent 说明在哪个页面进行什么操作时遇到了什么问题。如果 Agent 能有一双眼睛跟用户一样看着当前的页面那么或许就能够提前帮用户预输入当前的上下文减少用户的使用成本。短期记忆在Agent中我们设计了基于Session级别的短期记忆存储基于ES实现。在短期记忆中会话、实体、工作记忆均被设计统一的Segment格式存储为Agent提供上下文连续性。用户对话 → 内部产生Segment → 短期记忆存储 → 下轮对话时检索 → 提供上下文记忆消息类型段落记忆消息存储推理段落信息是Agent执行过程的核心记忆载体。数据结构 :classSegmentMemoryMessageextendsShortTerm3MemoryMessage { InferenceSegment segment; // 推理段落内容 (Thought/Command/Evaluation等) String execId; // 所属执行ID标识当前轮次 ListString parentExecId; // 父节点执行ID列表支持执行链追溯 }实体记忆消息存储结构化实体信息用于记录关键对象和状态。数据结构 :classEntity3MemoryMessageextendsShortTerm3MemoryMessage { String title; // 实体标题/名称 Object data; // 实体数据内容(可为任意对象) }使用场景 :工具调用结果存储用户关键信息提取环境状态快照基础消息类型所有短期记忆消息的基类提供通用属性。数据结构 :abstract classShortTerm3MemoryMessage { String uuid; // 唯一标识符用于更新和删除操作 String sessionId; // 会话IDSession级别隔离 ListString tags; // 标签列表支持多维度分类 Long timestamp; // 创建时间戳用于时序管理 Long sortValue; // 排序值控制记忆优先级 }长期记忆知识点知识点目标是将内部积累的研发经验和专业知识系统化。特别是在与MCP系统集成后将能够模拟开发人员的问题解决思路提供更加专业和精准的支持。知识点的内容需要主要覆盖几个关键领域DevOps相关平台研发团队的工具/api/平台使用调用实战经验团队私有域知识除了正面的知识注入系统还包含了约束性知识例如平台使用的注意事项、特定场景下的最佳实践以及常见问题的标准处理流程。这些知识将直接影响Agent的响应策略和问题处理方式。值得注意的是这些新增的知识点与知识库的区别 新的知识点会作为Agent思考的Prompt的指引。往往包含“概念性”的内容。当一个知识沉淀成一个“文档”比较重又希望告知Agent的时候就可以使用短知识来进行维护短知识往往是一句话比如重新部署是流水线的概念重启是诺曼底的运维概念。代码执行经验这里描述的是接下来将推出的形态在目前版本中大模型投票机制还没有记忆的存储与检索目前只是在向量数据库中知识图谱方案还在对接中。在Agent每轮逻辑执行完成后本轮执行的细节将会被记录到经验记录表中。经过人工审核大模型投票机制会将记忆录入到知识库团队提供的经验图谱进行存储。在Agent每次使用大模型生成代码时将会从知识图谱中检索到对应的经验随后拼接到Prompt中的固定位置。用户偏好记忆通过环境感知根据用户页面访问情况实时动态上报业务实体操作作为业务实体记忆上下文。Memory部分接收环境感知上报的数据进而转换成业务实体记忆存储(BizEntityMemroy),BizEntityMemroy主要组成部分:schema: 定义业务实体的结构schemajson schema格式data: 定义业务实体的具体数据operation: 平台操作tags: 实体标签历史会话记忆用户通过助手进行会话时由Agent规划模块进行意图识别并规划Task。在规划Task执行完成时对会话记忆进行总结。HistoryChatMemory(历史会话总结记忆)存储结构{ time: 2025-09-18 17:14:00 question_type: 操作实施, keys: 应用名: example, summary: 用户在明天(2025-09-18 14:00:00)有一个example的发布计划, userId: }历史会话记忆检索通过全文向量融合查询召回会话记忆向量化字段keysfilteruserId记忆淘汰策略4、代码驱动在 Agent 开发的早期我们用业界必选的Agent实现方式走了LLM返回JSON 固定文本前缀的路。这看起来是最直观的选择我们的Agent 1.0 和 2.0 版本都是这么实现的。但随着项目深入作为一个重工具调用的Agent频繁调用Mcp、Agent的问题接踵而至数据格式虽然可以保证但是内容质量并不能保证Token 超长导致的性能下降JSON 格式不够稳定多轮对话既要保证灵活性又要保证速度无论是对接 Mcp 还是 A2A想要又快又准确地调用各种能力都面临着重重困难。我们也在不断借鉴业界各领域的优秀实践从 mem0 到 JManus但始终觉得差点意思。为了提高任务成功率我们牺牲了响应速度为了提升速度我们又不得不降低灵活性而灵活性的降低恰恰又导致了任务成功率的下降。这似乎成了一个难解的死循环。2.0 版本虽然是对 1.0 的全面重构但经过一段时间的实践我们发现它在执行逻辑时总是一条路走到黑一旦开始节点错了就很难再纠正回来。正当我们为此困扰时一次偶然的发现给了我们启发在研究 Github Copilot Agent 时我们注意到它使用 JavaScript 来定义工具。虽然它最终还是用 JSON 来调用但这个设计却让我们灵光一现 —— 为什么不让 Agent 直接通过编写代码来实现自己的逻辑呢代码执行在Agent中代码与执行部分是整个系统的核心执行引擎。它实现了从代码生成到执行再到结果反馈的完整闭环让Agent真正具备了自我编程的能力。Python Execution Engine [Java]PythonExecutionEngine作为整个代码执行的引擎设计上采用了线程池异步执行监控的架构模式。本质上就是用Java发起Python让Python执行代码调用工具时回调Java同时Java负责调度和监控。核心设计思想异步执行 : 每个Python脚本都在独立线程中运行避免阻塞主流程生命周期管理 : 从执行ID生成到结果回收全程可追踪超时控制 : 防止Python脚本死循环默认3600秒超时资源隔离 : 每个执行都有独立的上下文环境脚本执行流程执行流程准备阶段 : Agent把生成的Python代码传递给PythonExecutionEngine初始化 : 分配执行ID设置上下文注册工具包执行 : 启动Python进程加载toolkit_bridge.py监控 : ExecutionMonitor实时跟踪执行状态收尾 : 收集结果清理资源反馈给Agent代码执行的核心逻辑在PythonScriptExecutor中它负责动态生成Python运行环境注入toolkit_bridge.py作为桥接层管理Python进程的生命周期处理标准输出和错误输出安全与监控执行日志 : 记录每次代码执行的详细信息性能监控 : 统计执行时间、成功率、错误分布安全检查 : 虽然还没完全实现但预留了代码安全扫描的接口。此处应该严格禁止某些系统函数的调用比如随便引用import、使用os操作系统文件等资源监控 : 监控Python进程的CPU和内存使用。Toolkit Bridge [Python]Toolkit Bridge是整个Python和Java沟通的桥梁可以说是这套架构中最关键的一环。它解决了Python怎么调用Java工具包这个核心问题。Py4j桥接机制我们用Py4j来实现Python和Java的双向通信。简单来说Java实现一个Py4j的Gateway ServerPython对接到这个Server中就能互相调用了。关键设计点单例Gateway : 全局只维护一个Gateway连接避免重复连接开销连接池化 : Gateway连接失败时自动重试保证连接的稳定性端口固定 : 默认使用15333端口避免端口冲突会话上下文管理SessionContext解决了Python代码怎么知道当前是哪个用户、哪个会话的问题classSessionContext: def __init__(self): self._data {} self._toolkit_context None def set_data(self, key, value): 设置会话数据如session_id、trace_id等 self._data[key] value每次Python脚本执行前Java会把session_id、trace_id、用户信息等存储到SessionContext里这样Python代码调用工具包时就知道自己代表哪个用户在执行了。异步调用支持PythonToolkitProxy这个类是我们的核心调用逻辑他提供一个动态代理入口它让Python代码可以像调用本地函数一样调用Java工具包classPythonToolkitProxy: def __init__(self, toolkit_name): self.toolkit_name toolkit_name def __getattr__(self, operation_name): async def async_operation_method(*args, **kwargs): return await call_toolkit_async(self.toolkit_name, operation_name, kwargs) return async_operation_method这样Python代码就能这么写# 这样调用就行了简单直观 result await example_toolkit.get_project_info(project_id123)就可以调用到在Java中的代码了publicclassExampleToolkit{ public Object get_project_info(String projectId){ return null; } }运行参数捕捉机制参数处理这块我们踩了不少坑。最开始位置参数和命名参数混用会出问题后来做了参数规范化捕获运行参数 使用装饰器标记在对应的函数上那么就能获取到函数中的临时变量了参数统一 : 优先使用命名参数位置参数自动转换类型转换 : DynamicEntity等Java对象自动转换为Python字典序列化 : 所有参数最终都序列化为JSON传递给Java端def capture_execution_variables_async(): 装饰器捕获异步Python函数执行时的局部变量 def decorator(func): functools.wraps(func) async def wrapper(*args, **kwargs): captured {} def tracer(frame, event, arg): if event returnand frame.f_code func.__code__: try: # 复制局部变量过滤掉内部变量 for key, value in frame.f_locals.items(): ifnot key.startswith(_) and key not in [args, kwargs]: # 检查值是否可序列化 try: json.dumps(value, defaultstr, ensure_asciiFalse, clsDynamicEntityJSONEncoder) captured[key] value except (TypeError, ValueError): # 对于不可序列化的对象转换为字符串 captured[key] str(value) except Exception as e: print(fExecutionVariableMonitor capture error: {e}) return tracer sys.settrace(tracer) try: result await func(*args, **kwargs) finally: sys.settrace(None) # 保存变量到全局context中供Java侧获取 if hasattr(sys.modules[__name__], captured_variables): sys.modules[__name__].captured_variables.update(captured) else: sys.modules[__name__].captured_variables captured.copy() # 输出捕获的变量使用特殊格式供Java端解析 for key, value in captured.items(): print(fVARIABLE_CAPTURED:{key}{json.dumps(value, defaultstr, ensure_asciiFalse, clsDynamicEntityJSONEncoder)}) return result return wrapper return decorator通过注解捕捉到运行参数后会在完成运行后由java解析并存储到redis里面。当下次执行的时候会从redis取出会话中的参数。以实现在下轮对话中可以感知到上轮对话的变量及内容。# 第一轮对话 def main(): a 1 # 第二轮对话 a 1 # 通过redis回放回来的参数 def main(): print(a1)Toolkit Mapper [Java]ToolkitMapper是整个工具包体系的调度中心它负责把Python的调用请求路由到具体的Java工具包实现。工具包映射与路由核心路由逻辑很直接根据toolkit_name找到对应的实现类然后调用对应的operation方法。但实际实现中有几个关键点动态路由 : 通过sessionId找到对应的Agent3实例再通过Agent的AgentToolkitManager来执行具体操作类型适配 : 不同类型的工具包有不同的接口ToolkitMapper负责做适配结果包装 : 所有返回结果都通过ResultWrapper进行统一包装数据传递机制为了实现让历史Python运行的临时参数可以被传递到下次运行Python的过程中我们在数据传递过程中在Java内部通过Base64将原始数据反编译然后使用参数传递到python脚本中。Python脚本拿到Base64之后自行解码将数据在内存恢复到目标参数中。方法调用机制我们在Agent、Mcp的Toolkit中将技能/工具映射成方法Agent/McpServer映射成Class。每个Agent、McpServer都对应一个独立的Toolkit。因此当某个Toolkit被调用时将会拿到自身的class、方法名从而找到对应的技能/工具进行泛化调用。Toolkit工具包Toolkit体系是整个Agent能力的具体体现它把抽象的智能助手落地为可执行的工具包。我们设计了四大类工具包每类都有自己的特色和应用场景。Custom Card Toolkit自定义卡片工具包是我们为了解决Agent怎么和用户交互这个问题而设计的。传统的文本对话太单调我们需要更丰富的交互形式。卡片组件系统卡片系统采用了组件化的设计思路每个卡片都是一个独立的UI组件支持的卡片类型转人工卡片 : 支持用户有转人工意图时发送卡片进行转人工处理运维卡片 : 用户想要进行运维操作时将会发送运维卡片Mcp ToolkitMcpModel Context ProtocolToolkit是我们对接外部服务的标准化接口。通过Mcp协议我们可以快速集成各种外部能力而不需要为每个服务单独开发适配器。Agent ToolkitAgent Toolkit实现了Agent之间的协作机制。在复杂任务场景下单个Agent可能无法独立完成所有工作需要和其他专业Agent协作。A2A协议支持A2AAgent to Agent协议定义了Agent间交互的标准格式任务分发 : 主Agent将复杂任务分解后分发给子Agent进度汇报 : 子Agent定期汇报任务执行进度异常处理 : 子Agent执行失败时的异常上报机制资源协调 : 多个Agent竞争同一资源时的协调机制工具包注册与管理工具包的注册与管理是整个Toolkit体系的基础设施它支持多种注册方式和管理机制。我们设计了两套并行的注册体系基于接口的动态工具包和基于注解的声明式工具包它们各有适用场景互不耦合。动态工具包注册动态工具包是我们的核心注册机制通过实现DynamicToolkit接口来定义工具包public interface DynamicToolkit { String name(); // 工具包名称 String getClassComment(); // 工具包描述 MapString, String getMethodPython(); // Python方法定义 MapString, Type[] getMethods(); // 方法参数类型 MapString, String[] getParameterNames(); // 参数名称 Object execute(String methodName, String execId, MapString, Object params); }接口驱动 : 所有动态工具包都实现DynamicToolkit接口保证接口的一致性运行时注册 : 工具包可以在运行时动态注册和卸载支持热插拔元数据自描述 : 工具包自己描述自己的能力和接口无需外部配置典型的动态工具包实现Component publicclassExampleDynamicToolkitimplementsDynamicToolkit { Override public String name(){ returnexample_toolkit; } Override public Object execute(String methodName, String execId, MapString, Object params){ // 动态分发到具体方法 switch (methodName) { caseget_project_info: return getProjectInfo(params); // 其他方法... } } }注解式工具包注册注解式注册是一种声明式的工具包定义方式适合结构相对固定的工具包ToolkitComponent( python system_toolkit, description 系统级工具包提供基础的系统操作能力 ) publicclassSystemToolkit { ToolkitOperation(python send_message) public ToolkitResult sendMessage(MapString, Object params){ // 发送消息的具体实现 } ToolkitOperation(python get_current_time, enabled true) public ToolkitResult getCurrentTime(MapString, Object params){ // 获取当前时间的具体实现 } }声明式配置 : 通过注解声明工具包的元数据简化配置编译时检查 : 注解在编译时就能发现配置错误Spring集成 : 与Spring的Bean管理机制无缝集成注册机制分离设计两种注册机制在实现上完全分离各自有独立的处理流程独立注册表 : DynamicToolkitRegistry和AnnotationToolkitRegistry分别管理两类工具包统一访问 : ToolkitMapper提供统一的访问接口屏蔽底层注册机制的差异互不干扰 : 两种机制可以独立开启或关闭不会相互影响5、反思开发一个Agent需要做的几件事情经过三轮Agent的升级与优化关于如何打造优质AI Agent我结合Agent实践经验总结几点核心要素Prompt组装与上下文工程的合理设计上下文管理影响多轮对话的稳定性。在搭建Agent时需要对Prompt进行单独的设计明确Prompt的组成部分、上下文的选择、Agent运行过程的不同形态下上下文的组装方式等。推荐的Prompt/上下文开发过程可以先准备一段完整的比较粗糙的prompt其中记忆、经验相关的内容都先使用mock的方式拼接在其中然后使用LLM的api对prompt的效果进行初步验证验证没问题后可以进入代码实现将prompt按逻辑和结构拆分成多个部分例如自我介绍、工作机制、输入格式、输出格式、示例等然后分别实现每个部分后续需要在运行过程中不断调整prompt可以在每次发现bad case的时候将目前的prompt、出现的问题和自己的思路发给LLM让LLM帮助优化我们在前两个版本的时候Prompt组装是没有系统性、结构性设计的这也就导致了过程中出现了一个900多行的超级大的Prompt它里面各个位置的内容都是比较乱的。Prompt和上下文的组装、拼接经过了单独的设计实现的代码中对其组装也模板设计模式、Builder设计模式的组合来完成Prompt的拼接。Agent的工程架构设计也很重要工程架构直接影响交互体验的流畅度。工程层面Agent需要考虑Agent运行过程如何持久化、优雅上下线、任务的完成与失败如何定义和管理、日志/监控/可观测/评测制度的建立、记忆如何管理。模型决定上限工程决定下限这种说法就像曾经的PHP是世界上最好的语言一样片面。实际上二者是相辅相成的关系。有些产品即便采用了Claude这样的强大模型整体效果反而不如使用Deepseek但工程实现更优秀的同类产品。关键在于模型能力与工程细节的契合度。在工程层面比如工具调用编排、用户交互设计、内部流程优化等都需要在工程层面深度打磨才能充分发挥模型潜力。过分迷信模型能力而死等模型升级是不可取的。Agent提高运行质量和稳定性可以通过让他自我积累、自我学习经验积累则确保跨会话的一致性。不论是JSON、文本前缀还是Coding驱动经验都是一个好东西。它可以大大地提高返回数据的稳定性。这里分享几篇论文《ExpeL: LLM Agents Are Experiential Learners》《How Memory Management Impacts LLM Agents: An Empirical Study of Experience-Following Behavior》《Get Experience from Practice: LLM Agents with Record Replay》简单来说经验的组装就是收集 - 加工 - 存储 - 检索在Agent运行过程中 收集一切有用的信息随后在完成运行后通过 LLM 或者各种解析逻辑加工成一段文本、一个json代表本次执行的起因、经过、结果、思考等信息。随后存储到数据库中不仅局限于向量数据库。在Agent运行阶段将用户文本做简单加工随后进行检索。 只不过在工程层面检索过后的结果可以用作“回放”可以用作“Prompt”拼接。单纯的向量数据库检索不一定能让经验检索变得准确我们目前正在向图索引的方向探索让图谱的能力辅助经验的检索与加工。展望目标定位我们的最终目标是致力于让它成为可靠的1.5线答疑助手具备初级程序员1-3年的知识储备和问题解决能力同时拥有自我进化和持续学习能力。优化路径除了调用过程是代码拼接Prompt能否变得更加动态甚至在Cmd、Thought阶段的Prompt都是由Agent自我选择Toolkit拼装的在IntentPlanner阶段并非是不可循环的我们后续会把IntentPlanner、TaskExecutor的底层能力合并提供一个通用的Coding驱动Agent模型基于此模型实现各层的ReAct操作任务间的上下文隔离还需要做的更加精细知识点和经验的数据需要持续保鲜Mcp和Agent的深度和广度都需要持续提升开发一个桌面应用程序随时随地可以唤起日志、观测、报表、监控、评测机制的的完善。最后近期科技圈传来重磅消息行业巨头英特尔宣布大规模裁员2万人传统技术岗位持续萎缩的同时另一番景象却在AI领域上演——AI相关技术岗正开启“疯狂扩招”模式据行业招聘数据显示具备3-5年大模型相关经验的开发者在大厂就能拿到50K×20薪的高薪待遇薪资差距肉眼可见业内资深HR预判不出1年“具备AI项目实战经验”将正式成为技术岗投递的硬性门槛。在行业迭代加速的当下“温水煮青蛙”式的等待只会让自己逐渐被淘汰与其被动应对不如主动出击抢先掌握AI大模型核心原理落地应用技术项目实操经验借行业风口实现职业翻盘深知技术人入门大模型时容易走弯路我特意整理了一套全网最全最细的大模型零基础学习礼包涵盖入门思维导图、经典书籍手册、从入门到进阶的实战视频、可直接运行的项目源码等核心内容。这份资料无需付费免费分享给所有想入局AI大模型的朋友扫码免费领取全部内容部分资料展示1、 AI大模型学习路线图2、 全套AI大模型应用开发视频教程从入门到进阶这里都有跟着老师学习事半功倍。3、 大模型学习书籍文档4、AI大模型最新行业报告2025最新行业报告针对不同行业的现状、趋势、问题、机会等进行系统地调研和评估以了解哪些行业更适合引入大模型的技术和应用以及在哪些方面可以发挥大模型的优势。5、大模型大厂面试真题整理了百度、阿里、字节等企业近三年的AI大模型岗位面试题涵盖基础理论、技术实操、项目经验等维度每道题都配有详细解析和答题思路帮你针对性提升面试竞争力。6、大模型项目实战配套源码学以致用在项目实战中检验和巩固你所学到的知识同时为你找工作就业和职业发展打下坚实的基础。学会后的收获• 基于大模型全栈工程实现前端、后端、产品经理、设计、数据分析等通过这门课可获得不同能力• 能够利用大模型解决相关实际项目需求 大数据时代越来越多的企业和机构需要处理海量数据利用大模型技术可以更好地处理这些数据提高数据分析和决策的准确性。因此掌握大模型应用开发技能可以让程序员更好地应对实际项目需求• 基于大模型和企业数据AI应用开发实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能 学会Fine-tuning垂直训练大模型数据准备、数据蒸馏、大模型部署一站式掌握• 能够完成时下热门大模型垂直领域模型训练能力提高程序员的编码能力 大模型应用开发需要掌握机器学习算法、深度学习框架等技术这些技术的掌握可以提高程序员的编码能力和分析能力让程序员更加熟练地编写高质量的代码。扫码免费领取全部内容这些资料真的有用吗这份资料由我和鲁为民博士(北京清华大学学士和美国加州理工学院博士)共同整理现任上海殷泊信息科技CEO其创立的MoPaaS云平台获Forrester全球’强劲表现者’认证服务航天科工、国家电网等1000企业以第一作者在IEEE Transactions发表论文50篇获NASA JPL火星探测系统强化学习专利等35项中美专利。本套AI大模型课程由清华大学-加州理工双料博士、吴文俊人工智能奖得主鲁为民教授领衔研发。资料内容涵盖了从入门到进阶的各类视频教程和实战项目无论你是小白还是有些技术基础的技术人员这份资料都绝对能帮助你提升薪资待遇转行大模型岗位。这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

更多文章