AI Agent技术,让你的AI助手学会思考,使用工具
原创 Bob新视界 Bob的AI视界
大家好,我是Bob。
一个想和大家一起慢慢变富的AI程序员。
热爱分享AI前瞻思考、项目经验、面试技巧。
欢迎关注我,一起探索,一起破圈!
AI Agent技术,让大模型学会思考、调用工具。
为什么需要 Agent
在 ChatGPT 横空出世,夺走 Bert 的桂冠之后,大模型愈发 得 火热,国内各种模型层出不穷,史称“百模大战”。 大模型的能力是毋庸置疑的,但大模型在一些
实时的问题上,或是某些专有领域的问题上,可能会显得有些力不从心。 因此,我们需要一些工具来为大模型赋能,给大模型一个抓手,让大模型和现实世界发生的事情对齐颗粒度,这样我们就获得了一个更好的用的大模型。
什么是 Agent
AI Agent(人工智能代理)是image一种能够感知环境、进行决策和执行动作的智能实体,具备通过
独立思考、记忆能力、调用工具去逐步完成给定目标的能力,也可以称为“智能体”或“智能业务助理”。在大模型技术驱动下,让人们以自然语言为交互方式高自动化地执行和处理专业或繁复的工作任务,从而极大程度释放人员精力。
论文思路图
Agent 代码分享
本次的 Agent 技术分享,主要集中于模型
调用工具的能力 ,代码比较简单,仅用于学习,切勿部署于生产环境。
项目仓库:Github Project [1]
参考论文:ReAct: Synergizing Reasoning and Acting in Language Models [2]
Tool 工具集类(Tool.py)
import json
import requests
import os
class Tools:
def __init__(self) -> None:
self.tools_config=[
{
'chinese_name':'谷歌搜索',
'english_name':'google_search',
'description':'谷歌搜索是一个通用搜索引擎,可用于访问互联网、查询百科知识、了解时事新闻等。',
'parameters':[
{
'name': 'search_query',
'description': '搜索关键词或短语',
'required': True,
'schema': {'type': 'string'},
}
]
},
]
self.api=os.getenv('google_search_api')
def get_func(self):
return self.tools_config
def google_search(self,search_query:str):
url = "https://google.serper.dev/search"
payload = json.dumps({
"q":search_query
})
headers = {
'X-API-KEY': self.api,
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload).json()
return response['organic'][0]['snippet']
工具类包含两个部分,一个部分是
工具的配置描述,另一个部分是工具对应的方法.这里之构建了一个Google搜索工具,需要 Google search API [3] ,其他的工具大家可以按照模板来写。
ps:注意english_name必须和对应的方法名相同
LLM 大模型类(llm.py)
from typing import Dict, List, Optional, Tuple, Union
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
from langchain_openai import OpenAI,ChatOpenAI
from langchain_core.messages.ai import AIMessage
from langchain_core.messages.human import HumanMessage
class BaseModel:
def __init__(self,path:str='') -> None:
if path!='':
self.tokenizer=AutoTokenizer.from_pretrained(path)
self.model=AutoModelForCausalLM.from_pretrained(path)
elif path=='':
self.model= ChatOpenAI(model="gpt-3.5-turbo", temperature=0.1)
def chat(self,query:str, prompt_template: str='', history:List=[]):
pass
def load_model(self):
pass
class OpenAIModel(BaseModel):
def __init__(self, path: str = '') -> None:
super().__init__(path)
def chat(self,query:str, prompt_template: str='', history:List=[]):
message=[]
message.append(HumanMessage(content=prompt_template))
message.append(HumanMessage(content=query))
# message=prompt_template+f'\nQuestion: {query}'
# message=HumanMessage(content=message)
res=self.model.invoke(message)
return res.content
大模型类构建,默认使用OpenAI的API( 需要
api-key喔),可自行修改成本地大模型, 包含一个BaseModel的父类,存在init初始化方法和chat对话方法,OpenAIModel子类继承BaseModel类
Agent 类(Agent.py)
from typing import Dict, List, Optional, Tuple, Union
import json5
from components.LLM import OpenAIModel
from components.Tools import Tools
# from LLM import OpenAIModel
# from Tools import Tools
TOOL_DESC = """{english_name}: Call this tool to interact with the {chinese_name} API. What is the {chinese_name} API useful for? {description} Parameters: {parameters} Format the arguments as a JSON object."""
REACT_PROMPT = """Answer the following questions as best you can. You have access to the following tools:
{tools_description}
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, should be one of [{tools_name}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated zero or more times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
"""
class Agent:
def __init__(self,path:str='') -> None:
self.path=path
self.tools=Tools()
self.tools_config=self.tools.get_func()
self.llm=OpenAIModel()
self.template_prompt=self.build_template_prompt()
def build_template_prompt(self):
tools_description,tools_name=[],[]
for tool in self.tools_config:
tools_description.append(TOOL_DESC.format(**tool))
tools_name.append(tool['english_name'])
tools_description = '\n\n'.join(tools_description)
tools_name = ','.join(tools_name)
template_prompt=REACT_PROMPT.format(tools_description=tools_description,tools_name=tools_name)
return template_prompt
def select_func_call(self,text:str):
func_name=''
func_args=''
i = text.rfind('\nAction:')
j = text.rfind('\nAction Input:')
k = text.rfind('\nObservation:')
if j>i>=0:
if k<0:
text.strip()+'\nObservation:'
k = text.rfind('\nObservation:')
func_name=text[i+len('\nAction:'):j].strip()
func_args=text[j+len('\nAction Input:'):k].strip()
text=text[:k].strip()
return func_name,func_args,text
def call_plugin(self, func_name, func_args):
func_args = json5.loads(func_args)
if func_name=="google_search":
return '\nObservation:' + self.tools.google_search(**func_args)
def chat_by_func(self,query,history=[]):
res_model_1=self.llm.chat(query,self.template_prompt)
func_name,func_args,text=self.select_func_call(res_model_1)
if func_name:
res_func=self.call_plugin(func_name, func_args)
res_model_2=text+res_func
result=self.llm.chat(res_model_2,self.template_prompt)
show='第一次模型交互:\n'+text+'\n\n'+f'执行{func_name}的结果:\n'+res_func+'\n\n'+'第二次交互:\n'+res_model_2+'\n\n'+'最终结果:\n'+result
return show
Agent类包含
init方法,build_prompt构建提示词,select_func_call选择需要调用的方法,call_plugin调用方法,chat_by_func整合所有步骤的函数。解释一下流程:
第一次与AI交互:提出问题,利用提示词,引导模型做出思考,需要什么
流程,什么方法来完成目标。
2.与方法交互:解析回答的字符串,得到需要调用的
方法名与参数,调用方法,得到信息。3.第二次与AI交互:结合
问题与调用方法的信息,再次给到AI模型,让AI参考信息,做出最终回答
提示词如下:
Answer the following questions as best you can. You have access to the following tools:
{tools_description}
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, should be one of [{tools_name}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated zero or more times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Web_demo演示 (demo.py)
import gradio as gr
import time
from components.Agent import Agent
agent=Agent()
def echo(message, history):
# result=agent.llm.chat(message,agent.template_prompt)
result=agent.chat_by_func(message)
for i in range(len(result)):
time.sleep(0.02)
yield result[: i+1]
#自定义的流式输出
demo = gr.ChatInterface(fn=echo,
examples=["特朗普什么时候出生?","github是什么?"],
title="Echo Bot",
theme="soft")
demo.launch()
demo基于Gradio构建,可自行调试
结果如下
引用链接
[1] 项目仓库:Github Project: github.com/phbst/TinyA…
[2] 参考论文:ReAct: Synergizing Reasoning and Acting in Language Models:
arxiv.org/abs/2210.03…
[3] Google search API: serper.dev/api-key