如何为LLM和聊天模型添加工具调用功能

250 阅读3分钟

如何为LLM和聊天模型添加工具调用功能

引言

在自然语言处理和生成领域,大型语言模型(LLM)及其聊天模型已经展现了巨大的潜力。然而,这些模型在某些情况下需要调用外部工具来实现特定功能。虽然一些模型已经被调优以支持工具调用,但对于不具备这一原生支持的模型,我们可以通过编写合适的提示语(prompt)来实现这一功能。本文将详细介绍如何为LLM和聊天模型添加工具调用功能。

主要内容

安装必要的包

首先,我们需要安装LangChain以及相关工具包:

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

设置模型环境

我们将选择一些现有的模型,如OpenAI、Anthropic、Azure等,并设置相应的API密钥。在这里,我们以OpenAI的GPT-4为例:

pip install -qU langchain-openai

import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass()

from langchain_openai import ChatOpenAI

model = ChatOpenAI(model="gpt-4")

创建自定义工具

接下来,我们将创建两个简单的工具:加法和乘法。

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]

# 查看工具描述
for t in tools:
    print("--")
    print(t.name)
    print(t.description)
    print(t.args)

创建提示语

我们需要编写一个提示语,明确模型可以使用的工具及其参数,并约定输出格式。

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)

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"})

if isinstance(message, str):
    print(message)
else:
    print(message.content)

添加输出解析器

我们将使用JsonOutputParser解析模型的输出。

from langchain_core.output_parsers import JsonOutputParser

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

调用工具函数

我们需要一个函数来执行工具调用,根据模型返回的工具名称和参数来调用对应的工具。

from typing import Any, Dict, Optional, TypedDict
from langchain_core.runnables import RunnableConfig

class ToolCallRequest(TypedDict):
    name: str
    arguments: Dict[str, Any]

def invoke_tool(tool_call_request: ToolCallRequest, config: Optional[RunnableConfig] = None):
    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)

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

整合链式调用

最后,我们将所有步骤整合到一个链式调用中。

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

返回工具输入

有时我们希望返回不仅是工具的输出,还有输入,可以通过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"})

常见问题和解决方案

  1. 模型输出不符合预期格式

    • 解决方案: 提供少量示例,增加提示语的明确性。
  2. 工具调用失败

    • 解决方案: 添加错误处理机制,捕获异常并反馈给模型以纠正输出。

总结和进一步学习资源

通过本文的介绍,我们学习了如何为不具备原生支持工具调用的LLM和聊天模型添加工具调用功能。希望你能根据具体需求进行实验和调整。

参考资料

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---