hi~
上一篇,雄哥做了:
把GraphRAG当工具接入Agent的示例!
智能体自主决策何时查知识图谱数据,让KG始终支撑Agent干活!
实际,Agent支持接入任何数据库/外部工具,沿本方向跑,可拓展无数实践!
但这,只是在整个MAS(多智能体系统)中,最简单示例!
函数生成+执行=执行决策+获取信息动作!
还,干不了复杂任务!
因为:MAS远远不止函数调用
那,究竟什么是多智能体系统?如何做?
今天,跟着雄哥动手做一个“五脏俱全”的多智能体系统!
同时!
这也是MAS系列的补充,接下来几个月时间,雄哥也会在Agent领域,动手做实践!
一边动手一边学技能点!
未看之前内容?
简单来说就是:目标分解、计划、协调、共享记忆、反馈感知、执行...!
许多朋友可能已经看过很多这样介绍!后面雄哥用代码说明;
这好比:
在公司,项目经理,将复杂项目(比如写代码/写报告/洗数据..)拆分为较小任务,分配不同专业员工,去执行,回收结果,持续优化,达成目标!
沿着这条线,继续深入!
雄哥准备了这些内容,理论+代码:
① 巅峰的Agent有哪些关键组件?
② 细拆!MAS(多智能体系统)是怎样工作的?
③ 动手跑代码!边跑边聊细节!实现Agent+MAS!
以上,学完需1小时左右!
你一定要花一个下班时间,老实坐在电脑前,动手做!才能学会!
否则只是泛泛之识,恐怕吸收不到!
除了这些,雄哥已围绕大模型,做过微调、数据预处理、RAG0-1、知识图谱、Agent等内容了!
成为【意友圈】会员,全部系统地学一次!能帮你提速至少90天!
许多会员,都在社区,保持自己的项目,始终在正途发展的!
识别下方二维码即可加入
人的专注力只有10分钟,那,话不多说,开始今天内容!
第一部分:有哪些关键组件?如何工作?
AI Agent的核心,是由大型语言模型(LLM)驱动支持的实例。
至于什么是Agent,这样的知识,雄哥之前分享过无数次,默认你学过;
它将复杂的任务分解为可管理的步骤,使用各种工具来完成这些步骤,并从中学习经验,然后计划、推理、评估监管和采取行动,实现目标。
这就区别于当下市面大部分的LLM服务!
绝大部分的交互还知识chat对话,不具备复杂任务能力!
少部分产品,也仅仅做到单Agent+单线程驱动,确保尽可能安全可控情况下:
智能体 都在--> 多智能体系统
今天,跟着雄哥,把MAS拆开,把5个关键组件拎出来!
即:
组件 | 描述 |
LLM(大脑) | 代理的核心,负责文本处理、理解上下文并做出决策。 |
规划 | 将目标分解为一系列可管理任务,按优先级排序并根据新信息调整计划。 |
行动 | 使用工具和API与环境交互,执行如搜索、代码执行、数据访问等任务。 |
评估与监督 | 定义代理的行为、个性、沟通风格、专业化,确保响应符合预期目标。 |
记忆 | 存储和回忆过往交互,保持对话上下文,支持个性化和长期学习。 |
1.1 LLM(大脑)
代理的核心,负责文本处理、理解上下文并做出决策。
MAS系统中,每一个LLM都是各司其职,1个LLM=1个人
1个财务岗,他可以处理销售部的任务,当然也可以处理开发部的任务;
所以整个系统是并行多线程的,从不是单个Agent就能干完这些事
那如何能让一个Agent,掌握胜任“财务岗”的能力呢?
这里有两种方法:
1(明文提示)-是手把手教,把工作过程一步步写出来,照葫芦画瓢
2(微调训练)-是把知识真正从0学到1
后面雄哥会基于这两种方法,独立做一个系列,如何合成数据、如何微调、如何评估等,关注雄哥!
下面提到的规划、行动、评估、记忆,都离不开多个LLM来完成;
1.2 规划
代理的关键能力之一,是其规划能力。
此组件允许代理将复杂的目标,分解为一系列可管理的任务,规划模块能够:
#A 分析给定目标
#B 确定实现目标的必要步骤
#C 按逻辑顺序确定这些步骤的优先级
#D 根据获取的结果调整计划
有效规划=有效解决问题
尤其是复杂的多步骤问题,这里,简单做个生成式 AI 任务:
{
"task": "使用AI代理生成医疗建议",
"planning": {
"inputs": {
"user_preferences": [
"主题",
"关键词",
"语气"
],
"trending_data": "获取用户偏好的内容"
},
"workflow": [
{
"step": "收集输入",
"description": "收集用户偏好和热门数据",
"actions": [
"请求用户输入(例如,主题、关键词、语气)",
"从API获取话题和标签"
]
},
{
"step": "生成推文",
"description": "根据输入和趋势创建推文",
"actions": [
"使用AI模型生成不超过280个字符的健康贴士",
"结合用户偏好和热门数据以提高相关性"
]
},
{
"step": "优化参与度",
"description": "增强内容以提高参与度",
"actions": [
"添加相关标签和提及",
"调整语气和内容以实现最大参与度"
]
},
{
"step": "验证内容",
"description": "确保推文符合指导原则",
"actions": [
"检查字符数和格式",
"确保内容符合平台的规则和社区原则"
]
},
{
"step": "发布内容",
"description": "代表用户发布推文",
"actions": [
"使用API发布",
"确认内容已成功发布"
]
},
{
"step": "反馈循环",
"description": "收集反馈并改进",
"actions": [
"监控推文参与度(点赞、转发、评论)",
"根据性能数据和用户反馈调整AI模型"
]
}
]
}
}
后面,雄哥还有更深入内容,以构建它!
1.3 行动-函数调用
Agent执行任务,可以是一组数据库查询/写入,或者某组函数的执行,然后获取结果,反馈给Agent更新下一步的策略,相当于一个人的手手脚脚;
天黑,脚踩水了,肯定就不要再往前了;
这里我们,通常涉及使用各种工具或 API,后面雄哥会专门开一个系列,如何做函数调用,如何评估性能,如何提升tools触达率等;
最简单的实例,是这样的:
## API发布推文
{
"endpoint": "/api/post",
"method": "POST",
"description": "将生成的推文发布到小红书。",
"request": {
"body": {
"id": "字符串",
"user_id": "字符串",
"token": "字符串"
}
},
"response": {
"status": 200,
"body": {
"message": "推文发布成功。",
"post_id": "字符串"
}
}
}
## API获取数据
{
"endpoint": "/api/trending",
"method": "GET",
"description": "从小红书获取热门话题和标签。",
"request": {
"query_parameters": {
"location": "字符串",
"limit": "数字"
}
},
"response": {
"status": 200,
"body": {
"trending_topics": [
{
"hashtag": "#示例",
"volume": 10000
}
]
}
}
}
这段代码定义了两个API接口:
# 第一个接口
是用来发布推文的,客户端通过POST请求发送推文的ID、用户ID和OAuth令牌,成功后会返回发布成功的消息和推文ID。
# 第二个接口
用于获取热门话题和标签,客户端通过GET请求传递位置和限制数量,成功后返回热门话题列表及其相关的推文量。
系统执行层
当收到了雄哥的交互的时候,他会自动运行,并且执行操作,大概过程是这样的,雄哥发送:
“我想从小红书上获取一些关于人工智能的热门话题,并且发布这条推文到小红书,标题:一意AI今天上市敲钟了!”
系统收到信息后,背后的操作是这样的:
{
"endpoint": "/api/trending",
"method": "GET",
"parameters": {
"location": "全球", // 或者特定位置,如"中国",以缩小范围
"limit": 10 // 要检索的热门话题数量
},
"response": {
"status": 200,
"body": {
"trending_topics": [
{
"hashtag": "#人工智能示例1",
"volume": 25000
},
{
"hashtag": "#人工智能示例2",
"volume": 18000
}
// 更多热门话题...
]
}
}
}
{
"endpoint": "/api/post",
"method": "POST",
"body": {
"text": "一意今天上市敲钟了!",
"user_id": "你的用户ID", // 用户或应用的唯一ID
"token": "你的用户token" // 用于API认证的令牌
},
"response": {
"status": 200,
"body": {
"message": "推文发布成功。",
"post_id": "123456789"
}
}
}
tools使用上,可以定义任何的操作,包括现实环境(拥抱/机器人动作/环境操作)的交互,在一意慢病管理项目中,是非常重要模块,后面雄哥会展开这个系列;
1.4 评估与监督
这是一个由上至下的行动指南,多agent的编排,在名义的结构上,还需要对不同层次Agent做规范,定义了其行为、个性和特定功能。
包括:
#A 角色或专业化(如:健康管理师、数据分析师等)
#B 语气和沟通风格
#C道德准则和约束
#D 特定知识领域或专业领域的技能
一句话说完了,但是做好这个版块,一点都不容易,首先我们需要做一个高效的管理架构,然后对这个架构的Agent,做不同程度的管理。
雄哥前几天看到一个国外项目,这是一个Agent世界文明的构建指南,颇为震撼,60小时,完成一个超大型的多智能体的复杂文明构建,这是非常非常困难的事,中华文明形成用了上千年,人工智能时代,仅60小时;
1.5 记忆
记忆是Agent存储和调用过去交互的信息,主要作用:
#A 在正在进行的任务中保持上下文(不是无限记忆,只记重要的)
#B 从以前的经验中学习
#C 随着时间的推移总结提升能力
#D 根据用户历史记录提供个性化响应
#E 多个Agent间根据架构分配信息
记忆可以是短期的(在单个对话的持续时间内)或长期的(在多个交互中持续存在),这里最难做的是:记忆的规则。
在单个任务或Agent中,是比较容易实现的,但MAS中,是多Agent的协调,这时,下游的Agent需要上游的任务入口,提供有效的信息;
注意,是有效的信息!
代表了部分,不是所有的信息都能共享的,需要一套完备的信息管理系统。
就像一个公司,销售部,是不需要知道公司内部的财务盈亏信息的;
一个完整的MAS系统,需要大量的工作,许多技术当下的实现还是0,这才是AI时代,真正的机会,都需要你,一步步实现,所有人,都有机会;
接下来,跟着雄哥,在已有的技术基础上,在本地搭建一个MAS吧!
这不是最终版,这是跑通,学习用途,生产的话,需要做的路更长!
而且,这是一个产品的核心和优势差异;
第二部分:跑起来!边跑边聊代码!
本次,跟着雄哥完成Agent的关键组件,涵盖:
1. 反思
2.工具使用
3.规划(任务分配)
4.多代理协作
任务是:生成平均气温图表,通过多个agnet调用函数收集数据、生成表格,然后返回到LLM,返回结果给用户,如下图:
最终实现,Agent分析任务,然后把任务拆解,分别给不同的Agent去完成任务,我们的最终输出是让Agent生成代码,做表格+总结输出:
背后干了几件事:
任务:获取过去1年中国广东的GDP并绘制一张图表
动作一:收集过去1年广东的GDP数据(Agent 1)
动作二:总结收到的数据(Agent 2)
动作三:根据数据生成创建图表的代码(Agent 3)
动作四:根据图表和数据做最终回复(Agent 4)
雄哥会把这些组件拆开,组成一个MAS(简易版),实践的环境,如下:
操作系统:无要求,雄哥win11
代码环境:minidonda、jupyter
大模型:openai api(当然可以本地啦)
Agent框架:LangChain、 CrewAI
需要你在本地搭建好AI环境,还未搭建,在这里快速搭建!
第四天!0基础微调大模型+知识库,部署在微信!手把手安装AI必备环境!4/45
所有的实践代码,都已经上传到会员盘(百度),如果你还不是会员,在末尾联系工程师,即可申请加入,加入后就能看到代码,也可以直接找到雄哥;
创建conda环境!
指定mas名称,3.10的Python版本,注意,每一个实践,你都应该是独立的环境,否则容易有依赖版本冲突;
习惯用其他的环境管理工具?怎么顺手怎么来!
新手跟着雄哥走即可!打开conda窗口,输入:
conda create --name mas python=3.10
激活进入mas环境!
conda activate mas
cd进入代码目录
这里要进入你放代码的目录,雄哥放在F:\mas,方便后面打开;
cd F:\mas
安装jupyter
这是一个交互式的工具,可以看到每一行代码的执行结果!
conda install jupyter
进入jupyter环境!
输入以下指令,他会自动跳转到浏览器
jupyter notebook
双击打开代码!
现在开始,正式进入代码环节,这里,雄哥会拿一些核心的代码出来,演示他背后的重要节点,是怎样做的。
添加共享记忆!
agent_executor = create_react_agent(model, tools, checkpointer=memory)
config = {"configurable": {"thread_id": "123"}}
for chunk in agent_executor.stream(
{"messages": [HumanMessage(content="我是一意AI,一个长期专注AI工程师培养、AI技术支撑、降本增效,始终陪伴伙伴持续成长的学习平台")]}, config
):
print(chunk)
print("----")
测试是否成功,问:我是谁?
回答:
你好,很高兴认识你,一意AI。我会尽我所能为你提供帮助。你有什么问题或者需要我做什么吗?
创建Agent的函数和提示词!
def create_agent(llm, tools, system_message: str):
"""Create an agent."""
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
" 你是一个有帮助的AI助手,与其他助手协作."
" 使用提供的工具来推动回答问题."
" 如果你无法完全回答,也没关系,其他具有不同工具的助手会接着你未完成的部分进行帮助."
" 尽你所能地执行,以取得进展."
" 如果你或其他助手有最终答案或交付成果,请在你的回应前加上[最终答案]."
" 这样团队就知道可以停止了."
" 你可以使用以下工具: {tool_names}.\n{system_message}",
),
MessagesPlaceholder(variable_name="messages"),
]
)
prompt = prompt.partial(system_message=system_message)
prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
return prompt | llm.bind_tools(tools)
定义了create_agent 的函数,用于创建一个AI助手
该函数接受三个参数:llm、tools、system_message
函数的主要作用是:使用 ChatPromptTemplate.from_messages 创建一个提示模板,这个模板包含了系统信息和消息占位符。
系统信息部分定义了AI助手的行为准则,包括与其他助手协作、使用提供的工具来回答问题,并在找到最终答案时在回应前加上特定的标记。
将系统消息和工具名称动态地插入到提示模板中。
创建tool!
注意啊,这个tool是可以直接生成代码+执行代码,可能会搞坏你本地环境,注意使用!不要搞花哨操作!
def python_repl(
code: Annotated[str, "生成图表的Python代码."],
):
"""如果你想要查看一个值的输出,使用这个来执行Python代码
你应该使用 print(...) 将其打印出来。这是用户可见的."""
try:
result = repl.run(code)
except BaseException as e:
return f"Failed to execute. Error: {repr(e)}"
result_str = f"Successfully executed:\n```python\n{code}\n```\nStdout: {result}"
return (
result_str + "\n\nIf 你已经完成了所有任务,合成最终答案.")
这里是告诉Agent,可以直接生成Python代码,并且执行,生成图表;
创建Agent状态的数据结构!
class AgentState(TypedDict):
messages: Annotated[Sequence[BaseMessage], operator.add]
sender: str
定义 AgentState 的类型字典类,继承自 TypedDict。
TypedDict 是一个在Python中用于类型注解的特殊类型,用户可定义字典的键及其对应的类型。
在 AgentState 类中,定义了两个键:
messages:这是一个键,其值被注解为 Sequence[BaseMessage],并且使用了 operator.add 作为额外的注解。这表示 messages 键的值应该是一个 BaseMessage 对象的序列(比如列表或元组),并且暗示了可能会对这个序列使用加法操作(例如,将两个消息序列合并)。
sender:这是一个键,其值被注解为 str,表示 sender 键的值应该是一个字符串,用于表示消息的发送者。
定义Agent!
# 数据采集agent
research_agent = create_agent(
llm,
[tavily_tool],
system_message="你应该为 chart_generator 提供准确的数据以供使用.",
)
research_node = functools.partial(agent_node, agent=research_agent, name="Researcher")
# 图表生成agent
chart_agent = create_agent(
llm,
[python_repl],
system_message="你展示的任何图表都将被用户看到.",
)
chart_node = functools.partial(agent_node, agent=chart_agent, name="chart_generator")
定义边和创建逻辑!
# 任何一个代理都可以决定结束
from typing import Literal
def router(state) -> Literal["call_tool", "__end__", "continue"]:
# 路由
messages = state["messages"]
last_message = messages[-1]
if last_message.tool_calls:
# 前一个代理正在调用一个工具
return "call_tool"
if "FINAL ANSWER" in last_message.content:
# 任何代理都决定工作已经完成
return "__end__"
return "continue"
任务是否完成,现在执行的状态如何,非常重要!
如果上一个代理正在调用一个工具(绑定到代理的 llm),那么它会将状态更新为"call_tool"
如果上一个代理没有"call_tool",建议它更新状态:已完成其工作并且最终答案已准备就绪,则会将状态更新为 END
否则,它将更新 state 以继续
好啦!
现在开始输入一个任务!
events = graph.stream(
{
"messages": [
HumanMessage(
content="获取过去1年中国广东的GDP并绘制一张示意图"
)
],
},
# M在图中要采取的最大步骤数
{"recursion_limit": 150},
)
for s in events:
print(s)
print("----")
你就可以看到下图的输出过程了
接下来就会专门做Agent内容,发展飞快,一些价值的进展都想分享给你!
如果你想加群,或者付费成为会员,都可以在这里联系到雄哥的工程师-小胖!