CAMEL-Task2-Agent的构成组件

本文笔记主要关于2.7章节:CAMEL框架中agents如何使用工具。

一、工具说明

为什么要额外使用工具?

  • agents本身的知识和能力有限,比如一些问题需要联网搜索才能准确回答(而不是乱答,即“幻觉”),一些计算需要数学工具才能符合精度要求等。
  • agents本身不能和世界交互,需要依赖接口。比如:agents可以基于LLM的语言理解和生成能力对问题给予回应,但无法访问外部数据或执行具体的操作。

此时,工具的存在相当于为agents配备与外界交互的接口。工具的本质是一个具有名称、描述、输入参数和输出的函数,当agents“认为”自己需要使用工具时,只要agents能够正确地生成调用工具名称、参数,对应的工具就会被调用,工具的输出会成为agents继续回答的依据。

CAMEL提供了各种常用工具(包),也支持自定义工具。

二、工具自定义

以数学计算为例子,展示如何通过自定义工具,让agents的回答具备需要的精度。此处需要agents原生具备调用工具的能力(即支持function call)

无使用工具

from camel.agents import ChatAgent
from camel.models import ModelFactory
from camel.types import ModelPlatformTypeimport os
from dotenv import load_dotenv
import mathload_dotenv()# 定义系统消息
sys_msg = "你是一个数学大师,擅长各种数学问题。"# 初始化agent
api_key = os.getenv('QWEN_API_KEY')model = ModelFactory.create(model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL,model_type="Qwen/Qwen2.5-72B-Instruct",url='https://api-inference.modelscope.cn/v1/',api_key=api_key
)# 创建agent并添加工具
agent = ChatAgent(system_message=sys_msg,model=model,output_language='中文',tools=[]
)# 定义用户消息
usr_msg = "2的平方根是多少?"# 发送消息给agent
response = agent.step(usr_msg)
print(response.msgs[0].content)

此时得到的输出:

2的平方根是 \(\sqrt{2}\),约等于 1.414。

虽然没有错误,但精度不够高。此时可以借助数学计算工具达到更高的精度。

使用(自定义)工具

此处以“计算一个数的平方根”为例进行工具定义。示例代码(tool.py)如下:

from camel.toolkits import FunctionTool
import mathdef calculate_sqrt(x: float) -> float:r"""计算一个数的平方根。Args:x (float): 需要计算平方根的数字。Returns:float: 输入数字的平方根。"""return math.sqrt(x)# 用 FunctionTool 包装该函数
sqrt_tool = FunctionTool(calculate_sqrt)print(sqrt_tool.get_function_name()) # 检索函数的名称
print(sqrt_tool.get_function_description()) # 获取函数作用的描述

输出:

calculate_sqrt
计算一个数的平方根。

接下来将工具sqrt_tool引入,重新完成前述数学计算任务,代码如下:

