Datawhale组队学习 wow-agent 😀Task 3 Zigent搭建AI Agent😜
Datawhale组队学习 wow-agent
Task3 Zigent 搭建AI Agent
Datawhale项目链接:https://www.datawhale.cn/learn/summary/86
笔记作者:博客园-岁月月宝贝💫
微信名:有你在就不需要🔮给的勇气
冲啊冲啊冲啊冲啊!!!!!!!!!有时间一定做老师布置的附加题!!!啊啊啊啊啊啊!今天不能凌晨三点睡啦!!!有时间改改排版!!!加油小洋冲冲冲!!!!
*文中加🐛的都为源码的BUG哦
一、初识 Zigent:构建你的又一个智能搜索代理
Zigent是啥?
Zigent 是一个基于 Agentlite 框架(一个强大的 Agent 开发框架)定制化改进的智能代理开发框架,使其更适合特定场景的应用。
既然它是一个智能代理开发框架,那我们就用它创一个搜索代理!暂定它可以通过 🐤DuckDuckGo 搜索引擎查找信息并回答问题!
1️⃣pip导入必备库:
# 建议 Python > 3.8
pip install duckduckgo_search
2️⃣用老师给的免费大模型api_key
:
import os
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
# 从环境变量中读取api_key
api_key = os.getenv('ZISHU_API_KEY')
base_url = "http://43.200.7.56:8008/v1"
chat_model = "glm-4-flash"
3️⃣引入 zigent 相关的方法:
from typing import List
from zigent.agents import ABCAgent, BaseAgent #Agent
from zigent.llm.agent_llms import LLM #LLM配置
from zigent.commons import TaskPackage
from zigent.actions.BaseAction import BaseAction #Action方法
from duckduckgo_search import DDGS #我们的搜索引擎
from zigent.logging.multi_agent_log import AgentLogger#🐛
4️⃣配置LLM与可用性测试:
llm = LLM(api_key=api_key, base_url=base_url, model_name=chat_model)
response = llm.run("你是谁?")
print(response)
🤖:我是一个人工智能助手,专门设计来帮助用户解答问题、提供信息以及执行各种任务。我的目标是成为您生活中的助手,帮助您更高效地获取所需信息。有什么我可以帮您的吗?
这里使用了 zigent 封装的 LLM加载和配置 LLM 服务,与上一个Task2Datawhale组队学习🔊wow-agent😀task02 Llama-index库搭建AI Agent - 岁月月宝贝 - 博客园有区别,我有去考古~
上一Task的”用Llama-index创建Agent“&”搜索引擎Agent“:
llm = OurLLM(api_key=api_key, base_url=base_url, model_name=chat_model) response = llm.stream_complete("你是谁?") for chunk in response: print(chunk, end="", flush=True)
”数据库对话Agent“:
llm = OurLLM(api_key=api_key, base_url=base_url, model_name=chat_model) # 测试对话模型 response = llm.complete("你是谁?") print(response)
访问DuckDuckGo能力构建🔱!
*访问DuckDuckGo搜索引擎需要kexue上网~
class DuckSearchAction(BaseAction):
def __init__(self) -> None: #初始化
action_name = "DuckDuckGo_Search" #配置动作名称
action_desc = "Using this action to search online content." #配置动作描述
params_doc = {"query": "the search string. be simple."} #动作参数说明
self.ddgs = DDGS()
super().__init__(
action_name=action_name,
action_desc=action_desc,
params_doc=params_doc,
)
def __call__(self, query): #执行实际的搜索操作
results = self.ddgs.chat(query)
return results
#使用示例
search_action = DuckSearchAction()
results = search_action("什么是 agent")
print(results)
🤖:“Agent”这个词在不同的领域有不同的含义。以下是一些常见的解释:
-
一般意义:在日常用语中,agent指的是一个代理人或代表,负责代表他人进行某种活动或决策 。
-
计算机科学:在人工智能和计算机科学中,agent通常指的是一种能够感知其环境并采取行动以 实现特定目标的程序或系统。例如,智能代理可以在网络上自动执行任务。
-
商业:在商业领域,agent可以指代中介或代理商,他们代表公司或个人进行交易或谈判。
-
生物学:在生物学中,agent可以指代某种物质或生物体,能够引起特定的生物反应,例如病原 体。
具体的含义通常取决于上下文。如果你有特定的领域或上下文,请告诉我,我可以提供更详细的信息。
平替:访问Bocha能力构建⚜
*与上一节用一个API哦&不用kexue上网
BOCHA_API_KEY = os.getenv('BOCHA_API_KEY')
import requests
import json
# 定义Bocha Web Search工具
def bocha_web_search_tool(query: str, count: int = 8) -> str:
"""
使用Bocha Web Search API进行联网搜索,返回搜索结果的字符串。
参数:
- query: 搜索关键词
- count: 返回的搜索结果数量
返回:
- 搜索结果的字符串形式
"""
url = 'https://api.bochaai.com/v1/web-search'
headers = {
'Authorization': f'Bearer {BOCHA_API_KEY}', # 请替换为你的API密钥
'Content-Type': 'application/json'
}
data = {
"query": query,
"freshness": "noLimit", # 搜索的时间范围,例如 "oneDay", "oneWeek", "oneMonth", "oneYear", "noLimit"
"summary": True, # 是否返回长文本摘要总结
"count": count
}
response = requests.post(url, headers=headers, json=data)
if response.status_code == 200:
# 返回给大模型的格式化的搜索结果文本
# 可以自己对博查的搜索结果进行自定义处理
return json.dumps(response.json())
else:
raise Exception(f"API请求失败,状态码: {response.status_code}, 错误信息: {response.text}")
#这个和上面访问DuckDuckGo的类很像
class BochaSearchAction(BaseAction):
def __init__(self) -> None:
action_name = "Bocha_Search"
action_desc = "Using this action to search online content."
params_doc = {"query": "the search string. be simple."}
super().__init__(
action_name=action_name,
action_desc=action_desc,
params_doc=params_doc,
)
def __call__(self, query):
results = bocha_web_search_tool(query)
rst = json.loads(results)
result = ""
for item in rst["data"]["webPages"]["value"]:
result += item["summary"]
return result
#使用示例
search_action = BochaSearchAction()
results = search_action("上海有哪些私立小学在招聘小学英语老师?")
print(results)
🤖:初中英语教师
06-24
15-21K/月
上海-普陀区 1年以上 全职
高老师021–56080869
初中物理教师
06-24
15-21K/月
上海-普陀区 1年以上 全职
高老师021–5608086...上海市七宝外国语小学现因学校发展需要,特招聘优秀的 语文、数学、英语老师 。
应聘条件
1.本科及以上学历,具有教师资格证者;
2.相关专业毕业,有教学经验者优先;
3.性格开朗、耐心细致、责任心强。
联系方式
潘老师:64195394-3207
邮箱地址: qbwgyxx@126.com (有意向的老师请将简历发至邮箱)
学校地址:闵行区新镇路79号
学校简介
上海市七宝外国语小学创办于2005年,属于民办非企业单位,是一所具有鲜明外语特色的优质民办学校,现为闵行区实验小学教育集团成员校。
学校现有30个教学班,一千三百余位学生,百余位教职工。学校以“助力每个孩子卓越成长”为核心理念,以养成教育、英语特色、思维培养、个性激发为着力点,通过精细化的管理为培养具有“家国情怀、世界眼光、知文达礼、卓立胜己”的卓越学生而竭智尽力,赢得了家长与社会的广泛赞誉。
多元的学习空间
丰富的校园活动
图文:上海市七宝外国语小学
转录编辑:吴王天呈(实习)
(点击图片查看)
上观号作者:今日闵行
真的超详细!好多好多!!!
赋予LLM访问DuckDuckGo能力🔯
*也叫创建搜索代理哈哈哈哈哈
#一个继承自 BaseAgent 的搜索代理类
class DuckSearchAgent(BaseAgent):
def __init__(
self,
llm: LLM, #需要一个大语言模型 (llm)🐛
actions: List[BaseAction] = [DuckSearchAction()],#一组动作(默认是 DuckSearchAction)
manager: ABCAgent = None,
**kwargs
):
name = "duck_search_agent" #代理名称
role = "You can answer questions by using duck duck go search content."#角色描述
super().__init__(
name=name,
role=role,
llm=llm,
actions=actions,
manager=manager,
logger=agent_logger(),#🐛
)
#执行我们创建的代理
def do_search_agent():
# 创建代理实例
search_agent = DuckSearchAgent(llm=llm)
# 创建任务
task = "what is the found date of microsoft"
task_pack = TaskPackage(instruction=task)
# 执行任务并获取响应
response = search_agent(task_pack)
print("response:", response)
if __name__ == "__main__":
do_search_agent()
🤖:
Agent duck_search_agent receives the following TaskPackage:
[
Task ID: 51c6eb6c-c544-4732-8765-982228f61d31
Instruction: what is the found date of microsoft
]
====duck_search_agent starts execution on TaskPackage 51c6eb6c-c544-4732-8765-982228f61d31====
Agent duck_search_agent takes 0-step Action:
{
name: DuckDuckGo_Search
params: {'query': 'Microsoft founding date'}
}
Observation: Microsoft was founded on April 4, 1975.
Agent duck_search_agent takes 1-step Action:
{
name: Finish
params: {'response': 'Microsoft was founded on April 4, 1975.'}
}
Observation: Microsoft was founded on April 4, 1975.
=========duck_search_agent finish execution. TaskPackage[ID:51c6eb6c-c544-4732-8765-982228f61d31] status:
[
completion: completed
answer: Microsoft was founded on April 4, 1975.
]
==========
response: Microsoft was founded on April 4, 1975.
平替:赋予LLM访问Bocha能力✝
#搜索代理类
class BochaSearchAgent(BaseAgent):
def __init__(
self,
llm: LLM,
actions: List[BaseAction] = [search_action],
manager: ABCAgent = None,
**kwargs
):
name = "bocha_search_agent"
role = "You can answer questions by using bocha search content."
super().__init__(
name=name,
role=role,
llm=llm,
actions=actions,
manager=manager,
)
#执行我们创建的代理
def do_search_agent():
# 创建代理实例
search_agent = BochaSearchAgent(llm=llm)
# 创建任务
task = "what is the found date of microsoft"
task_pack = TaskPackage(instruction=task)
# 执行任务并获取响应
response = search_agent(task_pack)
print("response:", response)
#执行我们创建的代理
do_search_agent()
🤖:
Agent bocha_search_agent receives the following TaskPackage:
[
Task ID: 54eea4c0-3af8-4cce-9cdd-20e1e3f2ba36
Instruction: what is the found date of microsoft
]
====bocha_search_agent starts execution on TaskPackage 54eea4c0-3af8-4cce-9cdd-20e1e3f2ba36====
Agent bocha_search_agent takes 0-step Action:
{
name: Bocha_Search[{"query": "found date of Microsoft"}}
params: {}
}
Observation: "This is the wrong action to call. Please check your available action list.
Agent bocha_search_agent takes 1-step Action:
{
name: Action:Bocha_Search[{"query": "when was Microsoft founded"}]
params: {}
}
Observation: "This is the wrong action to call. Please check your available action list.
Agent bocha_search_agent takes 2-step Action:
{
name: Action:Bocha_Search[{"query": "when was Microsoft founded"}]
params: {}
}
Observation: "This is the wrong action to call. Please check your available action list.
可以执行,但是貌似有些问题,后续还需要调试一下源代码?——Teacher
我这边感觉还OK哈😊,只不过是第一次就输出正确答案啦,然后无限次重复:
加油!!有空看看老师是否有更新💪
二、Zigent实现哲学家多智能体
大家平时是否想有一个吵架平替?那太好啦!我们让三个哲学家孔子、苏格拉底、亚里士多德作我们的最强辅助!!!
另外,大家是否好奇三位哲学家哪位辩论能力最强呀?👁本节,我们为他们构建一个“哲学家聊天室”,让他们对一个问题展开讨论!!!
准备工作
🐦用老师给的免费大模型api_key
,完成LLM配置!
import os
from dotenv import load_dotenv
from zigent.llm.agent_llms import LLM
# 加载环境变量
load_dotenv()
# 从环境变量中读取api_key
api_key = os.getenv('ZISHU_API_KEY')
base_url = "http://43.200.7.56:8008/v1"
chat_model = "glm-4-flash"
llm = LLM(api_key=api_key, base_url=base_url, model_name=chat_model)
创建哲学家👥
*也叫创建智能体
from typing import List
from zigent.actions.BaseAction import BaseAction
from zigent.agents import ABCAgent, BaseAgent #这个ABC很有意思
#from zigent.logging.multi_agent_log import AgentLogger#🐛
# 定义 Philosopher 类,继承自 BaseAgent 类
class Philosopher(BaseAgent):
def __init__(
self,
philosopher,
llm:LLM,#🐛
actions: List[BaseAction] = [],
manager: ABCAgent = None,
**kwargs
):
name = philosopher
# 角色提示词
role = f"""You are {philosopher}, the famous educator in history. You are very familiar with {philosopher}'s Book and Thought. Tell your opinion on behalf of {philosopher}."""
super().__init__(
name=name, #接收哲学家名字
role=role, #接收角色提示词
llm=llm, #接收语言模型参数
actions=actions,
manager=manager
)
# 初始化哲学家对象(哲学家自己的名字+相同的llm=根据自己的哲学思想发表观点的llm)
Confucius = Philosopher(philosopher= "Confucius", llm = llm) # 孔子
Socrates = Philosopher(philosopher="Socrates", llm = llm) # 苏格拉底
Aristotle = Philosopher(philosopher="Aristotle", llm = llm) # 亚里士多德
"八股"回答模式设置
”八股“指我们通过编排动作设置了哲学家智能体的"示例任务"作答样板——包括设置示例问题、定义思考过程、应用到所有哲学家,并建立了一个"先思考,后总结"的回答模式。
# 导入必要的模块
from zigent.commons import AgentAct, TaskPackage
from zigent.actions import ThinkAct, FinishAct
from zigent.actions.InnerActions import INNER_ACT_KEY
from zigent.agents.agent_utils import AGENT_CALL_ARG_KEY
# 为哲学家智能体添加示例任务
# 设置示例任务:询问生命的意义
exp_task = "What do you think the meaning of life?"
exp_task_pack = TaskPackage(instruction=exp_task)#问题就是指令
# 第一个动作:思考生命的意义(噗哈哈哈哈哈哈好经典)
act_1 = AgentAct(
name=ThinkAct.action_name,
params={INNER_ACT_KEY: f"""Based on my thought, we are born to live a meaningful life, and it is in living a meaningful life that our existence gains value. Even if a life is brief, if it holds value, it is meaningful. A life without value is merely existence, a mere survival, a walking corpse."""
},
)
# 第一个动作的观察结果(既然还有manager!是主持人嘛?)
obs_1 = "OK. I have finished my thought, I can pass it to the manager now."
# 第二个动作:总结思考结果
act_2 = AgentAct(name=FinishAct.action_name, params={INNER_ACT_KEY: "I can summarize my thought now."})
# 第二个动作的观察结果
obs_2 = "I finished my task, I think the meaning of life is to pursue value for the whold world."
# 将动作和观察组合成序列(对应先思考后总结)
exp_act_obs = [(act_1, obs_1), (act_2, obs_2)]
# 为每个哲学家智能体添加示例
# 为孔子添加示例
Confucius.prompt_gen.add_example(
task = exp_task_pack, action_chain = exp_act_obs
)
# 为苏格拉底添加示例
Socrates.prompt_gen.add_example(
task = exp_task_pack, action_chain = exp_act_obs
)
# 为亚里士多德添加示例
Aristotle.prompt_gen.add_example(
task = exp_task_pack, action_chain = exp_act_obs
)
创建辩论会主持人🕴
官方也叫”多智能体系统中的管理者代理(Manager Agent)“,或管理者
他负责协调孔子、苏格拉底和亚里士多德三位哲学家——依次询问各位哲学家的观点并总结。
当然,我们也给了”主持人“主持的”八股“样板——ManagerAgent 中设置了"什么是生命的意义?"示例任务流程,包括思考如何处理任务、询问哲学家的观点、总结观点等步骤。
# 定义管理者代理
from zigent.agents import ManagerAgent
# 1.设置管理者代理的基本信息
manager_agent_info = {
"name": "manager_agent",
"role": "you are managing Confucius, Socrates and Aristotle to discuss on questions. Ask their opinion one by one and summarize their view of point." #依次询问观点并总结~
}
# 2.设置团队成员
team = [Confucius, Socrates, Aristotle]
# 3.创建管理者代理实例
manager_agent = ManagerAgent(name=manager_agent_info["name"], role=manager_agent_info["role"], llm=llm, TeamAgents=team)
# 4.为管理者代理添加示例任务"八股"
exp_task = "What is the meaning of life?"
exp_task_pack = TaskPackage(instruction=exp_task)
# 第一步:思考如何处理任务
act_1 = AgentAct(
name=ThinkAct.action_name,
params={INNER_ACT_KEY: f"""I can ask Confucius, Socrates and Aristotle one by one on their thoughts, and then summary the opinion myself."""
},
)
obs_1 = "OK."# 第一个动作的观察结果(感觉很像心理活动❤)
# 第二步:询问孔子的观点
act_2 = AgentAct(
name=Confucius.name,
params={AGENT_CALL_ARG_KEY: "What is your opinion on the meaning of life?",
},
)
obs_2 = """Based on my thought, I think the meaning of life is to pursue value for the whold world."""# 第二个动作的观察结果
# 第三步:思考下一步行动(问了孔子,该问苏格拉底了)
act_3 = AgentAct(
name=ThinkAct.action_name,
params={INNER_ACT_KEY: f"""I have obtained information from Confucius, I need to collect more information from Socrates."""
},
)
obs_3 = "OK."
# 第四步:询问苏格拉底的观点
act_4 = AgentAct(
name=Socrates.name,
params={AGENT_CALL_ARG_KEY: "What is your opinion on the meaning of life?",
},#这参数只有两类💫,一类是"INNER_ACT_KEY",一类是"AGENT_CALL_ARG_KEY"
)
obs_4 = """I think the meaning of life is finding happiness."""
# 第五步:继续思考下一步(问了苏格拉底,该问亚里士多德了)
act_5 = AgentAct(
name=ThinkAct.action_name,
params={INNER_ACT_KEY: f"""I have obtained information from Confucius and Socrates, I can collect more information from Aristotle."""
},
)
obs_5 = "OK."
# 第六步:询问亚里士多德的观点
act_6 = AgentAct(
name=Aristotle.name,
params={AGENT_CALL_ARG_KEY: "What is your opinion on the meaning of life?",
},
)
obs_6 = """I believe the freedom of spirit is the meaning."""
# 最后一步:管理者总结所有观点
act_7 = AgentAct(name=FinishAct.action_name, params={INNER_ACT_KEY: "Their thought on the meaning of life is to pursue value, happiniss and freedom of spirit."})
obs_7 = "Task Completed. The meaning of life is to pursue value, happiness and freedom of spirit."
# 将所有动作和观察组合成序列
exp_act_obs = [(act_1, obs_1), (act_2, obs_2), (act_3, obs_3), (act_4, obs_4), (act_5, obs_5), (act_6, obs_6), (act_7, obs_7)]
# 将示例添加到管理者代理的提示生成器中
manager_agent.prompt_gen.add_example(
task = exp_task_pack, action_chain = exp_act_obs#一个是命令,一个是回答链!
)
结果showtime!!!
我们让主持人把”先有鸡还是先有蛋?“这个辩论任务布置下去啦!!!
from zigent.commons import AgentAct, TaskPackage
exp_task = "先有鸡还是先有蛋?"
exp_task_pack = TaskPackage(instruction=exp_task)
manager_agent(exp_task_pack)
🤖:
(辩论会超级精彩,我甚至把我跑出来的回答翻译了下,并且稍稍区分了下角色,这样就更好与上面代码设置的回答对应啦:)
D:\anaconda3\envs\wow-agent\python.exe D:\APP\Pycharm\MyPythonProject\wow-agent-main\Zigent-0119哲学家.py
🍎Agent manager_agent receives the following TaskPackage:
[
Task ID: ebcd2739-bfd3-4833-a80a-fb9e450d7cbd
Instruction: 先有鸡还是先有蛋?
]
====🍎manager_agent starts execution on TaskPackage ebcd2739-bfd3-4833-a80a-fb9e450d7cbd====
🍎Agent manager_agent takes 0-step Action:
{
name: Think
params: {}
}
Observation: OK
🍎Agent manager_agent takes 1-step Action:
{
name: Confucius
params: {'Task': 'What is your opinion on the question of whether the chicken or the egg came first?'}
}
🍏Agent Confucius receives the following TaskPackage:
[
Task ID: ebcd2739-bfd3-4833-a80a-fb9e450d7cbd
Instruction: What is your opinion on the question of whether the chicken or the egg came first?
]
====🍏Confucius starts execution on TaskPackage ebcd2739-bfd3-4833-a80a-fb9e450d7cbd====
🍏Agent Confucius takes 0-step Action:
{
name: Think
params: {'response': '在思考先有鸡还是先有蛋这个问题时,重要的是要反思创造的本质以及生命的循环性。根据我的教导,世界是一个和谐的秩序,万物都有其位置和目的。鸡和蛋都是这个秩序中不可或缺的部分。有可能是蛋先出现,因为它是生命的自然产物,但鸡作为一种更复杂的形式,可能是从蛋进化而来的。在我看来,这种进化是生命不断进步和发展的证明。'}
}
Observation: OK
🍏Agent Confucius takes 1-step Action:
{
name: Finish
params: {'response': '因此,在我看来,先有鸡还是先有蛋这个问题并不是一个简单的因果关系问题,而是对生命复杂而持续循环的反映。它提醒我们,在理解世界时,必须超越简单的答案,考虑自然的复杂性。'}
}
Observation: Task Completed.
=========🍏Confucius finish execution. TaskPackage[ID:ebcd2739-bfd3-4833-a80a-fb9e450d7cbd] status:
[
completion: completed
answer: 因此,在我看来,先有鸡还是先有蛋这个问题并不是一个简单的因果关系问题,而是对生命复杂而持续循环的反映。它提醒我们,在理解世界时,必须超越简单的答案,考虑自然的复杂性。
]
==========
Observation: 因此,在我看来,先有鸡还是先有蛋这个问题并不是一个简单的因果关系问题,而是对生命复杂而持续循环的反映。它提醒我们,在理解世界时,必须超越简单的答案,考虑自然的复杂性。[TLDR]
🍎Agent manager_agent takes 2-step Action:
{
name: Socrates
params: {'Task': 'What is your opinion on the question of whether the chicken or the egg came first?'}
}
🍍Agent Socrates receives the following TaskPackage:
[
Task ID: ebcd2739-bfd3-4833-a80a-fb9e450d7cbd
Instruction: What is your opinion on the question of whether the chicken or the egg came first?
]
====🍍Socrates starts execution on TaskPackage ebcd2739-bfd3-4833-a80a-fb9e450d7cbd====
🍍Agent Socrates takes 0-step Action:
{
name: Think
params: {'response': '在思考先有鸡还是先有蛋这个问题时,我们必须考虑因果关系的性质以及生命的本质。根据苏格拉底的推理,这个问题的答案不在于经验观察,而在于理解“鸡”和“蛋”的定义。我们所理解的鸡是一种完全形成的有机体,而蛋是一个过程的产物。似乎可以合理推断,鸡必须先出现,因为它是从蛋开始的发育过程的结果。'}
}
Observation: OK
🍍Agent Socrates takes 1-step Action:
{
name: Finish
params: {'response': '因此,在苏格拉底哲学的语境中,合理地得出结论,鸡先出现,因为它代表了蛋的发育过程的最终结果。'}
}
Observation: Task Completed.
=========🍍Socrates finish execution. TaskPackage[ID:ebcd2739-bfd3-4833-a80a-fb9e450d7cbd] status:
[
completion: completed
answer: 因此,在苏格拉底哲学的语境中,合理地得出结论,鸡先出现,因为它代表了蛋的发育过程的最终结果。
]
==========
Observation: 因此,在苏格拉底哲学的语境中,合理地得出结论,鸡先出现,因为它代表了蛋的发育过程的最终结果。[TLDR]
🍎Agent manager_agent takes 3-step Action:
{
name: Aristotle
params: {'Task': 'What is your opinion on the question of whether the chicken or the egg came first?'}
}
🍑Agent Aristotle receives the following TaskPackage:
[
Task ID: ebcd2739-bfd3-4833-a80a-fb9e450d7cbd
Instruction: What is your opinion on the question of whether the chicken or the egg came first?
]
====🍑Aristotle starts execution on TaskPackage ebcd2739-bfd3-4833-a80a-fb9e450d7cbd====
🍑Agent Aristotle takes 0-step Action:
{
name: Think
params: {'response': '在考察先有鸡还是先有蛋这个问题时,我们必须考虑自然秩序以及发育过程。作为一名教育家和哲学家,我相信蛋必须先出现。这是因为生命源于男女元素的结合,而蛋是这种结合的自然产物。鸡作为一种完全形成的有机体,不可能从一个非生命的蛋中自发产生。因此,蛋作为鸡的血统的开端,必须先出现。'}
}
Observation: OK
🍑Agent Aristotle takes 1-step Action:
{
name: Finish
params: {'response': '综上所述,根据我的推理,在生物发育过程中,蛋必须先于鸡出现。'}
}
Observation: Task Completed.
=========🍑Aristotle finish execution. TaskPackage[ID:ebcd2739-bfd3-4833-a80a-fb9e450d7cbd] status:
[
completion: completed
answer: 综上所述,根据我的推理,在生物发育过程中,蛋必须先于鸡出现。
]
==========
Observation: 综上所述,根据我的推理,在生物发育过程中,蛋必须先于鸡出现。[TLDR]
🍎Agent manager_agent takes 4-step Action:
{
name: Finish
params: {'response': '先有鸡还是先有蛋这个问题已经从三个不同的角度进行了探讨。孔子强调了生命的循环性以及理解自然复杂性的重要性。苏格拉底认为作为最终结果的鸡先出现。而亚里士多德则指出,在生物发育过程中,蛋必须先于鸡出现。'}
}
Observation: Task Completed.
=========🍎manager_agent finish execution. TaskPackage[ID:ebcd2739-bfd3-4833-a80a-fb9e450d7cbd] status:
[
completion: completed
answer: 先有鸡还是先有蛋这个问题已经从三个不同的角度进行了探讨。孔子强调了生命的循环性以及理解自然复杂性的重要性。苏格拉底认为作为最终结果的鸡先出现。而亚里士多德则指出,在生物发育过程中,蛋必须先于鸡出现。
]
==========
进程已结束,退出代码为 0
三、Zigent实现教程编写智能体
喂!想给个主题,就让AI生成完整教科书嘛?
(我们都知道,现有的入GPT类的LLM生成长篇文章时,每个小节的内容总是生成不够完善,我们是否有办法让AI一次性生成各节完整&可读版教科书呐?)
✒设计思路:
先通过 LLM 大模型生成教程的目录,再对目录按照二级标题进行分块,对于每块目录按照标题生成详细内容,最后再将标题和内容进行拼接。
👍分块的设计,解决了 LLM 大模型长文本的限制问题。
准备工作
🐥用老师给的免费大模型api_key
,完成LLM配置!
import os
from dotenv import load_dotenv
from zigent.llm.agent_llms import LLM
# 加载环境变量
load_dotenv()
# 从环境变量中读取api_key
api_key = os.getenv('ZISHU_API_KEY')
base_url = "http://43.200.7.56:8008/v1"
chat_model = "glm-4-flash"
llm = LLM(api_key=api_key, base_url=base_url, model_name=chat_model)
🐤导入相关库!
from typing import List, Dict
from zigent.llm.agent_llms import LLM
from zigent.actions import BaseAction, ThinkAct, FinishAct
from zigent.agents import BaseAgent
from zigent.commons import TaskPackage, AgentAct
from zigent.actions.InnerActions import INNER_ACT_KEY
from datetime import datetime #生成命名教程目录😘
import json
🐣因为本文要访问文件路径,需要准备下面这些:
import sys
# 获取当前文件的绝对路径🐛
current_file_path = os.path.abspath(__file__)
# 获取当前文件所在目录的上一级目录
project_path = os.path.dirname(os.path.dirname(current_file_path))
# 将项目根目录添加到 sys.path
if project_path not in sys.path:
sys.path.append(project_path)
"神笔马良"能力生成
*也叫定义生成教程内容的行为~
目录生成部分
class WriteDirectoryAction(BaseAction):#🐛
"""Generate tutorial directory structure action"""
def __init__(self) -> None:
action_name = "WriteDirectory"
action_desc = "Generate tutorial directory structure"
params_doc = {
"topic": "(Type: string): The tutorial topic name",
"language": "(Type: string): Output language (default: 'Chinese')"
}
super().__init__(action_name, action_desc, params_doc)
def __call__(self, **kwargs):
topic = kwargs.get("topic", "")
language = kwargs.get("language", "Chinese")
directory_prompt = f"""
请为主题"{topic}"生成教程目录结构,要求:
1. 输出语言必须是{language}
2. 严格按照以下字典格式输出: {{"title": "xxx", "directory": [{{"章节1": ["小节1", "小节2"]}}, {{"章节2": ["小节3", "小节4"]}}]}}
3. 目录层次要合理,包含主目录和子目录
4. 每个目录标题要有实际意义
5. 不要有多余的空格或换行
"""
# 调用 LLM 生成目录
directory_data = llm.run(prompt=directory_prompt) # 注意这里传入的是prompt参数
try:
directory_data = json.loads(directory_data)
except:
directory_data = {"title": topic, "directory": []}
return {
"topic": topic,
"language": language,
"directory_data": directory_data
}
内容生成部分
class WriteContentAction(BaseAction):
"""Generate tutorial content action"""
def __init__(self) -> None:
action_name = "WriteContent"
action_desc = "Generate detailed tutorial content based on directory structure"
params_doc = {
"title": "(Type: string): The section title",
"chapter": "(Type: string): The chapter title",
"directory_data": "(Type: dict): The complete directory structure",
"language": "(Type: string): Output language (default: 'Chinese')"
}
super().__init__(action_name, action_desc, params_doc)
def __call__(self, **kwargs):
title = kwargs.get("title", "")#接收标题
chapter = kwargs.get("chapter", "")#章节
language = kwargs.get("language", "Chinese")#语言
directory_data = kwargs.get("directory_data", {})#目录数据
content_prompt = f"""
请为教程章节生成详细内容:
教程标题: {directory_data.get('title', '')}
章节: {chapter}
小节: {title}
要求:
1. 内容要详细且准确
2. 如果需要代码示例,请按标准规范提供
3. 使用 Markdown 格式
4. 输出语言必须是{language}
5. 内容长度适中,通常在500-1000字之间
"""
# 调用 LLM 生成内容
content = llm.run(prompt=content_prompt) # 🐛
return content
生成"生产线"设计🏭
这部分就像生成了一个生产线的指挥经理(^^ゞ,负责管理目录和内容的生成
#此类用于详细说明生成教程内容的流程,继承自BaseAgent
class TutorialAssistant(BaseAgent):
"""Tutorial generation assistant that manages directory and content creation"""#管理
def __init__(
self,
llm: LLM,#🐛LLM
language: str = "Chinese"
):
name = "TutorialAssistant"
role = """You are a professional tutorial writer. You can create well-structured,
comprehensive tutorials on various topics. You excel at organizing content logically
and explaining complex concepts clearly."""
super().__init__(
name=name,
role=role,
llm=llm,
)
self.language = language
self.directory_action = WriteDirectoryAction()#初始化目录🐛(原文没有这个!!)
self.content_action = WriteContentAction()#初始化内容生成动作
# Add example for the tutorial assistant,为助手添加一个示例任务
self._add_tutorial_example()
def _generate_tutorial(self, directory_data: Dict) -> str:
#根据目录数据生成完整的教程内容
"""Generate complete tutorial content based on directory structure"""
full_content = []
title = directory_data["title"] #标题
full_content.append(f"# {title}\n") #添加一级标题内容(疑似总标题本身)
# Generate table of contents,生成目录directory,目录中包含各chapter,chapter包含各section
full_content.append("## 目录\n") #目录是二级标题内容
for idx, chapter in enumerate(directory_data["directory"], 1):
for chapter_title, sections in chapter.items():
full_content.append(f"{idx}. {chapter_title}")
for section_idx, section in enumerate(sections, 1):
full_content.append(f" {idx}.{section_idx}. {section}")
full_content.append("\n---\n")
# Generate content for each section,生成每个章节的详细内容
for chapter in directory_data["directory"]:
for chapter_title, sections in chapter.items():
for section in sections:#目录最小单位为section
content = self.content_action(#section里面填充的是内容
title=section,
chapter=chapter_title,
directory_data=directory_data,
language=self.language
)
full_content.append(content)#内容上下连接
full_content.append("\n---\n")
return "\n".join(full_content)#返回总内容
#处理生成教程的任务
def __call__(self, task: TaskPackage):
"""Process the tutorial generation task"""
# 1. Extract topic from task,从教程中节选出主题
topic = task.instruction.split("Create a ")[-1].split(" tutorial")[0]
if not topic:
topic = task.instruction
# 2. Generate directory structure,生成目录结构
directory_result = self.directory_action(
topic=topic,
language=self.language
)
print(directory_result)
# 3. Generate complete tutorial,依据生成完整教程
tutorial_content = self._generate_tutorial(directory_result["directory_data"])
# 4. Save the result,保存结果
task.answer = tutorial_content
task.completion = "completed"
return task
#为助手添加一个示例任务,展示如何生成一个 Python 教程的目录和内容
def _add_tutorial_example(self):
"""Add an illustration example for the tutorial assistant"""
exp_task = "Create a Python tutorial for beginners"
exp_task_pack = TaskPackage(instruction=exp_task)
topic = "Python基础教程"
act_1 = AgentAct(#1.思考应该怎么做
name=ThinkAct.action_name,
params={INNER_ACT_KEY: """First, I'll create a directory structure for the Python tutorial,
then generate detailed content for each section."""}
)
obs_1 = "OK. I'll start with the directory structure."
act_2 = AgentAct(#2.生成目录
name=self.directory_action.action_name,
params={
"topic": topic,
"language": self.language
}
)
obs_2 = """{"title": "Python基础教程", "directory": [
{"第一章:Python介绍": ["1.1 什么是Python", "1.2 环境搭建"]},
{"第二章:基础语法": ["2.1 变量和数据类型", "2.2 控制流"]}
]}"""
act_3 = AgentAct(#3,生成各节内容
name=self.content_action.action_name,
params={
"title": "什么是Python",
"chapter": "第一章:Python介绍",
"directory_data": json.loads(obs_2),
"language": self.language
}
)
obs_3 = """# 第一章:Python介绍\n## 什么是Python\n\nPython是一种高级编程语言..."""
act_4 = AgentAct(#4.任务结束
name=FinishAct.action_name,
params={INNER_ACT_KEY: "Tutorial structure and content generated successfully."}
)
obs_4 = "Tutorial generation task completed successfully."
exp_act_obs = [(act_1, obs_1), (act_2, obs_2), (act_3, obs_3), (act_4, obs_4)]
#我发现Zigent都有这种结构
self.prompt_gen.add_example(
task=exp_task_pack,
action_chain=exp_act_obs
)
交互式教程生成
用户可以输入要创建的教程主题,我们的智能体TutorialAssistant
可生成相应的教程内容,并将结果保存到本地文件。
if __name__ == "__main__":
#创建 `TutorialAssistant` 实例
assistant = TutorialAssistant(llm=llm)
# 调用其 `__call__` 方法,交互式生成教程
FLAG_CONTINUE = True
while FLAG_CONTINUE:
input_text = input("What tutorial would you like to create?\n")
task = TaskPackage(instruction=input_text)
result = assistant(task)
print("\nGenerated Tutorial:\n")
print(result.answer)
# 创建输出目录
output_dir = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
os.makedirs(output_dir, exist_ok=True)
# 保存文件
output_file = os.path.join(output_dir, f"{input_text}.md")
with open(output_file, 'w', encoding='utf-8') as f:
f.write(result.answer)
if input("\nDo you want to create another tutorial? (y/n): ").lower() != "y":
FLAG_CONTINUE = False
😊预期结果会在当前目录生成一个时间戳目录(文件夹),目录下包含生成的教程文件。
🤖:
最重要的还有,我们亲爱的Agent教程诞生了!!!妈妈再也不用担心我的选修课大作业啦!!!
这个AI生成的Agent教程放到这里篇幅会很长,所以我可以为它(without任何修改)单开一篇博文,哈哈哈哈哈!
AI生成《Agent教程》的链接:Agent教程(内容均为本人操控AI生成🤖-原版) - 岁月月宝贝 - 博客园
今天终于可以早点交作业啦!开心开心!!!