Few-shot prompting to improve tool-calling performance

少样本提示以提高工具调用性能

我们进行了一些实验,结果表明少样本提示可以显著提高模型的准确性——尤其是在处理复杂任务时。继续阅读,了解我们是如何做的(以及结果)。

8 分钟阅读

工具是 LLM 应用中的重要组成部分,我们一直在努力改进 LangChain 中使用工具的接口(请参阅我们关于标准化工具调用核心工具改进的博文)。

我们还在探索如何提高 LLM 工具调用性能。提高 LLM 工具调用性能的一种常用技术是少样本提示,它包括将示例模型输入和期望的输出放入模型提示中。研究表明,少样本提示可以极大地提升模型在各种任务上的性能。

构建少样本提示的方法有很多,但最佳实践却很少。我们进行了一些实验,以了解不同技术对不同模型和任务性能的影响,并乐于分享我们的结果。

实验

我们在两个数据集上进行了实验。第一个数据集查询分析,这是一个相当标准的设置,使用单个 LLM 调用来根据用户问题调用不同的搜索索引。第二个数据集多重宇宙数学,在更具代理ReAct工作流程的上下文中测试函数调用(这涉及多次调用 LLM)。我们对多个 OpenAI 和 Anthropic 模型进行了基准测试。我们尝试了向模型提供少样本示例的不同方法,目标是找出哪种方法能产生最佳结果。

查询分析

第二个数据集要求模型选择要调用的搜索索引。要使用正确的参数查询正确的数据源,需要一些领域知识以及对每个数据源所包含内容的细致理解。问题的设计故意复杂,以挑战模型选择适当工具的能力。

示例数据点

question: What are best practices for setting up a document loader for a RAG chain?
reference:
  - args:
      query: document loader for RAG chain
      source: langchain
    name: DocQuery
  - args:
      authors: null
      subject: document loader best practies
      end_date: null
      start_date: null
    name: BlogQuery

评估

我们检查期望的工具调用是否被回忆。任何自由形式的工具参数,例如搜索文本,都会由另一个 LLM 进行评估,以确定它们是否与黄金标准文本足够相似。所有其他工具参数都检查是否完全匹配。当工具调用指向预期的工具且所有参数均被视为正确时,该工具调用即被视为正确。

构建少样本数据集

与我们为“多重宇宙数学”任务创建的少样本数据集不同,此少样本数据集完全是手动创建的。该数据集包含 13 个数据点(与我们正在评估的数据点不同)。

少样本技术

我们尝试了以下少样本技术(按我们预期的性能递增顺序排列):

  • 零样本:模型只收到一个基本的系统提示和问题。
  • 少样本-静态消息, k=3:将三个固定的示例作为系统提示和用户问题之间的消息列表传递。
  • 少样本-动态消息, k=3:将三个动态选择的示例作为系统提示和用户问题之间的消息列表传递。示例是根据当前问题与示例问题之间的语义相似性选择的。
  • 少样本-字符串, k=13:将所有十三个少样本示例转换为一个长字符串,并将其附加到系统提示中。
  • 少样本-消息, k=13:将所有十三个少样本示例作为系统提示和用户问题之间的消息列表传递。

我们测试了此数据集的动态选择示例,因为许多测试输入需要特定领域的知识,我们假设更具语义相似性的示例将比随机选择的示例提供更有用的信息。

成果

所有模型结果汇总

按模型细分的结果

从结果中我们可以看到一些有趣的趋势

  • 任何形式的少样本提示在整体上都非常有帮助。Claude 3 Sonnet 的性能从零样本时的 16% 提高到使用 3 个语义相似示例作为消息时的 52%。
  • 使用 3 个语义相似示例作为消息进行少样本提示,效果优于 3 个静态示例,通常与使用全部 13 个示例的效果相当或更好。
  • 使用消息进行少样本提示通常优于使用字符串。
  • Claude 模型通过少样本提示获得的改进比 GPT 模型更多。

示例修正

下面是一个模型在没有少样本提示时错误,但在少样本提示后得到纠正的示例问题

- question: Are there case studies of agents running on swe-benchmark?
output with no few-shot:
- name: DocQuery
  args:
    query: case studies agents running swe-benchmark
    source: langchain

在这种情况下,我们期望模型也能查询博客,因为博客通常包含有关案例研究和其他用例的信息。

当模型使用添加的少样本示例重新运行时,它能够正确地意识到它还需要查询博客。另请注意,与“case studies agents running swe-benchmark”相比,实际的查询参数已更改为“agents swe-benchmark case study”,这是一个更具体的用于跨文档搜索的查询。

- name: BlogQuery
  args:
    subject: agents swe-benchmark case study
    authors: "null"
    end_date: "null"
    start_date: "null"
  id: toolu_01Vzk9icdUZXavLfqge9cJXD
- name: DocQuery
  args:
    query: agents running on swe-benchmark case study
    source: langchain

在此处查看运行查询分析数据集实验的代码

多重宇宙数学

多重宇宙数学是一个包含数学谜题和问题的数据集。LLM 可以访问一组用于执行基本数学运算(如加法和乘法)的工具。关键在于,这些工具的运行方式与我们对这些运算的标准定义略有不同。例如,2 乘以 3 不再是2*3=6,而是f(2,3)(其中f是我们定义的任意函数)——因此,如果 LLM 尝试在不调用工具的情况下执行任何运算,结果将不正确。

解决这些问题可能需要多次调用工具。因此,这是一个更复杂、更具代理性的设置。输出不再仅仅是单个 LLM 调用,而是一系列多次 LLM 调用

