3.2 智能体开发与定制


3.2 智能体开发与定制

在体系中的位置:3.1 装好环境,这一节写第一个真智能体——把 2.2 的模型落到代码,并接上 2.6 的工具。这是你从"读框架"到"用框架"的真正的第一次动手。

先讲因果:为什么定制智能体不是"填个 prompt 就行"?因为生产里的智能体要满足三件事——知道自己是谁(角色)、会干特定的活(工具)、记得相关的事(记忆)。这三者组合出来的行为,靠一个通用 prompt 撑不住,必须显式组装。

用 ReActAgent 组装一个能干活的智能体

下面给一个完整、可运行的调研员智能体:带检索工具、带记忆、带明确角色。

import os from agentscope.agents import ReActAgent from agentscope.models import OpenAIChatModel from agentscope.memory import InMemoryMemory from agentscope.toolkit import Toolkit from agentscope.tools import tool from agentscope.message import Msg @tool def search_web(query: str) -> str: """联网检索关键词,返回前几条摘要。""" # 真实场景调用搜索 API;演示返回占位 return f"关于「{query}」的检索结果:AgentScope 支持多智能体编排。" tk = Toolkit() tk.register_tool(search_web) agent = ReActAgent( name="调研员", sys_prompt=( "你是严谨的调研员。用户给主题,你先用 search_web 查资料," "再基于资料输出带出处的结论。不要编造。" ), model=OpenAIChatModel(model_name="gpt-4o-mini", api_key=os.environ["OPENAI_API_KEY"]), toolkit=tk, memory=InMemoryMemory(), ) reply = agent(Msg(name="user", content="调研 AgentScope 的容错设计", role="user")) print(reply.content)

运行输出(典型):智能体内部先调 search_web("AgentScope 的容错设计"),拿到结果后组织成带出处的结论返回。reply.content 类似"根据检索,AgentScope 在通信中间件层提供重试与超时……"。工具调用的触发是模型基于 sys_prompt 和 docstring 决策的,不是硬编码。

1.x 写法对照:继承 AgentBase

存量项目多用旧写法。为兼容与理解,这里给对照版。注意 2.0 把这套循环内置了,旧写法需自己重写 reply

# 1.x 风格(兼容老项目,新项目建议用 3.2 上方的 ReActAgent) from agentscope.agents import AgentBase from agentscope.models import OpenAIChatModel from agentscope.tools import tool from agentscope.memory import Memory @tool def get_weather(city: str) -> str: """获取指定城市天气。""" return f"{city}:晴,25 摄氏度" class WeatherAgent(AgentBase): def __init__(self, name: str): super().__init__(name=name) self.model = OpenAIChatModel(name="qwen-turbo", api_key=os.environ["DASHSCOPE_API_KEY"]) self.memory = Memory() self.tool_list.append(get_weather) def reply(self, msg) -> "Msg": # 旧版需自行驱动思考-行动循环,或调用父类 reply response = super().reply(msg) return response bot = WeatherAgent(name="天气小助手") resp = bot.reply(Msg(role="USER", content="北京天气?", name="USER"))

解读:旧写法把"循环怎么跑"留给你,灵活但易错;2.0 的 ReActAgent 把循环固化,你只填配置。新项目优先 2.0,老项目迁移时可混用——AgentScope 两个版本 API 并非互斥。

定制记忆后端:长任务不断片

InMemoryMemory 重启即失。长任务换持久化后端(详见 2.5),这里给一个接入 SQLite 记忆的骨架示意:

# 长任务记忆示意(具体后端名以你所装版本为准) from agentscope.memory import InMemoryMemory # 占位,演示替换点 # mem = SqliteMemory(db_path="agent_mem.db") mem = InMemoryMemory() agent = ReActAgent(name="长工", sys_prompt="...", model=model, toolkit=tk, memory=mem) # 重启后若用持久化后端,mem 能读回历史,实现断点续跑

运行说明:持久化后端的类名随版本可能不同,核心是"替换 memory 字段即可,其余代码不动"。这正是 2.1 说的"灵活在配置"——换记忆后端不影响智能体其他部分。

案例:双角色协作写技术文档

背景:要产出"提纲 + 正文"的技术文档,两者知识结构不同(2.2 讲过的隔离收益)。

操作:规划者用 DialogAgent(只产提纲),写作者用 ReActAgent(可调检索补全)。两者入 MsgHub,规划者发言后写作者可见其提纲。

planner = DialogAgent(name="规划者", sys_prompt="只输出文档提纲,不写正文。", model=model) writer = ReActAgent(name="写作者", sys_prompt="基于提纲写正文,必要时检索。", model=model, toolkit=tk) async with MsgHub([planner, writer], announcement=Msg("user", "写 AgentScope 入门文档", "user")) as hub: await planner() # 产出提纲,自动广播 await writer() # 看到提纲后写正文

结果:提纲与正文由各自维持纪律的智能体产出,质量高于单智能体混杂。

解读:这里 DialogAgentReActAgent 的选型符合 2.2 建议——规划不调工具用 Dialog,写作需检索用 ReAct。

变式:若文档很短(几百字),拆两智能体反而多一次消息往返、增加延迟,此时单 ReActAgent 更划算。再次印证 1.3 的临界点判断要绑规模。

本节要点回顾

  • 2.0 用 ReActAgent 配置即智能体:name + sys_prompt + model + toolkit + memory 五件套。
  • 工具触发靠模型决策,依据是 sys_prompt 和工具 docstring,不是硬编码。
  • 1.x 继承 AgentBase 仍可运行,新项目优先 2.0,迁移时可混用。
  • 换记忆后端只改 memory 字段,其余不动——灵活在配置的体现。

⚠️ 别用 DialogAgent 硬扛需调工具的任务(2.2 已强调)。写作智能体要检索,就用 ReActAgent,否则工具调用不稳定会中途跑偏。

💡 定制智能体先列三件事:角色(sys_prompt)、会干的活(toolkit)、记得的事(memory)。三件齐了,行为才可控;缺一件,行为就漂移。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U