注意:@tool 修饰在langchainV0.2支持
什么是@tool修饰?
from langchain_core.tools import tool
@tool
def add(a: int, b: int) -> int:
"""Adds a and b."""
return a + b
from langchain_openai import ChatOpenAI
tool = [add]
model = ChatOpenAI(model="gpt-4o-2024-08-06")
prompt = "5+6等于多少?"
model_with_tool = model.bind_tools(tools=tool, tool_choice="add")
model_with_tool.invoke(prompt).tool_calls
return如下,可见返回的消息中已经有函数调用信息,但是现在还没有进行函数调用
[{'name': 'add',
'args': {'a': 5, 'b': 6},
'id': 'call_UXCUvL7VpFJKhFmGEmfGiOlX',
'type': 'tool_call'}]
经过@tool修饰就可以令自定义的函数像langchain预定义的工具(tool)一样被支持工具调用的模型(例如OpenAI的GPT系列)调用
下面我们根据模型生成的参数和调用信息来调用工具
# 将用户输入和准备调用工具的信息转换为列表作为下一步给模型的输入
tool_invoke = add.invoke(model_with_tool.invoke(prompt).tool_calls[0])
tool_invoke
输出
ToolMessage(content='11', name='add', tool_call_id='call_3EzfZjrkTYMYwssYEInaloDY')
这样就实现了一次完整的工具调用,那么后续我们就可以根据执行的结果来进行模型的自然语言回答,这里不做介绍
duckduckgo是一个完全免费的搜索工具,调用也是免费的不同于Tavily和Google有免费额度的搜索限制,开发阶段(对于资金不充裕的我)非常友好
langchain中的duckduckgo工具的文档给定的示例 DuckDuckGoSearchResults
这个接口我认为已经过时,可以直接用 @tool
来自己实现修饰一个duckduckgo搜索工具的实现,duckduckgo_search这个链接是python包的地址,在用langchain官方示例
DuckDuckGoSearchResults.invoke(“what is openai?”)
如图1它不能给我返回有效的例如官网或者wiki的介绍
如图2直接调用duckduckgo_search sdk中的函数返回的内容确是非常精准的有wiki和官网的内容,还有一些额外的功能可以自己进行实现,所以我推荐自己制作一个tool来调用,这样的体验和可控性会更好
那么如何实现我们可以仿照上述@tool来实现,注意实现函数的时候里面的描述也会传递给模型所以大家写描述的时候要写清楚
from langchain_core.tools import tool
from duckduckgo_search import DDGS
@tool
def duckduckgo(query: str) -> list:
"""
Invoke DuckDuckGo's service to retrieve the latest information from the internet.
Args:
query: The query.
Returns:
search_results: The search results.
"""
search_results = DDGS().text(keywords=query, region="wt-wt", safesearch="on", max_results=2)
return search_results
from langchain_openai import ChatOpenAI
tool = [duckduckgo]
model = ChatOpenAI(model="gpt-4o-2024-08-06")
prompt = "what is openai?"
model_with_tool = model.bind_tools(tools=tool, tool_choice="duckduckgo")
model_with_tool.invoke(prompt).tool_calls
return
[{'name': 'duckduckgo',
'args': {'query': 'OpenAI'},
'id': 'call_2buAM5HatlN9MwhS3wV6qIdH',
'type': 'tool_call'}]
tool_invoke = duckduckgo.invoke(model_with_tool.invoke(prompt).tool_calls[0])
tool_invoke
return
ToolMessage(content='[{"title": "OpenAI", "href": "https://openai.com/", "body": "Instant answers. Greater productivity. Endless inspiration. We believe our research will eventually lead to artificial general intelligence, a system that can solve human-level problems. Building safe and beneficial AGI is our mission."}, {"title": "ChatGPT | OpenAI", "href": "https://openai.com/chatgpt/", "body": "Get started with ChatGPT today. View pricing plans. Free. Assistance with writing, problem solving and more. Access to GPT-4o mini. Limited access to GPT-4o. Limited access to advanced data analysis, file uploads, vision, web browsing, and image generation. Use custom GPTs. $0/ month."}]', name='duckduckgo', tool_call_id='call_Uz2bxRlaORAgH5UtTyIctIj1')
返回的内容是OpenAI官网,可见搜索的还是很精准的
那么你也可以自己来定义自己的工具来给LLM使用,像定义函数一样容易