动手做一个最小Agent——TinyAgent!

 Datawhale干货 

作者:宋志学,Datawhale成员

前 言

大家好,我是不要葱姜蒜。在ChatGPT横空出世,夺走Bert的桂冠之后,大模型愈发地火热,国内各种模型层出不穷,史称“百模大战”。大模型的能力是毋庸置疑的,但大模型在一些实时的问题上,或是某些专有领域的问题上,可能会显得有些力不从心。因此,我们需要一些工具来为大模型赋能,给大模型一个抓手,让大模型和现实世界发生的事情对齐颗粒度,这样我们就获得了一个更好用的大模型。

这里基于React的方式,制作了一个最小的Agent结构(其实更多的是调用工具),暑假的时候会尝试将React结构修改为SOP结构。

一步一步手写Agent,可能让我对Agent的构成和运作更加地了解。以下是React论文中一些小例子。

参考论文:https://arxiv.org/abs/2210.03629

90c4892ae8349f6f9c68bb246a21db4a.png

实现细节

Step 1: 构造大模型

我们需要一个大模型,这里我们使用InternLM2作为我们的大模型。InternLM2是一个基于Decoder-Only的对话大模型,我们可以使用transformers库来加载InternLM2

首先,还是先创建一个BaseModel类,这个类是一个抽象类,我们可以在这个类中定义一些基本的方法,比如chat方法和load_model方法。方便以后扩展使用其他模型。

class BaseModel:def __init__(self, path: str = '') -> None:self.path = pathdef chat(self, prompt: str, history: List[dict]):passdef load_model(self):pass

接着,我们创建一个InternLM2类,这个类继承自BaseModel类,我们在这个类中实现chat方法和load_model方法。就和正常加载InternLM2模型一样,来做一个简单的加载和返回即可。

class InternLM2Chat(BaseModel):def __init__(self, path: str = '') -> None:super().__init__(path)self.load_model()def load_model(self):print('================ Loading model ================')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()print('================ Model loaded ================')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
Step 2: 构造工具

我们在tools.py文件中,构造一些工具,比如Google搜索。我们在这个文件中,构造一个Tools类,这个类中包含了一些工具的描述信息和具体实现。我们可以在这个类中,添加一些工具的描述信息和具体实现。

  • 首先要在 tools 中添加工具的描述信息

  • 然后在 tools 中添加工具的具体实现

使用Google搜索功能的话需要去serper官网申请一下token: https://serper.dev/dashboard

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': {'type': 'string'},}],}]return toolsdef google_search(self, search_query: str):pass
Step 3: 构造Agent

我们在Agent类中,构造一个Agent,这个Agent是一个ReactAgent,我们在这个Agent中,实现了chat方法,这个方法是一个对话方法,我们在这个方法中,调用InternLM2模型,然后根据ReactAgent的逻辑,来调用Tools中的工具。

首先我们要构造system_prompt, 这个是系统的提示,我们可以在这个提示中,添加一些系统的提示信息,比如ReAct形式的prompt

def build_system_input(self):tool_descs, tool_names = [], []for tool in self.tool.toolConfig:tool_descs.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

OK, 如果顺利的话,运行出来的示例应该是这样的:

Answer the following questions as best you can. You have access to the following tools:google_search: Call this tool to interact with the 谷歌搜索 API. What is the 谷歌搜索 API useful for? 谷歌搜索是一个通用搜索引擎,可用于访问互联网、查询百科知识、了解时事新闻等。Parameters: [{'name': 'search_query', 'description': '搜索关键词或短语', 'required': True, 'schema': {'type': 'string'}}] Format the arguments as a JSON object.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 [google_search]
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 questionBegin!

这个system_prompt告诉了大模型,它可以调用哪些工具,以什么样的方式输出,以及工具的描述信息和工具应该接受什么样的参数。

目前只是实现了一个简单的Google搜索工具,后续会添加更多的关于地理信息系统分析的工具,没错,我是一个地理信息系统的学生。

关于Agent的具体结构可以在Agent.py中查看。这里就简单说一下,Agent的结构是一个React的结构,提供一个system_prompt,使得大模型知道自己可以调用那些工具,并以什么样的格式输出。

