基于 DeepSeek + OpenAI Agent 构建 Agent 实战
本文档基于 openai-agents 官方文档,详细介绍了一个支持异步调用的多智能体系统,实现了各个智能体的明确分工协作。 其实在我看来,这个框架的本质是:把 Swarm 改进成支持异步调用,并把手写 Agent 传递变成 Handoff 的封装,可能也做了增加稳定性的优化。
安装指南 使用以下命令安装依赖包:
1 pip install openai-agents
基础使用流程 系统使用包含以下两步:
Agent 定义
Agent 执行 (输入用户问题)
基础示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from agents import Agent, Runner, set_default_openai_client, set_default_openai_api, set_tracing_disabledfrom openai import AsyncOpenAIcustom_client = AsyncOpenAI(base_url="base_url" , api_key="sk-xxxxx" ) set_default_openai_client(custom_client) set_default_openai_api("chat_completions" ) set_tracing_disabled(True ) libai_agent = Agent( name="libai" , model="deepseek-r1" , instructions="模拟李白风格,根据用户输入创作诗歌。" ) result = Runner.run_sync(libai_agent, "请创作一首描写科举考生赴京场景的诗。" ) print (result.final_output)
执行后可能输出如下:
1 2 3 4 5 6 7 《赴京举子》 万里风尘逐帝京,八方士子共云程。 墨香暗度关山月,剑气遥连北斗星。 金殿未登龙虎榜,青衫已染凤凰名。 何须更问功成事,醉卧长安笑公卿。 注:本诗采用李白豪放飘逸的笔法,描绘了举子千里赴京的宏大场景。诗中运用"墨香剑气"暗喻文韬武略,以"龙虎榜"与"凤凰名"展现功名与气节的对比,末联"醉卧长安"体现了对科举制度的超然态度,同时也反映了盛唐气象,延续了李白诗作中特有的浪漫气质与历史纵深感。
以上展示了系统的基本工作流程:Agent 定义、执行两个步骤。
复杂任务 在处理复杂任务时,系统可能面临以下技术挑战:
语言模型能力要求 :需要同时具备推理规划和函数调用能力
提示词复杂度 :需要同时处理规划制定、函数调用和结果输出
缺乏系统性规划 :每次 Function Call 后重新思考,缺乏连贯的执行计划
(注:DeepSeek-R1 目前尚未支持函数调用功能)
解决方案:采用多智能体分工协作模式,将单一大型语言模型拆分为多个专门化的智能体。每个智能体负责特定任务,便于系统优化和评估。
我们遵循”智能体职责分离”原则,实现模块化设计,提高系统可维护性和可扩展性。
下面大致介绍一下工作流程:
系统工作流程示意:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 用户输入: "please show me the menu" │ ▼ 规划智能体【系统管理器】(Deepseek-R1) 分析用户输入并确定调用策略: "调用智能体:菜单管理智能体 用户原始输入:请展示菜单" │ ▼ 分配智能体【服务管理器】(Deepseek-V3) 接收指令并执行: -> llm function call:show_order_menu │ ▼ 获取菜单数据: -> 执行 show_order_menu 函数 │ ▼ 语言处理智能体【多语言适配器】(Deepseek-V3,根据用户语言选择对应处理模块) -> 如英文翻译agent:english_translator │ ▼ 返回处理后的菜单数据(包含处理模块标识) │ ▼ 向用户返回处理结果
进阶实现示例 以下代码展示了多智能体协作系统的完整实现流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 import asynciofrom agents import Agent, Runner, set_default_openai_client, set_default_openai_api, set_tracing_disabled, function_toolfrom openai import AsyncOpenAIcustom_client = AsyncOpenAI(base_url="base_url" , api_key="sk-xxxxx" ) set_default_openai_client(custom_client) set_default_openai_api("chat_completions" ) set_tracing_disabled(True ) english_translator = Agent( name="English translator" , model="deepseek-v3" , instructions="你处于一个多Agent工作流中,职责是英文翻译,将收到任何文本(包括tool中)返回成英文结果。(请务必遵从以上原则,否则会破坏工作流)最后你要以你的身份来作为结尾告诉我这是来自谁的答复,如This response comes from the English translator." , ) chinese_translator = Agent( name="Chinese translator" , model="deepseek-v3" , instructions="你作为中文翻译,将收到任何文本返回成中文结果。你要以你的身份来作为结尾告诉我来自谁的答复" , ) @function_tool def show_order_menu (): menu=''' 1. 美式咖啡 ¥10 2. 拿铁 ¥15 3. 卡布奇诺 ¥15 4. 摩卡 ¥20 5. 热巧克力 ¥15 6. 红茶 ¥10 7. 松饼 ¥10 8. 蛋糕 ¥15 ''' print (menu) return "你向顾客展示了" +menu agent_dispatcher = Agent( name="dispatcher" , model="deepseek-v3" , instructions="你是副总管,请根据用户的问题调用相关工具,拿到相关工具结果后,再根据用户的文本语言选择合适的翻译Agent帮助你回复" , handoffs=[chinese_translator,english_translator], tools=[show_order_menu] ) agent_planner = Agent( name="planner" , model="deepseek-r1" , instructions=( "你现在处于多智能体协作流程中,身份是 Agent 总管。你的任务是:" "根据用户的问题分析并决定调用哪种功能,告诉副总管应该调用哪个Agent或tool处理用户的问题,最后加入用户原文" "仅输出该指令文本,不包含任何具体答案。示例如:Agent_planner->Agent_dispatcher: @MenuAgent @MenuTool: plz show me the menu" ), ) async def main (): reply=None question = "plz show me the menu" orderFromPlanner = await Runner.run(agent_planner, question) print ("planner输出:" , orderFromPlanner.final_output) result = await Runner.run(agent_dispatcher, input =orderFromPlanner.final_output) print ("dispatcher输出:" , result.final_output) if __name__ == "__main__" : asyncio.run(main())
系统自检机制 系统实现了自检功能,通过在响应智能体中加入异常检测逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 agent_response = Agent( name="Agent 回复" , model="deepseek-r1" , instructions=( "你现在负责整理多智能体的输出,生成最终回复。" "输入包含各 Agent 的输出和用户问题。" "如果发现流程异常,有两种情况:" "如果发现流程异常,有两种情况:" "1. 可通过重新生成问题并执行流程解决,请在开头输出RETRY加重试次数1(若原文中已包含重试次数,则重试次数+1)便于程序做判断,接下来你的输出会作为新的用户输入,请你根据用户问题(保留原文原意原语音)重新生成易于命中的问题。" "2. 工作流或重试次数超过3次,请在开头输出ERROR,并在接下来分析原因。" ), ) async def main (): response = None query = "plz show me the menu " while True : orderFromPlanner = await Runner.run(agent_planner, query) print ("总管输出:" , orderFromPlanner.final_output) result = await Runner.run(agent_dispatcher, input =orderFromPlanner.final_output) print ("结果输出:" , result.final_output) response = await Runner.run(agent_response, input ="用户输入:" + query + "\n系统指令:" + orderFromPlanner.final_output + "\n执行结果:" + result.final_output) if response.final_output.startswith("RETRY" ): print ("重试" ) query = response.final_output else : print ("系统响应:" , response.final_output) break
异常处理示例:
当出现异常如下文,系统将触发自检机制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 总管输出: Agent_planner->Agent_dispatcher: @MenuAgent @MenuTool: plz show me the menu plz show me the menu 1. 美式咖啡 ¥10 2. 拿铁 ¥15 3. 卡布奇诺 ¥15 4. 摩卡 ¥20 5. 热巧克力 ¥15 6. 红茶 ¥10 7. 松饼 ¥10 8. 蛋糕 ¥15 结果输出: {'assistant': '中文翻译'} #这里由于偶然性走到了中文翻译,所以输出的是中文翻译,在自检中检测出来并优化重试 总管输出: Agent_planner->Agent_dispatcher: @MenuAgent @MenuTool: plz show me the current menu items and prices in English 1. 美式咖啡 ¥10 2. 拿铁 ¥15 3. 卡布奇诺 ¥15 4. 摩卡 ¥20 5. 热巧克力 ¥15 6. 红茶 ¥10 7. 松饼 ¥10 8. 蛋糕 ¥15 结果输出: You have displayed the following items to the customer: 1. Americano - ¥10 2. Latte - ¥15 3. Cappuccino - ¥15 4. Mocha - ¥20 5. Hot Chocolate - ¥15 6. Black Tea - ¥10 7. Muffin - ¥10 8. Cake - ¥15 This response comes from the English translator. 系统响应: The current menu items and prices in English are as follows: 1. Americano - ¥10 2. Latte - ¥15 3. Cappuccino - ¥15 4. Mocha - ¥20 5. Hot Chocolate - ¥15 6. Black Tea - ¥10 7. Muffin - ¥10 8. Cake - ¥15 Let me know if you need further assistance!
以上展示了基于”规划-执行”模式的多智能体系统实现:
通过将任务处理流程分解为规划层(系统管理器、服务管理器)和执行层(功能模块、语言处理模块),实现了智能体的职责分离,同时充分利用了 DeepSeek 等模型在推理方面的优势,规避了其在函数调用等方面的限制。系统还实现了自检和异常处理机制,提高了系统的可靠性和稳定性。