from camel.agents import ChatAgent
from camel.models import ModelFactory
from camel.types import ModelPlatformType
from tool import sqrt_toolimport os
from dotenv import load_dotenv
import mathload_dotenv()# 定义系统消息
sys_msg = "你是一个数学大师,擅长各种数学问题。"# 初始化agent
api_key = os.getenv('QWEN_API_KEY')model = ModelFactory.create(model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL,model_type="Qwen/Qwen2.5-72B-Instruct",url='https://api-inference.modelscope.cn/v1/',api_key=api_key
)# 定义系统消息
sys_msg = "你是一个数学大师,擅长各种数学问题。当你遇到数学问题的时候,你要调用工具,将工具计算的结果作为答案"# 定义用户消息
usr_msg = "2的平方根是多少?"# 创建agent并添加工具
tool_agent = ChatAgent(tools = [sqrt_tool], # 使用自定义的sqrt_toolsystem_message=sys_msg,model=model,output_language="中文")# 重新发送消息给toolagent
response = tool_agent.step(usr_msg)
print(response.msgs[0].content)
print(response.info['tool_calls']) # 检查工具是否真的被调用

输出:

2的平方根是1.4142135623730951。
[ToolCallingRecord(tool_name='calculate_sqrt', args={'x': 2}, result=1.4142135623730951, tool_call_id='call_7c18733f4d324bfb98944f', images=None)]

可以看到agents给出了更精确的结果,并且工具确实被调用。

三、使用CAMEL内置工具

此处以“查询牛津大学校龄”为问题(假设现在是2024年,牛津大学的成立年份,并计算出其当前年龄。然后再将这个年龄加上10年。使用百度搜索工具。),考察agents在CAMEL框架下能否正确使用工具(SearchToolkitMathToolkit)回答问题。

代码如下:

from camel.toolkits import SearchToolkit,MathToolkit
from camel.types.agents import ToolCallingRecord
from camel.models import ModelFactory
from camel.types import ModelPlatformType
from camel.societies import RolePlaying
from camel.utils import print_text_animated
from colorama import Foreimport os
from dotenv import load_dotenvload_dotenv()
api_key = os.getenv('QWEN_API_KEY')#定义工具包
tools_list = [*SearchToolkit().get_tools(),*MathToolkit().get_tools()
]# 设置任务
task_prompt = ("假设现在是2024年,""牛津大学的成立年份,并计算出其当前年龄。""然后再将这个年龄加上10年。使用百度搜索工具。")# 创建模型
model = ModelFactory.create(model_platform=ModelPlatformType.OPENAI_COMPATIBLE_MODEL,model_type="Qwen/Qwen2.5-72B-Instruct",url='https://api-inference.modelscope.cn/v1/',api_key=api_key
)# 设置角色扮演
role_play_session = RolePlaying(assistant_role_name="搜索者",user_role_name="教授",assistant_agent_kwargs=dict(model=model,tools=tools_list, # 允许agent使用SearchToolkit,MathToolkit),user_agent_kwargs=dict(model=model,),task_prompt=task_prompt,with_task_specify=False,output_language='中文'
)# 设置聊天轮次限制
chat_turn_limit=10print(Fore.GREEN+ f"AI助手系统消息:\n{role_play_session.assistant_sys_msg}\n"
)
print(Fore.BLUE + f"AI用户系统消息:\n{role_play_session.user_sys_msg}\n"
)print(Fore.YELLOW + f"原始任务提示:\n{task_prompt}\n")
print(Fore.CYAN+ "指定的任务提示:"+ f"\n{role_play_session.specified_task_prompt}\n"
)
print(Fore.RED + f"最终任务提示:\n{role_play_session.task_prompt}\n")n = 0
input_msg = role_play_session.init_chat()
while n < chat_turn_limit:n += 1assistant_response, user_response = role_play_session.step(input_msg)if assistant_response.terminated:print(Fore.GREEN+ ("AI助手终止。原因: "f"{assistant_response.info['termination_reasons']}."))breakif user_response.terminated:print(Fore.GREEN+ ("AI用户终止。"f"原因: {user_response.info['termination_reasons']}."))break# 打印用户的输出print_text_animated(Fore.BLUE + f"AI用户:\n\n{user_response.msg.content}\n")if "CAMEL_TASK_DONE" in user_response.msg.content:break# 打印助手的输出,包括任何函数执行信息print_text_animated(Fore.GREEN + "AI助手:")tool_calls: list[ToolCallingRecord] = assistant_response.info['tool_calls']for func_record in tool_calls:print_text_animated(f"{func_record}")print_text_animated(f"{assistant_response.msg.content}\n")input_msg = assistant_response.msg

先安装beautifulsoup4这个python包,否则后续调用工具时,会因为缺少这个包而无法调用。

输出记录

AI助手系统消息
BaseMessage(role_name='搜索者', role_type=<RoleType.ASSISTANT: 'assistant'>, meta_dict={'task': '假设现在是2024年,牛津大学的成立年份,并计算出其当前年龄。然后再将这个年龄加上10年。使用百度搜索工具。', 'assistant_role': '搜索者', 'user_role': '教授'}, content='===== RULES OF ASSISTANT =====\nNever forget you are a 搜索者 and I am a 教授. Never flip roles! Never instruct me!\nWe share a common interest in collaborating to successfully complete a task.\nYou must help me to complete the task.\nHere is the task: 假设现在是2024年,牛津大学的成立年份,并计算出其当前年龄。然后再将这个年龄加上10年。使用百度搜索工具。. Never forget our task!\nI must instruct you based on your expertise and my needs to complete the task.\n\nI must give you one instruction at a time.\nYou must write a specific solution that appropriately solves the requested instruction and explain your solutions.\nYou must decline my instruction honestly if you cannot perform the instruction due to physical, moral, legal reasons or your capability and explain the reasons.\nUnless I say the task is completed, you should always start with:\n\nSolution: <YOUR_SOLUTION>\n\n<YOUR_SOLUTION> should be very specific, include detailed explanations and provide preferable detailed implementations and examples and lists for task-solving.\nAlways end <YOUR_SOLUTION> with: Next request.\nRegardless of the input language, you must output text in 中文.', video_bytes=None, image_list=None, image_detail='auto', video_detail='auto', parsed=None)
AI用户系统消息
BaseMessage(role_name='教授', role_type=<RoleType.USER: 'user'>, meta_dict={'task': '假设现在是2024年,牛津大学的成立年份,并计算出其当前年龄。然后再将这个年龄加上10年。使用百度搜索工具。', 'assistant_role': '搜索者', 'user_role': '教授'}, content='===== RULES OF USER =====\nNever forget you are a 教授 and I am a 搜索者. Never flip roles! You will always instruct me.\nWe share a common interest in collaborating to successfully complete a task.\nI must help you to complete the task.\nHere is the task: 假设现在是2024年,牛津大学的成立年份,并计算出其当前年龄。然后再将这个年龄加上10年。使用百度搜索工具。. Never forget our task!\nYou must instruct me based on my expertise and your needs to solve the task ONLY in the following two ways:\n\n1. Instruct with a necessary input:\nInstruction: <YOUR_INSTRUCTION>\nInput: <YOUR_INPUT>\n\n2. Instruct without any input:\nInstruction: <YOUR_INSTRUCTION>\nInput: None\n\nThe "Instruction" describes a task or question. The paired "Input" provides further context or information for the requested "Instruction".\n\nYou must give me one instruction at a time.\nI must write a response that appropriately solves the requested instruction.\nI must decline your instruction honestly if I cannot perform the instruction due to physical, moral, legal reasons or my capability and explain the reasons.\nYou should instruct me not ask me questions.\nNow you must start to instruct me using the two ways described above.\nDo not add anything else other than your instruction and the optional corresponding input!\nKeep giving me instructions and necessary inputs until you think the task is completed.\nWhen the task is completed, you must only reply with a single word <CAMEL_TASK_DONE>.\nNever say <CAMEL_TASK_DONE> unless my responses have solved your task.\nRegardless of the input language, you must output text in 中文.', video_bytes=None, image_list=None, image_detail='auto', video_detail='auto', parsed=None)
任务提示
原始任务提示:
假设现在是2024年,牛津大学的成立年份,并计算出其当前年龄。然后再将这个年龄加上10年。使用百度搜索工具。指定的任务提示:
None最终任务提示:
假设现在是2024年,牛津大学的成立年份,并计算出其当前年龄。然后再将这个年龄加上10年。使用百度搜索工具。Warning: No results found. Check if Baidu HTML structure has changed.
AI用户
Instruction: 使用百度搜索工具查找牛津大学的成立年份。
Input: None
AI助手
Tool Execution: search_baiduArgs: {'query': '牛津大学 成立年份', 'number_of_result_pages': 1}Result: {'results': []}
Tool Execution: subArgs: {'a': 2024, 'b': 1167}Result: 857
看起来直接从百度搜索结果中没有获取到具体的信息,但我可以根据已知的资料来回答您的问题。牛津大学的成立年份普遍认为是在1096年或者1167年,但确切的日期并不确定,因为大学是一个逐渐形成的过程而不是一个具体的事件。如果我们假设牛津大学的成立年份为1167年,那么到2024年,牛津大学的年龄将是857年。接下来,我将这个年龄再加上10年。857 + 10 = 867年。因此,如果现在是2024年,那么牛津大学在2024年的年龄是857年,而再过10年后,它的年龄将会是867年。如果您需要进一步确认牛津大学的确切成立年份,请告诉我,我可以尝试通过其他途径查询。 Next request.
AI用户
Instruction: 确认牛津大学的成立年份是否为1167年,并计算其在2024年的年龄以及再过10年的年龄。
Input: 1167
AI助手
Tool Execution: search_baiduArgs: {'query': '牛津大学 确切成立年份', 'number_of_result_pages': 1}Result: {'results': [{'result_id': 1, 'title': '...世界中最古老的大学。A哈佛大学B剑桥大学B剑桥大学C牛津大学D...', 'description': '', 'url': 'http://www.baidu.com/link?url=R4hnTfV9RxjVwHauc21YLg_AUDUwVSCLVJ2A6a7rLBeHkg2sIHQXi7D6NUMtvyLfliWl5mPj2NPg_HMkLVtjZdeWIw1jNGDYnh9L2YrL6nWt3HnADJ4UGP8oZsFTRsqWmKBPYaaYC5NumQRQYwRCmK'}]}
根据百度搜索的结果,虽然没有直接明确指出牛津大学的具体成立年份,但根据历史记载和学术界的共识,牛津大学的成立年份通常被认为是1167年。因此,按照1167年作为牛津大学的成立年份,我们可以计算出:
- 到2024年,牛津大学的年龄为857年(2024 - 1167 = 857)。
- 再过10年,即2034年,牛津大学的年龄将是867年(857 + 10 = 867)。所以,牛津大学在2024年的年龄是857年,而在2034年的年龄将是867年。 Next request.
AI用户
Instruction: 确认上述计算结果是否正确,并完成任务。
Input: 857年,867年
AI助手
根据之前的计算和信息确认,牛津大学的成立年份为1167年。因此:- 2024年时,牛津大学的年龄为 \(2024 - 1167 = 857\) 年。
- 再过10年,即2034年时,牛津大学的年龄为 \(857 + 10 = 867\) 年。这些计算结果是正确的。至此,我们已经完成了任务,确认了牛津大学在2024年的年龄为857年,以及再过10年后其年龄为867年。如果您有其他任何问题或需要进一步的帮助,请随时告知。任务已完成。 Next request.
AI用户
CAMEL_TASK_DONE

观察

此案例中同样使用RolePlaying。由于使用的LLM基座不是很厉害,所以AI用户和AI助手的对话其实会随着每次运行的不同而改变,这里选取了一次确实调用了工具查证后再回答问题的对话记录进行分析。

是的,有时候agents会假装自己用了工具,但实际上工具函数的输入参数是自己编的。

在AI用户和AI助手的对话过程中,第一回合里面AI助手其实工具调用没有返回有用的信息,但自己先假设了一个结果,再第二回合里再去验证。验证的时候,工具返回了有用的信息(可以通过response.info['tool_calls']查看工具调用的具体信息),这使得后续对话内容更具有真实性。

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

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

相关文章

数据整理自动化 - 让AI成为你的数据助手

文章目录数据整理自动化 - 让AI成为你的数据助手引言&#xff1a;数据整理的时代挑战与机遇1. 常见数据整理场景分析1.1 数据整理的多元场景图谱1.2 数据质量问题的分类与影响1.3 传统处理方法的局限性2. AI与传统脚本的协同工作流2.1 智能数据整理架构设计2.2 协同工作流的最佳…

react速成

项目目录package.json文件&#xff1a;包含核心两个依赖&#xff08;react、react-dom&#xff09;和命令&#xff08;start、bulid&#xff09;src&#xff1a;源码目录&#xff0c;开始之用的到index.js和App.jsindex.js&#xff1a;是项目的入口&#xff0c;一切的运行起点/…

Maven的进阶使用(上)

pom.xml文件 就像 Make 的 MakeFile、Ant 的 build.xml 一样&#xff0c;Maven 项目的核心是 pom.xml。POM(全称 Project Object Model&#xff0c;项目对象模型 ) 定义了项目的基本信息&#xff0c;用于描述项目如何构建&#xff0c;声明项目依赖&#xff0c;等等。 Gredele--…

【最后203篇系列】034 使用SQLite构建简单的任务管理

表数据同步的断点续传 有时候需要将一个表的数据复制到另一个表&#xff0c;循环是常用的方式。当表比较大&#xff0c;执行的时间很长&#xff0c;会有很多因素引起失败。我希望可以比较简单的跑数&#xff0c;所以做一个简单的任务系统。 SQLitre是嵌入式数据库&#xff0c;这…

SpringCloud Alibaba核心知识点

Spring Cloud Alibaba 是阿里巴巴开源的一套微服务解决方案&#xff0c;与 Spring Cloud 生态深度集成。以下是其主要组件及其功能&#xff1a;Nacos服务注册与发现&#xff1a;支持动态服务注册、健康监测及DNS-Based服务发现。配置中心&#xff1a;提供分布式配置管理&#x…

LeetCode 分类刷题:34. 在排序数组中查找元素的第一个和最后一个位置

题目给你一个按照非递减顺序排列的整数数组 nums&#xff0c;和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target&#xff0c;返回 [-1, -1]。你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。示例 1&#xff1a;…

自建知识库,向量数据库 (十二)之 文章向量搜索——仙盟创梦IDE

“未来之窗” 文章向量搜索&#xff1a;多领域应用与学习指南 在数字化浪潮中&#xff0c;“未来之窗” 文章向量搜索凭借其独特的技术优势&#xff0c;在酒店、电商、诊疗及知识库等多个领域展现出巨大的应用潜力&#xff0c;为各行业的信息处理与检索带来了全新的视角和高效…

深度剖析:基于反射的.NET二进制序列化器设计与实现

&#x1f50d; 深度剖析&#xff1a;基于反射的.NET二进制序列化器设计与实现本文将从底层原理到高级优化&#xff0c;全面剖析一个基于反射的.NET二进制序列化器的设计与实现&#xff0c;涵盖类型系统处理、内存布局、递归算法、性能优化等核心主题。1. 设计哲学与架构总览 1.…

如何在 Ubuntu 上安装和配置 Samba ?

Samba 是一个开源程序&#xff0c;用于文件共享和网络打印&#xff0c;使用 SMB 协议。现在基本上用于提供在 Windows 上可访问的 Linux 文件共享系统。 本文介绍如何在 Ubuntu 上安装和配置 Samba 服务器&#xff0c;以便跨文件夹共享网络上不同的计算机。 Update Your Syst…

MATLAB实现CNN-GRU-Attention时序和空间特征结合-融合注意力机制混合神经网络模型的风速预测

该 MATLAB 代码实现了一个基于 CNN-GRU-Attention 时序和空间特征结合-融合注意力机制混合神经网络模型的风速预测。以下是对代码的简要分析&#xff1a;一、主要功能 该代码用于风速时间序列预测&#xff0c;使用历史风速特征数据&#xff08;18个特征&#xff0c;75天&#x…

【升级版】从零到一训练一个 0.6B 的 MoE 大语言模型

前文&#xff1a;从零到一训练一个 0.6B 的 MoE 大语言模型&#xff0c;本次升级完全重新从零开始重新训练。主要升级如下&#xff1a; 替换预训练数据集&#xff0c;使用序列猴子通用文本数据集进行预训练。使用更先进的训练方法。新增思考模式控制&#xff0c;可通过添加/th…

51单片机-实现定时器模块教程

本章概述思维导图&#xff1a; 51单片机驱动定时器模块 CPU时序简介 CPU时序定义了CPU内部操作的时间节奏&#xff0c;以下从四个时序周期进行逐步解析&#xff1b; 1、振荡周期 振荡周期&#xff1a;CPU内部时钟源产生的最小时间单位&#xff0c;由晶振或内部振荡器决定&am…

7.Kotlin的日期类

以下是 Kotlin 中常用时间类&#xff08;基于 java.time 包&#xff09;的核心方法及使用示例&#xff0c;参考数组方法的表格形式&#xff0c;按类分类展示&#xff1a; 一、LocalDate&#xff08;日期&#xff1a;年/月/日&#xff09;方法签名返回值说明示例now(): LocalDat…

【Big Data】Hive技术解析:大数据仓库的SQL桥梁

Hive作为Apache顶级项目&#xff0c;是Hadoop生态系统中最具影响力的SQL查询引擎&#xff0c;它解决了大数据处理与传统SQL技能之间的鸿沟。Hive的核心价值在于将类SQL查询语言HiveQL无缝转换为分布式计算框架MapReduce的任务&#xff0c;使数据分析师能够利用熟悉的SQL语法操作…

Ubuntu2204server系统安装postgresql14并配置密码远程连接

前言&#xff1a; 最近因项目需要安装postgresql14&#xff0c;系统是ubuntu2204server系统&#xff0c;安装好后发现无法实现远程连接&#xff0c;解决了之后在此记录一下解决方法。 疑问&#xff1a; 什么情况下需要配置postgresql远程连接&#xff1f; ①如果是postgresql和…

【嵌入式】【搜集】状态机、状态迁移图及状态模式材料

文章目录状态机状态机状态机定义与核心特点状态机总结状态迁移图状态迁移图状态迁移图核心概念与要素状态迁移图常见错误与规避状态迁移图总结状态模式状态模式状态模式核心概念与组成状态模式核心价值与适用场景状态模式优缺点分析进阶优化技巧行为模式总结状态机 状态机 状…

Java学习历程14——制作一款五子棋游戏(4)

上次我们基本实现了五子棋游戏的功能&#xff0c;这次我们进行一些优化和添加一些便于用户使用的功能。新增功能及优化一、复盘功能复盘功能就是指在下完一局棋后&#xff0c;我们可以通过复盘按钮使本局棋的所有棋子重头开始自动下一遍。分析得知&#xff0c;我们首先要保存以…

记录一次el-table+sortablejs的拖拽bug

bug回顾出现bug的情况时 当编辑表格过于紧凑的时候 有些非必要编辑或需要一眼看到的数据 移动到了el-table-column typeexpand时 同事&#xff1a;怎么拖拽功能用不了了 ok开始检查代码 当原来是个简单的编辑表格 不涉及展开和简单拖拽时 不会出现问题 解决了 出现了展开行以后…

利用go sort.Sort()排序自定义切片

1 sort.Sort()简介2 核心功能3 调用前提4 代码示例 1 sort.Sort()简介 Go语言中的sort.Sort函数是标准库提供的通用排序接口 2 核心功能 核心功能支持多种类型进行快速排序 基础类型支持‌&#xff1a;内置Ints、Float64s、Strings等函数直接排序常见切片 自定义排序‌&a…

Elasticsearch脑裂紧急处理与预防

在 Elasticsearch 中出现 网络分区&#xff08;Network Partition&#xff09; 或 脑裂&#xff08;Split-Brain&#xff09; 导致两个子集群各自选出 Master 的情况&#xff0c;是非常严重的问题。比如这个场景&#xff08;20个节点分裂成两个10节点的子集群&#xff0c;各自选…