每次用户的提问,如果需要调用工具的话,都会进行两次的大模型调用,第一次解析用户的提问,选择调用的工具和参数,第二次将工具返回的结果与用户的提问整合。这样就可以实现一个React的结构。

下面为Agent代码的简易实现,每个函数的具体实现可以在Agent.py中查看。

class Agent:def __init__(self, path: str = '') -> None:passdef build_system_input(self):# 构造上文中所说的系统提示词passdef parse_latest_plugin_call(self, text):# 解析第一次大模型返回选择的工具和工具参数passdef call_plugin(self, plugin_name, plugin_args):# 调用选择的工具passdef text_completion(self, text, history=[]):# 整合两次调用pass
ebf60fa37be7a8e17ef94e1efc4ec726.png
Step 4: 运行Agent

在这个案例中,使用了InternLM2-chat-7B模型, 如果你想要Agent运行地更加稳定,可以使用它的big cup版本InternLM2-20b-chat,这样可以提高Agent的稳定性。

from Agent import Agentagent = 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》。

https://github.com/KMnO4-zx/TinyAgent

记得给仓库点个小小的 star 哦~

论文参考

ReAct: Synergizing Reasoning and Acting in Language Mod‍els

50b5f42423615dcde472020884f3117e.png
一起“赞”三连

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/791283.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

字符分类函数

字符分类函数 C语言中有⼀系列的函数是专门做字符分类的,也就是⼀个字符是属于什么类型的字符的。这些函数的使用都需要包含⼀个头文件是 ctype.h 这些函数的使用方法非常类似,我们就讲解⼀个函数的事情,其他的非常类似: int i…

图的应用解析

01.任何一个无向连通图的最小生成树(B )。 A.有一棵或多棵 B.只有一棵 C.一定有多棵 D.可能不存在 02.用Prim算法和Kruskal算法构造图的最小生成树&#xff0c…

内存和网卡压力测试

1.内存压力测试 1.1测试目的 内存压力测试的目的是评估开发板中的内存子系统性能和稳定性,以确保它能够满足特定的应用需求。开发板通常用于嵌入式系统、物联网设备、嵌入式智能家居等场景,这些场景对内存的要求通常比较高。 其内存压力测试的主要目的…

【深度学习】sdwebui的token_counter,update_token_counter,如何超出77个token的限制?对提示词加权的底层实现

文章目录 前言关于token_counter关于class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing)如何超出77个token的限制?对提示词加权的底层实现Overcoming the 77 token limit in diffusers方法1 手动拼方法2 compel 问询、帮助请看: 前言 …

动规训练2

一、最小路径和 1、题目解析 就是一个人从左上往做下走,每次只能往右或者往下,求他到终点时,路径上数字和最小,返回最小值 2、算法原理 a状态表示方程 小技巧:经验题目要求 用一个二维数组表示,创建一个…

Flask Python:数据库多条件查询,flask中模型关联

前言 在上一篇Flask Python:模糊查询filter和filter_by,数据库多条件查询中,已经分享了几种常用的数据库操作,这次就来看看模型的关联关系是怎么定义的,先说基础的关联哈。在分享之前,先分享官方文档,点击查看 从文档…

FreeRTOS中断管理以及实验

FreeRTOS中断管理以及实验 继续记录学习FreeRTOS的博客,参照正点原子FreeRTOS的视频。 ARM Cortex-M 使用了 8 位宽的寄存器来配置中断的优先等级,这个寄存器就是中断优先级配置寄存器 , STM32寄存器中并且这个寄存器只使用[7:4]&#xff0c…

RTX RTOS 操作实例分析之---线程(thread)

0 Preface/Foreword 1 线程(thread) 1.1 线程定义 1.1.1 USE_BASIC_THREADS(宏定义) 经过以上步骤(makefile包含),USE_BASIC_THREADS在编译阶段被定义到相应的模块中。 1.1.2 定义线程ID变量…

安装Pillow库的方法最终解答!_Python第三方库

