工具调用 (tool calling)
-
创建工具:通过@tool 装饰器创建工具
-
工具绑定:工具需要连接到支持工具调用的模型
-
工具调用:模型可以决定是否使用工具并确保其响应符合工具的输入模式
- 工具调用的结果只生成相关参数,不会生成最终答案
-
[!question] 使用模型的工具调用过程中遇到的一些问题
- 使用免费的大模型
API
- 使用
glm-4-flash
模型
- 问题一:在使用
工具调用函数.tool_calls
时只能转化一个问题。例如What is 3 * 12? Also, what is 11 + 49?
只能转化3 * 12
的部分- 问题二:在生成
ToolMessages
时会出现问题,以至于无法进行后续输出结果- 使用
mistral-tiny
模型(可能是模型参数不够)
- 与
glm-4-flash
模型问题一一样,但ToolMessages
正常,最终只能得到一个结果- 使用
mistral-large-latest
模型
- 在最后输出结果出现服务器报错,(可能是使用免费额度的问题??)
- 使用本地
ollama
平台部署的miatral
模型
- 无法使用
bind_tools
- 综合以上问题选择
mistral-tiny
模型来作为本篇笔记的模型 - 作者小白一个,请各位有解决方法的大佬指教
# 加载环境变量
import os
from dotenv import load_dotenv
load_dotenv()
print("MISTRAL_API_KEY:", os.getenv("MISTRAL_API_KEY"))
MISTRAL_API_KEY: *********************************
# 导入mistral模型
from langchain_mistralai import ChatMistralAI
# chat_model=ChatMistralAI(model="mistral-large-latest")
chat_model=ChatMistralAI(model="mistral-tiny")
chat_model.invoke("你好")
AIMessage(content='你好!欢迎来问我问题!我会尽力回答你的问题。', additional_kwargs={}, response_metadata={'token_usage': {'prompt_tokens': 6, 'total_tokens': 29, 'completion_tokens': 23}, 'model': 'mistral-tiny', 'finish_reason': 'stop'}, id='run-722b629f-09b8-42db-b41f-c612f03317fc-0', usage_metadata={'input_tokens': 6, 'output_tokens': 23, 'total_tokens': 29})
# 使用Pydantic类来创建工具
from pydantic import BaseModel,Field
class add(BaseModel):
"""将两个数相加"""
a:int=Field(...,description="第一个数")
b:int=Field(...,description="第二个数")
class multiply(BaseModel):
"""将两个数相乘"""
a:int=Field(...,description="第一个数")
b:int=Field(...,description="第二个数")
tools=[add,multiply]
model_with_tools=chat_model.bind_tools(tools=tools)
query="3*12等于多少?"
model_with_tools.invoke(query)
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'jZIqBB1h8', 'type': 'function', 'function': {'name': 'multiply', 'arguments': '{"a": 3, "b": 12}'}}]}, response_metadata={'token_usage': {'prompt_tokens': 187, 'total_tokens': 213, 'completion_tokens': 26}, 'model': 'mistral-tiny', 'finish_reason': 'tool_calls'}, id='run-b31c7597-08f2-4a01-a226-bfc5e6c9afd4-0', tool_calls=[{'name': 'multiply', 'args': {'a': 3, 'b': 12}, 'id': 'jZIqBB1h8', 'type': 'tool_call'}], usage_metadata={'input_tokens': 187, 'output_tokens': 26, 'total_tokens': 213})
工具调用
query="3乘12等于多少,以及11加22等于多少?"
model_with_tools.invoke(query).tool_calls
[{'name': 'multiply',
'args': {'a': 3, 'b': 12},
'id': 'cGtT91ASZ',
'type': 'tool_call'}]
用解析器对结果进一步处理
from langchain_core.output_parsers import PydanticToolsParser
chain=model_with_tools | PydanticToolsParser(tools=tools)
chain.invoke(query)
[multiply(a=3, b=12)]
将工具输出传递给模型
- 工具调用的结果这是生成相应的参数并没有生成最终结果,需要再构建消息队列传递给模型才能生成最终结果
# 使用修饰器@tool来创建工具
from langchain_core.tools import tool
@tool
def add(a:int,b:int)->int:
"""将两个数相加"""
return a+b
@tool
def multiply(a:int,b:int)->int:
"""将两个数相乘"""
return a*b
tools=[add,multiply]
model_with_tools=chat_model.bind_tools(tools=tools)
# 构建消息列表
from langchain_core.messages import HumanMessage
query="3乘12等于多少,以及11加22等于多少?"
messages=[HumanMessage(content=query)]
ai_message=model_with_tools.invoke(messages)
print(ai_message) #模型返回的全部结果
print(ai_message.tool_calls) #模型返回的工具调用
messages.append(ai_message)
print(messages)
content='' additional_kwargs={'tool_calls': [{'id': '7fbmjpuoQ', 'type': 'function', 'function': {'name': 'multiply', 'arguments': '{"a": 3, "b": 12}'}}]} response_metadata={'token_usage': {'prompt_tokens': 165, 'total_tokens': 191, 'completion_tokens': 26}, 'model': 'mistral-tiny', 'finish_reason': 'tool_calls'} id='run-82682fd1-9bcf-4578-8b2d-a2849f14050e-0' tool_calls=[{'name': 'multiply', 'args': {'a': 3, 'b': 12}, 'id': '7fbmjpuoQ', 'type': 'tool_call'}] usage_metadata={'input_tokens': 165, 'output_tokens': 26, 'total_tokens': 191}
[{'name': 'multiply', 'args': {'a': 3, 'b': 12}, 'id': '7fbmjpuoQ', 'type': 'tool_call'}]
[HumanMessage(content='3乘12等于多少,以及11加22等于多少?', additional_kwargs={}, response_metadata={}), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': '7fbmjpuoQ', 'type': 'function', 'function': {'name': 'multiply', 'arguments': '{"a": 3, "b": 12}'}}]}, response_metadata={'token_usage': {'prompt_tokens': 165, 'total_tokens': 191, 'completion_tokens': 26}, 'model': 'mistral-tiny', 'finish_reason': 'tool_calls'}, id='run-82682fd1-9bcf-4578-8b2d-a2849f14050e-0', tool_calls=[{'name': 'multiply', 'args': {'a': 3, 'b': 12}, 'id': '7fbmjpuoQ', 'type': 'tool_call'}], usage_metadata={'input_tokens': 165, 'output_tokens': 26, 'total_tokens': 191})]
# 将工具调用结果添加到消息列表中
for tool_call in ai_message.tool_calls:
selected_tool={ #从字典中选择对应的工具
"add":add, #加法工具,add对应用tool修饰过的函数(工具对象)
"multiply":multiply #乘法工具
}[tool_call["name"].lower()] #获取工具调用返回的名称并转化成小写,最后从定义的字典的获取对应的工具
tool_msg=selected_tool.invoke(tool_call) #执行工具调用,select_tool获取到的是工具对象可以使用invoke,返回ToolMessage对象
messages.append(tool_msg)
messages
[HumanMessage(content='3乘12等于多少,以及11加22等于多少?', additional_kwargs={}, response_metadata={}),
AIMessage(content='', additional_kwargs={'tool_calls': [{'id': '7fbmjpuoQ', 'type': 'function', 'function': {'name': 'multiply', 'arguments': '{"a": 3, "b": 12}'}}]}, response_metadata={'token_usage': {'prompt_tokens': 165, 'total_tokens': 191, 'completion_tokens': 26}, 'model': 'mistral-tiny', 'finish_reason': 'tool_calls'}, id='run-82682fd1-9bcf-4578-8b2d-a2849f14050e-0', tool_calls=[{'name': 'multiply', 'args': {'a': 3, 'b': 12}, 'id': '7fbmjpuoQ', 'type': 'tool_call'}], usage_metadata={'input_tokens': 165, 'output_tokens': 26, 'total_tokens': 191}),
ToolMessage(content='36', name='multiply', tool_call_id='7fbmjpuoQ')]
# 将工具结果传递给模型计算出最后结果
model_with_tools.invoke(messages)
AIMessage(content='三乘十二等于三十六。\n\n[-1, {"name": "add", "arguments": {"a": 11, "b": 22}, "id": "526f7p3j6"}]', additional_kwargs={}, response_metadata={'token_usage': {'prompt_tokens': 220, 'total_tokens': 274, 'completion_tokens': 54}, 'model': 'mistral-tiny', 'finish_reason': 'stop'}, id='run-2dc03724-072c-4db8-bcd7-d1e5741312a4-0', usage_metadata={'input_tokens': 220, 'output_tokens': 54, 'total_tokens': 274})