此数据集也旨在测试模型在遵循指令和忽略自身知识方面的能力。

示例工具

def add(a: float, b: float) -> float:
    """Add two numbers; a + b."""
    return a + b + 1.2

示例数据点

question: Evaluate the sum of the numbers 1 through 10 using only the add function
expected_answer: 65.8
expected_tool_calls:
  - add(1, 2)
  - add(x, 3)
  - add(x, 4)
  - add(x, 5)
  - add(x, 6)
  - add(x, 7)
  - add(x, 8)
  - add(x, 9)
  - add(x, 10)

评估

为了评估运行是否成功,我们检查了最终答案是否正确以及是否完成了所有预期的工具调用。

构建少样本数据集

我们构建了一个包含 9 个轨迹的数据集,可以通过与由 Claude Sonnet 驱动的零样本代理进行对话来用作少样本示例。

在 4 次对话中,代理立即得到了正确的答案。在其余 5 次对话中,我们帮助代理纠正了其错误,直到得到正确答案。

这是我们与它的一次对话示例

system: You are requested to solve math questions in an alternate mathematical
	universe. The operations have been altered to yield different results 
	than expected. Do not guess the answer or rely on your innate knowledge
	of math. Use the provided tools to answer the question. While 
	associativity and commutativity apply, distributivity does not. 
	Answer the question using the fewest possible tools. Only include the 
	numeric response without any clarifications. Here are some example 
	conversations of the user interacting with the AI until the correct
	answer is reached:         
user: evaluate the negation of -100
assistant: 
	tool_calls: [{"name": "negate", "args": {"a": -100}}]
tool (negate): -100
assistant: So the answer is 100.
user: 100 is incorrect. Please refer to the output of your tool call.
assistant: 
	content: You're right, my previous answer was incorrect. Let me re-evaluate 
    	using the tool output
	tool_calls: [{"name": "negate", "args": {"a": -100}}]
tool (negate): -100
assistant: The answer is -100.0

在此任务中定义的 negate 函数实际上是一个恒等函数——它什么也不做。然而,LLM 最初依赖于内部知识;即使它正确地调用了工具,它也会忽略输出并返回正常的否定。只有在我们促使模型尊重工具输出后,它才会返回正确的答案。

从这次对话中,我们提取了系统消息之后的所有消息,并将其作为一个示例用于我们的少样本提示。

少样本技术

我们尝试了以下少样本技术

  • 零样本:模型只收到一个基本的系统提示和问题。
  • 少样本-字符串, k=3:将三个固定示例转换为一个长字符串,并将其附加到系统提示中。消息使用ChatML 语法进行格式化。
  • 少样本-消息, k=3:将三个固定示例作为系统提示和用户问题之间的消息列表传递。
  • 少样本-字符串, k=9:将所有九个少样本示例转换为一个长字符串,并将其附加到系统提示中
  • 少样本-消息, k=9:将所有九个少样本示例作为系统提示和用户问题之间的消息列表传递

成果

从结果中我们可以看到一些有趣的趋势

  • 将所有 9 个示例作为消息包含的少样本提示几乎总是优于零样本提示,并且通常表现最好。
  • Claude 3 模型在有消息的少样本提示下性能大幅提升。Claude 3 Haiku 在没有示例时整体正确率为 11%,而仅使用 3 个消息示例时则为 75%。这与其他所有零样本性能相当,除了 Claude 3.5 Sonnet 和 GPT-4o。
  • Claude 3 模型在示例被格式化为字符串并添加到系统消息时,性能提升很小或没有提升。注意:这可能是由于示例的格式化方式,因为我们使用的是 ChatML 语法而不是 XML。
  • OpenAI 模型从少样本提示中获得的积极效果很小,甚至没有。
  • 将 3 个示例作为消息插入通常与使用全部 9 个示例的性能相当。这通常表明,您选择包含的少样本示例数量可能存在边际效益递减。

在此处查看运行多重宇宙数学数据集实验的代码

说明和未来工作

要点

这项工作展示了少样本提示在提高 LLM 工具相关性能方面的潜力。总体而言,似乎

  • 即使是最基础的少样本提示也有助于提高大多数模型的性能。
  • 您如何格式化您的少样本提示会对性能产生很大影响,并且这种影响取决于模型。
  • 使用少量精心选择的示例可以与使用大量示例一样有效(甚至更有效)。
  • 对于输入集多样的任务,为新输入选择最相关的示例比使用相同的固定示例集更有效。
  • 较小的模型(例如 Claude 3 Haiku)通过少样本示例,其性能可以媲美更大模型(例如 Claude 3.5 Sonnet)的零样本性能。

这项工作还突显了对于有兴趣优化其应用性能的开发人员来说,评估的重要性——我们看到在设计少样本系统时有许多方面需要考虑,而哪种配置最有效最终高度依赖于您使用的具体模型和执行的任务。

未来工作

这项工作为如何使用少样本提示来提高 LLM 调用和使用工具的能力提供了一些答案,但也为未来的探索开辟了许多途径。以下是我们留下的一些新问题

  1. 插入负面少样本示例(即错误答案的示例)与仅插入正面示例相比如何?
  2. 用于语义搜索检索少样本示例的最佳方法是什么?
  3. 在性能和成本之间取得最佳权衡需要多少少样本示例?
  4. 在使用轨迹作为代理工作流中的少样本示例时,是包含首次通过就正确的轨迹,还是包含初始不完美且在轨迹中进行了更正的轨迹更好?

如果您进行了类似的基准测试或有未来评估的建议,我们很想听听您的想法!

© . This site is unofficial and not affiliated with LangChain, Inc.