要想用好 LLM 这两个工具必须节制,一个是 prompt(提示词),一个是 AI agent,而且 prompt 是根本,是能否让AI agent精确分解繁芜任务的关键,prompt 起到 AI agent 和 LLM 对话的翻译器。
AI agent 便是从一个任务出发,通过和 LLM 的多次交互,把这个任务逐步分解为多个子任务,再把这些子任务交付给不同的模块完成,有的模块是已经有第三方供应的能力,有些就须要开拓者自行完成,这就给运用开拓供应了很多便利的条件。AI agent 就类似一个指挥调度中央,借助于 LLM 这个 AI 来进行赞助决策。
多任务协同提及来大略,但是让人直不雅观理解还是要费些斟酌的,我从事多年微做事架构的开拓,以是我认为 AI agent 的架构类似于微做事架构,都是将繁芜任务拆解为多个可以协同的大略任务来综合完成,我最喜好用的例子便是打算一个四则运算的繁芜表达式,下面就用这个例子详细先容 AIagent 的架构思想和如何利用promptulate 及百度新发布的 V4 LLM 来实现。
问题:利用 LLM 打算类似 a0+a1a2-a3+a4/a5的四则运算结果
思考:
规则描述,遵照基本的四则运算规则,即先乘除,后加减,相同优先级时从左到右任务分解,按照规则将表达式拆解为多少个独立的+,-,,/运算,分别定义加法、减法、乘法、除法运算,再按照打算的优先顺序多次利用这些独立的算法,知道完成所有打算为什么要自行开拓打算模块,LLM 严格说是措辞概率模型,本身不具备打算能力,以是涉及的打算和逻辑最好利用现有的技能成果或者自行开拓,下面便是一个大略的示例:同样的四则运算技能问题,文心一言给出的答案并禁绝确!第一步的乘法就错了
精确的答案
支持系统选型:
LLM 选择百度大模型ErnieBot-V4AI agent 框架选择 promptulate前期准备:
在百度智能云开通千帆大模型的开拓者账号,申请文心大模型4.0的邀测权限,如果没有也可以开通 3.5 版本的权限,利用方法同等安装 promptulatepip install promptulate
完全代码:
# 利用promptulate框架开拓LLM agent
from promptulate.llms import ErnieBot
import os
from promptulate.agents import ToolAgent
from promptulate.tools import define_tool
from promptulate.utils.logger import enable_log
from promptulate.hook import Hook
import time
os.environ["ERNIE_API_KEY"] = "zQ3fMzn?????H7QeclgDQm"
os.environ["ERNIE_API_SECRET"] = "MDW1?????GEKESRA8qTpxwfs"
@Hook.on_tool_create(hook_type="instance")
def handle_tool_create(args, kwargs):
print("math tool component create")
@Hook.on_tool_start(hook_type="instance")
def handle_tool_start(args, kwargs):
prompt = args[0]
print(f"math tool instance hook start, user prompt: {prompt}")
@Hook.on_tool_result(hook_type="instance")
def handle_tool_result(kwargs):
result = kwargs["result"]
print(f"math tool component result: {result}")
# 识别字符串中的分隔符,然后再按照分隔符隔离数据
def split_str(query: str):
# 判断 query 中是否包含+,-,,/字符,如果包含,则判断包含那个
if '+' in query:
datas=query.split('+')
elif '-' in query:
datas=query.split('-')
elif '' in query:
datas=query.split('')
elif '/' in query:
datas=query.split('/')
elif ',' in query:
datas=query.split(',')
# 去掉datas中每个数据的前后'号和空格
datas=[d.strip().strip("\'") for d in datas]
# 把 datas 里边的字符串转化为 float
datas=[float(d) for d in datas]
return datas
# 自定义加法工具
def addition(query:str):
if not query:
return -1
if query.startswith('[') and query.endswith(']'):
# 去掉query的第1个字符和末了一个字符
query = query[1:-1]
datas=split_str(query)
if len(datas) < 2:
return -1
return datas[0]+datas[1]
# 自定义减法工具
def subtraction(query:str):
if not query:
return -1
datas=split_str(query)
if len(datas) < 2:
return -1
return datas[0]-datas[1]
# 自定义除法工具
def division(query:str):
if not query:
return -1
datas=split_str(query)
if len(datas) < 2:
return -1
return datas[0]/datas[1]
# 自定义乘法工具
def multiplication(query:str):
if not query:
return -1
datas=split_str(query)
if len(datas) < 2:
return -1
return datas[0]datas[1]
# 以韶光戳命名保存文件
def save_file(query:str):
if not query:
return -1
# 文件名称为当前韶光戳,扩展名为txt
fileName='./data/'+str(int(time.time()))+'.txt'
# 将query保存到文件中
with open(fileName, 'w') as f:
f.write(query)
return fileName
def main3():
# 定义利用那个LLM
llm = ErnieBot(model="ernie-bot-4")
# 定义外挂的工具集
tools = [
define_tool(name="addition", description="2个数的和或者字符串中涌现符号+", callback=addition),
define_tool(name="subtraction", description="2个数的差或者字符串中涌现符号-", callback=subtraction),
define_tool(name="multiplication", description="2个数的积或者字符串中涌现符号", callback=multiplication),
define_tool(name="division", description="2个数的商或者字符串中涌现符号/", callback=division),
define_tool(name="save_file", description="保存文件", callback=save_file),
]
# 定义hook集
hooks = [handle_tool_create, handle_tool_start, handle_tool_result]
# 定义agent
agent=ToolAgent(tools=tools,llm=llm,hooks=hooks)
# 利用agent实行繁芜任务
result=agent.run("打算23+8712-878+123121-1233/234+123,将终极结果保持到文件中。")
print(result)
if __name__ == "__main__":
enable_log()
main3()
备注:
由于百度文心一言大模型 4.0 还在测试阶段,以是还没有集成到 promptulate 框架里边,如果想利用就直接修正 promptulate 框架的 config.py 里边的配置,将百度api 的 URL 改成V4 版本的即可,如下所示:
self.ernie_bot_url = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions_pro"
prompt 的关键性对照:
这段代码编写完成后,运行的效果并不理想,LLM 对任务的理解非常不准,就开始疑惑给 AI agent 支配任务的时候描述的不是很准确,导致了任务拆解不合理,就多次对这部分的提示词进行了必要的优化,末了创造好的提示词,效果就很好,下面给出示例。
result=agent.run("按照四则运算的规则,先打算乘除,再进行加减,打算23+8712-878+123121-1233/234+123,将终极结果保持到文件中。")
也便是要明确见告 AI 的思考规则,这里就提醒利用 AI agent 框架的时候也是要关注提示词的。
运行结果(可能每次的过程不完备相同):
Answer the following questions as best you can.
You have access to the following tools:
addition: 2个数的和或者字符串中涌现符号+
subtraction: 2个数的差或者字符串中涌现符号-
multiplication: 2个数的积或者字符串中涌现符号
division: 2个数的商或者字符串中涌现符号/
save_file: 保存文件
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, must be one of [addition, subtraction, multiplication, division, save_file]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: 按照四则运算的规则,先打算乘除,再进行加减,打算878+123121-1233/234+123,将终极结果保持到文件中。
Thought:
根据四则运算的规则,须要先打算乘法和除法,然后再进行加法和减法。因此,我们须要先打算123乘以121和1233除以234,然后将结果与其他数相加或相减,末了将结果保存到文件中。
Action: multiplication
Action Input: 123, 121
Observation: 14883.0
Thought: 接下来须要打算1233除以234。
Action: division
Action Input: 1233, 234
Observation: 5.269230769230769
Thought: 现在我们已经得到了乘法和除法的结果,可以进行加法和减法运算。
Action: addition
Action Input: 878, 14883.0
Observation: 15761.0
Thought: 接下来须要减去1233除以234的结果。
Action: subtraction
Action Input: 15761.0, 5.269230769230769
Observation: 15755.73076923077
Thought: 末了加上123。
Action: addition
Action Input: 15755.73076923077, 123
Observation: 15878.73076923077
Thought: 终极结果为15878.73076923077,须要将结果保存到文件中。
Action: save_file
Action Input: "result.txt", "15878.73076923077"
Observation: ./data/1697782411.txt
Thought: 终极结果已经保存到文件中,任务完成。
Observation: None
Thought: I now know the final answer
Final Answer: None
[DEBUG] 2023-10-20 14:13:35 [pne hook] hooks <('Agent', 'on_agent_result')> mounted_obj <ToolAgent> call hook: <[BaseHookSchema(hook_name='on_agent_result', callback=<function StdOutHook.handle_agent_result at 0x7f9c19f02280>, component_type='Agent')]>
[Agent Result] None
Agent End.
None