跳到主要內容
Open In ColabOpen on GitHub

如何為 LLM 和聊天模型新增隨選工具呼叫功能

注意

某些模型已經過微調以進行工具呼叫,並提供專用的工具呼叫 API。 一般來說,此類模型比未經微調的模型更擅長工具呼叫,建議用於需要工具呼叫的用例。 請參閱如何使用聊天模型呼叫工具指南以獲取更多資訊。

先決條件

本指南假設您熟悉以下概念

在本指南中,我們將了解如何為聊天模型新增隨選工具呼叫支援。 如果您使用的模型不原生支援工具呼叫,這是一種調用工具的替代方法。

我們將透過簡單地編寫提示來實現此目的,該提示將使模型調用適當的工具。 這是邏輯圖

chain

設定

我們需要安裝以下套件

%pip install --upgrade --quiet langchain langchain-community

如果您想使用 LangSmith,請取消註解以下內容

import getpass
import os
# os.environ["LANGSMITH_TRACING"] = "true"
# os.environ["LANGSMITH_API_KEY"] = getpass.getpass()

您可以為本操作指南選擇任何給定的模型。 請記住,這些模型中的大多數已經支援原生工具呼叫,因此使用此處顯示的提示策略對於這些模型沒有意義,相反,您應該遵循如何使用聊天模型呼叫工具指南。

pip install -qU "langchain[openai]"
import getpass
import os

if not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter API key for OpenAI: ")

from langchain.chat_models import init_chat_model

model = init_chat_model("gpt-4", model_provider="openai")

為了說明這個想法,我們將透過 Ollama 使用 phi3,它原生支援工具呼叫。 如果您也想使用 Ollama,請按照這些說明進行操作。

from langchain_community.llms import Ollama

model = Ollama(model="phi3")
API 參考:Ollama

建立工具

首先,讓我們建立 addmultiply 工具。 有關建立自訂工具的更多資訊,請參閱本指南

from langchain_core.tools import tool


@tool
def multiply(x: float, y: float) -> float:
"""Multiply two numbers together."""
return x * y


@tool
def add(x: int, y: int) -> int:
"Add two numbers."
return x + y


tools = [multiply, add]

# Let's inspect the tools
for t in tools:
print("--")
print(t.name)
print(t.description)
print(t.args)
API 參考:tool
--
multiply
Multiply two numbers together.
{'x': {'title': 'X', 'type': 'number'}, 'y': {'title': 'Y', 'type': 'number'}}
--
add
Add two numbers.
{'x': {'title': 'X', 'type': 'integer'}, 'y': {'title': 'Y', 'type': 'integer'}}
multiply.invoke({"x": 4, "y": 5})
20.0

建立我們的提示

我們需要編寫一個提示,指定模型可以存取的工具、這些工具的參數以及模型所需的輸出格式。 在這種情況下,我們將指示它輸出 JSON blob 格式 {"name": "...", "arguments": {...}}

from langchain_core.output_parsers import JsonOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import render_text_description

rendered_tools = render_text_description(tools)
print(rendered_tools)
multiply(x: float, y: float) -> float - Multiply two numbers together.
add(x: int, y: int) -> int - Add two numbers.
system_prompt = f"""\
You are an assistant that has access to the following set of tools.
Here are the names and descriptions for each tool:

{rendered_tools}

Given the user input, return the name and input of the tool to use.
Return your response as a JSON blob with 'name' and 'arguments' keys.

The `arguments` should be a dictionary, with keys corresponding
to the argument names and the values corresponding to the requested values.
"""

prompt = ChatPromptTemplate.from_messages(
[("system", system_prompt), ("user", "{input}")]
)
chain = prompt | model
message = chain.invoke({"input": "what's 3 plus 1132"})

# Let's take a look at the output from the model
# if the model is an LLM (not a chat model), the output will be a string.
if isinstance(message, str):
print(message)
else: # Otherwise it's a chat model
print(message.content)
{
"name": "add",
"arguments": {
"x": 3,
"y": 1132
}
}

新增輸出解析器

我們將使用 JsonOutputParser 來解析我們的模型輸出為 JSON。

from langchain_core.output_parsers import JsonOutputParser

chain = prompt | model | JsonOutputParser()
chain.invoke({"input": "what's thirteen times 4"})
API 參考:JsonOutputParser
{'name': 'multiply', 'arguments': {'x': 13.0, 'y': 4.0}}
重要

🎉 太棒了! 🎉 我們現在指示了我們的模型如何請求調用工具。

現在,讓我們建立一些邏輯來實際運行工具!

調用工具 🏃

現在模型可以請求調用工具,我們需要編寫一個可以實際調用工具的函數。

該函數將按名稱選擇適當的工具,並將模型選擇的參數傳遞給它。

from typing import Any, Dict, Optional, TypedDict

from langchain_core.runnables import RunnableConfig


class ToolCallRequest(TypedDict):
"""A typed dict that shows the inputs into the invoke_tool function."""

name: str
arguments: Dict[str, Any]


def invoke_tool(
tool_call_request: ToolCallRequest, config: Optional[RunnableConfig] = None
):
"""A function that we can use the perform a tool invocation.

Args:
tool_call_request: a dict that contains the keys name and arguments.
The name must match the name of a tool that exists.
The arguments are the arguments to that tool.
config: This is configuration information that LangChain uses that contains
things like callbacks, metadata, etc.See LCEL documentation about RunnableConfig.

Returns:
output from the requested tool
"""
tool_name_to_tool = {tool.name: tool for tool in tools}
name = tool_call_request["name"]
requested_tool = tool_name_to_tool[name]
return requested_tool.invoke(tool_call_request["arguments"], config=config)
API 參考:RunnableConfig

讓我們測試一下 🧪!

invoke_tool({"name": "multiply", "arguments": {"x": 3, "y": 5}})
15.0

讓我們整合在一起

讓我們將其整合到一個鏈中,該鏈建立一個具有加法和乘法功能的計算器。

chain = prompt | model | JsonOutputParser() | invoke_tool
chain.invoke({"input": "what's thirteen times 4.14137281"})
53.83784653

返回工具輸入

返回不僅工具輸出而且工具輸入可能會很有幫助。 我們可以使用 LCEL 透過 RunnablePassthrough.assign 分配工具輸出來輕鬆做到這一點。 這將獲取 RunnablePassthrough 組件的任何輸入(假定為字典),並向其新增一個鍵,同時仍然傳遞目前輸入中的所有內容

from langchain_core.runnables import RunnablePassthrough

chain = (
prompt | model | JsonOutputParser() | RunnablePassthrough.assign(output=invoke_tool)
)
chain.invoke({"input": "what's thirteen times 4.14137281"})
API 參考:RunnablePassthrough
{'name': 'multiply',
'arguments': {'x': 13, 'y': 4.14137281},
'output': 53.83784653}

下一步是什麼?

本操作指南顯示了模型正確輸出所有必需工具資訊的「順利路徑」。

實際上,如果您使用更複雜的工具,您將開始遇到來自模型的錯誤,尤其是對於尚未針對工具呼叫進行微調的模型以及功能較弱的模型。

您需要準備好新增策略來改進模型的輸出; 例如:

  1. 提供少量範例。
  2. 新增錯誤處理(例如,捕獲異常並將其回饋給 LLM,要求其更正先前的輸出)。

此頁面是否有幫助?