安装Python第三方库Pillow 我的环境:Window10,Python3.7,Anaconda3,Pycharm2023.1.3 pillow库 Pillow库是一个非常强大的图像处理库。它提供了广泛的图像处理功能,让我们可以轻松地读取和保存图像、创建缩略图和合并到…

欧拉路径欧拉回路

欧拉回路,指遍历图时通过图中每条边且仅通过一次,最终回到起点的一条闭合回路,适用于有向图与无向图,如果不强制要求回到起点,则被称为欧拉路径。 欧拉图:具备欧拉回路的图 无向图:图的所有顶…

37-巩固练习(一)

37-1 if语句等 1、问&#xff1a;输出结果 int main() {int i 0;for (i 0; i < 10; i){if (i 5){printf("%d\n", i);}return 0;} } 答&#xff1a;一直输出5&#xff0c;死循环 解析&#xff1a;i5是赋值语句&#xff0c;不是判断语句&#xff0c;每一次循…

路径规划——曲线拟合详解(一):多项式轨迹与QP优化(minimum-snap算法核心部分)

前言 历经一个多星期时间&#xff0c;我们在路径规划——搜索算法部分讲解了7种常见的路径搜索算法&#xff0c;每一种算法的链接放在下面了&#xff0c;有需要的朋友点击跳转即可&#xff1a; 路径规划——搜索算法详解&#xff08;一&#xff09;&#xff1a;Dijkstra算法详…

由平行公设的不同而来三种几何学浅谈

由平行公设的不同而来三种几何学浅谈 欧几里德的《几何原本》 欧几里德的《几何原本》一开始就给出了23个定义&#xff0c;5个公设&#xff0c;5个公理。 23个定义(部分)&#xff1a; 点是没有部分的东西。 线是没有宽度的长度。 线的端点是点。 直线是各点都在同一方向上…

GraalVM运行模式和企业级应用

文章目录 GraalVM运行模式JIT模式AOT模式 GraalVM的问题和解决方案GraalVM企业级应用传统架构的问题Serverless架构函数计算Serverless应用场景Serverless应用 GraalVM内存参数 GraalVM运行模式 JIT模式 JIT&#xff08; Just-In-Time &#xff09;模式 &#xff0c;即时编译模…

Ruby 之交租阶段信息生成

题目 我看了一下&#xff0c;这个题目应该不是什么机密&#xff0c;所以先放上来了。大概意思是根据合同信息生成交租阶段信息。 解答 要求是要使用 Ruby 生成交租阶段信息&#xff0c;由于时间比较仓促&#xff0c;变量名那些就用得随意了些。要点主要有下面这些&#xff1a…

【介绍什么是DDOS】

&#x1f308;个人主页:程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

Qt 的发展历史、现状与启示

Qt 最早在1991年由挪威的两位程序员 Eirik Chambe-Eng 和 Haavard Nord 开发&#xff0c;他们在1994年创立 Trolltech 公司&#xff08;奇趣科技&#xff09;正式经营软件业务。Qt 的第一个公众预览版于1995年面世&#xff0c;之后在2008年被诺基亚收购&#xff1b;2011年到201…

Go——函数

一. 函数定义 1.1 特点 无需声明原型支持不定变参支持多返回值支持命名返回参数支持匿名函数和闭包函数也是一种类型&#xff0c;一种函数可以赋值给变量不支持嵌套&#xff0c;一个包不能有两个名字一样的函数不支持重载不支持默认参数 1.2 函数声明 函数声明包含一个函数名&…

备战蓝桥杯---DP刷题2

1.树形DP&#xff1a; 即问那几个点在树的直径上&#xff0c;类似ROAD那题&#xff0c;我们先求一下每一个子树根的子树的最大值与次大值用d1,d2表示&#xff0c;直径就是d1d2的最大值&#xff0c;那么我们如何判断是否在最大路径上&#xff0c;其实就是看一下从某一点出发的所…

还得是抖音,字节推出竖屏视频理解数据集,入选CVPR2024

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了免费的人工智能中文站https://ai.weoknow.com 新建了收费的人工智能中文站https://ai.hzytsoft.cn/ 更多资源欢迎关注 短视频在当下社交媒体逐渐成为主导的视频格式。传统视频处理技术和研究一般都专注于横屏视频…