工具是 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:所有 13 个少样本示例都被转换成一个长字符串,该字符串被附加到系统提示。
- 少样本-消息,k=13:所有 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
在这种情况下,我们希望模型也能查询博客,因为博客通常包含关于案例研究和其他用例的信息。
当模型在添加了少样本示例后重新运行时,它能够正确地认识到还需要查询博客。还要注意,在使用少样本提示后,实际查询参数从“案例研究代理运行 swe-benchmark”更改为“代理 swe-benchmark 案例研究”,这是一个更具体的跨文档搜索查询。
- 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
在这个任务中定义的取反函数实际上是一个恒等函数——它什么也不做。然而,LLM 最初依赖于内部知识;即使它正确地调用了工具,它也会忽略输出并返回正常的取反结果。只有在我们促使模型尊重工具输出后,它才会返回正确的答案。
从这次对话中,我们提取了系统消息之后的所有消息,并将它用作我们少样本提示中的一个示例。
少样本技术
我们尝试了以下少样本技术
- 零样本:仅为模型提供基本系统提示和问题。
- 少样本-字符串,k=3:三个固定示例被转换成一个长字符串,该字符串被附加到系统提示。这些消息使用ChatML 语法 格式化。
- 少样本-消息,k=3:三个固定示例作为系统提示和人类问题之间消息列表传递。
- 少样本-字符串,k=9:所有 9 个少样本示例被转换成一个长字符串,该字符串被附加到系统提示。
- 少样本-消息,k=9:所有 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 调用和使用工具能力的答案,但也开辟了一些值得未来探索的途径。以下是一些我们留下的新问题
- 插入负面少样本示例(即错误答案的示例)与仅插入正面示例相比如何?
- 什么是用于少样本示例的语义搜索检索的最佳方法?
- 为了在性能和成本之间取得最佳平衡,需要多少少样本示例?
- 在将轨迹用作代理性工作负载中的少样本示例时,最好包括在第一次尝试中就正确的轨迹,还是在初始阶段不完美,并且作为轨迹的一部分进行了修正的轨迹?
如果你已经进行过类似的基准测试,或者有想法进行未来的评估,我们非常乐意听到你的想法!