实现一个agent
agent的理论基础和代码查看,代码还没跑,之后在尝试一下。
1 构造大模型
使用InternLM2作为agent的基座模型。
使用transformer库来加载模型
首先,先创建一个basemodel类,定义基本的方法,比如加载模型, 对话。这是一个基类,之后加载任何的模型,都可以用其作为扩展。
class BaseModel:
def __init__(self, path:str = '') ->None:
self.path = path
def load_model(self):
pass
def chat(self, prompt:str, history:List[dict]):
pass
接着创建一个IternLM2类。继承上面的basemodel类,实现方法。
class InternLM2(BaseModel):
def __init__(self, path:str='')->None:
super().__init__(path)
self.load_model()
def load_model(self):
self.tokenizer = AutoTokenizer.from_pretrained(self.path, trust_remote_code=True)
self.model = AutoModelForCausalLM.from_pretrained(self.path, torch_dtype=torch.float16, trust_remote_code=True).cuda().eval()
def chat(self, prompt:str, history:List[dict], meta_instruction:str='')->str:
response, history = self.model.chat(self.tokenizer, prompt, history, temperature=0.1, meta_instruction=meta_instruction)
return response, history
2 构造工具
赋予agent功能。
比如说将agent作为Google搜索的工具,这一步构造一个tool类,添加工具的描述信息和具体实现方式。
第一步需要先申请一个Google的token来调用其API。token申请
class Tools:
def __init__(self)->None:
self.toolConfig = self._tools()
def _tools(self):
tools=[
{
'name_for_human':'谷歌搜索',
'name_for_model':'google_search',
'description_for_model': '谷歌搜索是一个通用搜索引擎,可用于访问互联网、查询百科知识、了解时事新闻等。',
'parameters':[{
'name':'search_query',
'description':'搜索关键词',
'required':True,
'schema':{'tyep':'string'},
}],
}]
return tools
def google_search(self, search_query:str):
pass
3 构造agent
3.1 agent
采用React(Reasoning + Act)范式的Agent,在其中实现了Text_completion对话方法,在其中调用模型,然后根据React的Agent逻辑调用tool工具。
那么agent需要的功能有:
- 调用模型生成输出
- 解析模型输出的文本,生成调用工具的
- 调用工具的功能
- 整合输出,返回响应
3.2 agent代码实现
先写出类和构造函数
class Agent:
def __init__(self, path: str = '') -> None:
self.path = path
self.tool = Tools() # 工具
self.system_prompt = self.build_system_input() # 系统提示
self.model = InternLM2Chat(path) # 调用的模型
首先需要构造system_prompt
def build_system_input(self):
tool_descs, tool_name =[], []
for tool in self.tool.toolConfig:
tool_desc.append(TOOL_DESC.format(**tool))
tool_names.append(tool['name_for_model'])
tool_descs = '\n\n'.join(tool_descs)
tool_names = ','.join(tool_names)
sys_prompt = REACT_PROMPT.format(tool_descs=tool_descs, tool_names=tool_names)
return sys_prompt
调用后,会得到输出,下一步就需要解析模型输出:
def parse_latest_plugin_call(self, text):
# 解析第一次大模型返回选择的工具和工具参数
plugin_name, plugin_args = '', ''
i = text.rfind('\nAction:')
j = text.rfind('\nAction Input:')
k = text.rfind('\nObservation:')
if 0 <= i < j: # If the text has `Action` and `Action input`,
if k < j: # but does not contain `Observation`,
text = text.rstrip() + '\nObservation:' # Add it back.
k = text.rfind('\nObservation:')
plugin_name = text[i + len('\nAction:') : j].strip()
plugin_args = text[j + len('\nAction Input:') : k].strip()
text = text[:k]
return plugin_name, plugin_args, text
这一步主要是要指定的调用工具、参数、以及剩余的输出。得到工具和参数后,就可以调用封装的tool得到输出
def call_plugin(self, plugin_name, plugin_args):
plugin_args = json5.loads(plugin_args)
if plugin_name == 'google_search':
return '\nObservation:' + self.tool.google_search(**plugin_args)
整合两步的输出,给出响应
def text_completion(self, text, history=[]):
text = "\nQuestion:" + text
response, his = self.model.chat(text, history, self.system_prompt)
print(response)
plugin_name, plugin_args, response = self.parse_latest_plugin_call(response)
if plugin_name:
response += self.call_plugin(plugin_name, plugin_args)
response, his = self.model.chat(response, history, self.system_prompt)
return response, his
4 agent的调用流程
得到agent后,就可以调用。
系统提示要告诉大模型它可以调用哪些工具,以什么样的方式输出,工具的描述信息和工具的参数。那么agent的使用步骤为
- 接受system_prompt,根据提示生成调用工具的参数
- 调用工具函数
- 整合工具的输出,得到输出。
from Agent import Agent
agent = Agent('/root/share/model_repos/internlm2-chat-20b')
response, _ = agent.text_completion(text='你好', history=[])
print(response)
# Thought: 你好,请问有什么我可以帮助你的吗?
# Action: google_search
# Action Input: {'search_query': '你好'}
# Observation:Many translated example sentences containing "你好" – English-Chinese dictionary and search engine for English translations.
# Final Answer: 你好,请问有什么我可以帮助你的吗?
response, _ = agent.text_completion(text='周杰伦是哪一年出生的?', history=_)
print(response)
# Final Answer: 周杰伦的出生年份是1979年。
response, _ = agent.text_completion(text='周杰伦是谁?', history=_)
print(response)
# Thought: 根据我的搜索结果,周杰伦是一位台湾的创作男歌手、钢琴家和词曲作家。他的首张专辑《杰倫》于2000年推出,他的音乐遍及亚太区和西方国家。
# Final Answer: 周杰伦是一位台湾创作男歌手、钢琴家、词曲作家和唱片制作人。他于2000年推出了首张专辑《杰伦》,他的音乐遍布亚太地区和西方国家。他的音乐风格独特,融合了流行、摇滚、嘻哈、电子等多种元素,深受全球粉丝喜爱。他的代表作品包括《稻香》、《青花瓷》、《听妈妈的话》等。
response, _ = agent.text_completion(text='他的第一张专辑是什么?', history=_)
print(response)
# Final Answer: 周杰伦的第一张专辑是《Jay》。