LangChain實戰 | Tool Calling :讓AI真正動起來的關鍵技術
近年來大模型發展過程中面臨的幾個核心挑戰:靜態知識的局限性、執行能力的缺失、與外部系統的割裂。為了應對這些挑戰,推動大模型從單純的語言生成工具演變為真正的任務執行引擎,Function calling 誕生了,成為大模型一項不可或缺的核心能力。
概念 Function calling 和 Tool Calling 會混用
我們在做應用開發的時候,大部分時候盡量避免直接耦合到OpenAI,會使得程序兼容性不好,這時只要面向 LangChain 開發就可以了。
LangChain 是一個靈活的框架,它提供了與多種大模型進行交互的能力。
它的設計允許集成和使用來自不同源的多種模型,包括但不限于OpenAl、Cohere和 Hugging Face 等模型庫中的模型。這樣,你不必拘泥于某種模型,而是為自己的應用選擇最合適的模型。對于Tool Calling能力來說,LangChain 也做了抽象。
調用其他工具的 API(如:Database Tool) 通常需要特定的有效負載格式。可以使用 Tool Calling 來向模型請求與特定格式匹配的響應。隨后可以使用這個響應作為負載去做“工具(Tool)實際的執行”。
通俗來將就是:讓大模型通過理解用戶的提示詞,來決定是否需要調用工具(如上圖),
如果需要調用工具,會返回需要調用的工具名稱和調用參數(不是直接執行工具),后續由代碼去執行對應的工具(Tool)。
如果不需要調用工具,那么就直接回復自然語言(如:How can I assist you?)。
工具(Tool)
tool抽象 在 LangChain 中將 Python函數 與 定義“函數名稱、描述和預期參數”的schema 關聯起來。
工具(Tool) 可以傳給支持 tool calling 的 聊天模型,允許模型使用特定輸入執行特定函數。
創建工具的推薦方法是使用@tool 裝飾器。此裝飾器旨在簡化工具創建過程,在大多數情況下應使用它。定義函數后,可以使用@tool 對其進行裝飾,以創建實現工具接口 的工具。
代碼如:
from langchain_core.tools import tool
@tool
def multiply(a: int, b: int) -> int:
"""兩個數字相乘."""
return a * b
默認情況下,裝飾器使用函數名稱作為工具名稱。
裝飾器將使用函數的文檔字符串作為工具的描述 —— 因此必須提供文檔字符串。
定義工具后,可以通過調用直接使用它。
result = multiply.invoke({"a": 2, "b": 3})
print(result)
# Output: 6
也能直接看到工具的具體信息。
print(multiply.name)
print(multiply.description)
print(multiply.args)
# 輸出
multiply
兩個數字相乘.
{'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}}
通過參數自定義工具
@tool("multiplication-tool", args_schema=CalculatorInput, return_direct=True)
屬性 | 類型 | 描述 |
名稱 | str | 在提供給 LLM 或代理的一組工具中必須是唯一的。 |
描述 | str | 描述工具的作用。用作 LLM 或代理的上下文。 |
args_schema | pydantic.BaseModel | 可選但推薦,如果使用回調處理程序則為必需。它可用于提供更多信息(例如,少量示例)或驗證預期參數。 |
return_direct | 布爾值 | 僅與agent相關。當為 True 時,在調用給定的工具后,代理將停止并將結果直接返回給用戶。 |
代碼如:
from pydantic import BaseModel, Field
class CalculatorInput(BaseModel):
a: int = Field(descriptinotallow="第一個數字")
b: int = Field(descriptinotallow="第二個數字")
# 通過參數自定義
@tool("multiplication-tool", args_schema=CalculatorInput, return_direct=True)
def multiply(a: int, b: int) -> int:
"""兩個數字相乘."""
return a * b
# 查看工具的具體信息
print(multiply.name)
print(multiply.description)
print(multiply.args)
print(multiply.return_direct)
輸出:
# 輸出
multiplication-tool
兩個數字相乘.
{'a': {'description': '第一個數字', 'title': 'A', 'type': 'integer'}, 'b': {'description': '第二個數字', 'title': 'B', 'type': 'integer'}}
True
通過解析文檔字符串配置定義工具
@tool 可以選擇性地解析Google Style 文檔字符串,并將文檔字符串組件(例如參數描述)與工具schame的相關部分關聯起來。使用這種方法,需要指定 parse_docstring
代碼如:
@tool(parse_docstring=True) # 解析文檔字符串
def multiply(a: int, b: int) -> int:
"""兩個數字相乘.
Args:
a: 第一個數字
b: 第二個數字
Returns:
兩個數字相乘的結果
"""
return a * b
# 查看工具的具體信息
print(multiply.name)
print(multiply.description)
print(multiply.args)
print(multiply.return_direct)
結果:
# 輸出
multiply
兩個數字相乘.
{'a': {'description': '第一個數字', 'title': 'A', 'type': 'integer'}, 'b': {'description': '第二個數字', 'title': 'B', 'type': 'integer'}}
False
通過大模型的 Tool calling 調用工具
Tool calling 允許聊天模型通過“Tool calling”來響應給定的提示詞。
雖然“Tool calling”這個名字暗示模型正在直接執行某些操作,但實際上并非如此!模型僅生成工具的參數,而是否運行工具(或不運行)取決于用戶。
Tool calling 可以從模型生成結構化輸出,即使您不打算調用任何工具,也可以使用它。該技術是從非結構化文本中提取信息。
如下圖,把用戶輸入的文本,通過大模型的Tool calling提取出了符合工具get_weather的信息。
代碼示例
第一步:定義工具
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
model = ChatOpenAI(
api_key='hk-iwtb1e427',
base_url='https://api.openai-hk.com/v1',
temperature=0
)
print("第一步 :定義工具")
@tool
def multiply(a: int, b: int) -> int:
"""兩個數字相乘."""
return a * b
tools = [multiply]
第二步:把工具綁定到大模型
# Tool binding
print("第二步 :把工具綁定到大模型")
model_with_tools = model.bind_tools(tools)
第三步:大模型 Tool calling
# Tool calling
print("第三步 :大模型Tool calling")
query = "2乘以3"
messages = [HumanMessage(query)]
ai_msg = model_with_tools.invoke(messages)
print(ai_msg)
# 獲取返回的response中工具名稱和調用參數
print("大模型 Tool calling 返回結果 : ",ai_msg.tool_calls)
# [{'name': 'multiplication-tool', 'args': {'a': 2, 'b': 3}, 'id': 'call_2bJbBe74qhuDfg3ZGCu7p9e3', 'type': 'tool_call'}]
messages.append(ai_msg)
第四步:工具的執行(Tool calling 返回需要執行的工具)
print("第四步 :工具的執行")
# 定義所有的工具字典
all_tools = {
"multiply": multiply
}
for tool_call in ai_msg .tool_calls:
selected_tool = all_tools[tool_call["name"].lower()]
tool_msg = selected_tool.invoke(tool_call)
print("工具的執行 返回結果 : ",tool_msg)
messages.append(tool_msg)
# cnotallow='6' name='multiply' tool_call_id='call_CTCJAFlibfN3zhM9jMMStBlp'
print("聊天上下文 :")
print(messages)
第五步:大模型處理工具的返回結果
print("第五步:大模型處理工具的返回結果")
response = model_with_tools.invoke(messages)
print("大模型返回 :",response.content)
# 大模型返回 : 2乘以3的結果是6。
用戶輸入 :2乘以3
大模型返回 : 2乘以3的結果是6。
日志:
本文轉載自 ??AI取經路??,作者: AI取經路
