导语
Langchain团队进行了一些实验,结果表明few-shot提示可以显著提高模型的准确性,尤其是对于复杂的任务更为明显。
工具是LLM应用程序的重要组成部分,LangChain团队一直在努力改善LangChain调用工具的接口。此外,他们还一直在探索如何提高LLM调用工具的性能。改进LLM工具调用的一种常见技术方案是使用few-shot prompting,需要将示例模型输入和所属输出放入模型提示词中。研究表明,这种方法可以极大地提高模型在各种任务上的性能。
构建few-shot提示的方法很多,但是非常出色的却比较少。LangChain团队进行了一些实验,研究了不同技术如何影响模型和任务的性能,下面来看一下他们的方法和成果。
实验过程
LangChain团队对两个数据集进行了实验。第一个是Query Analysis,这是一个非常标准的设置,其中使用对LLM的单个调用来根据human question调用不同的搜索索引。第二个是Multiverse Math,测试在代理ReAct工作流上下文中的function calling(这涉及到对LLM的多次调用)。
LangChain团队对多个OpenAI和Anthropic模型进行基准测试。他们尝试用不同的方式为模型提供few-shot示例,目的是看看哪种方法能产生最佳结果。
Query Analysis
第二个数据集要求模型选择调用哪些搜索索引。要用正确的参数查询正确的数据源,需要一些领域知识和对每个数据源中内容类型的细微理解。这些问题刻意设计得很复杂,以便在选择合适的工具时挑战模型。
示例数据:
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评估,以确保它们是否与黄金标准文本足够相似。检查所有其他工具参数是否完全匹配。如果工具调用是对预期工具的调用,并且所有参数都被认为是正确的,则该工具调用是正确的。
构建few-shot数据集
和为Multiverse Math任务创建的few-shot据集不同,这个few-shot数据集完全是手工创建的。数据集包含13个数据点,而且与正在评估的数据点也是不同的。
few-shot技术
LangChain团队尝试了以下few-shot技术:
- zero-shot:仅向模型提供基本的系统提示和问题
- Few-shot-static-msgs, k=3:三个固定示例作为system prompt和human question之间的消息列表传入
- Few-shot-dynamic-msgs, k=3:三个动态选择的示例作为system prompt和human question之间的消息列表传递进来。基于当前问题和示例问题之间的语义相似度选择示例
- Few-shot-str, k=13 :所有 13 个 Few-shot 示例都被转换为一个长字符串,并附加到系统提示词中
- Few-shot-msgs, k=13 :所有 13 个 Few-shot 示例都作为system prompt和human question之间的消息列表传入
LangChain团队为这个数据集测试了动态选择的示例,因为许多测试输入需要特定于领域的知识,并且他们假设语义上更相似的示例将比随机选择的示例提供更有用的信息。
实验结果
所有模型的汇总结果:
按模型划分的结果:
从结果可以看到一些有趣的趋势:
- 任何类型的few-shotting都有相当大的帮助。 Claude 3 Sonnet 的性能在使用zero-shot时是 16%,当使用 3 个语义相似的示例作为信息时上升到了52%
- 使用3个语义相似的示例作为信息的few-shotting比使用3个静态示例的要好,并且通常与使用全部13个示例时一样好或更好
- 使用few-shotting比直接使用文字描述效果要好
- 与 GPT 模型相比,Claude 模型使用few-shotting时提升更明显
修正示例
下面是一个模型在没有few-shotting时出错而在加入few-shotting时得到纠正的示例:
- 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
在这种情况下,我们期望模型也查询博客,因为博客通常包含有关案例研究和其他用例的信息。
当模型使用添加的few-shotting重新运行时,它能够正确地意识到它还需要查询博客。还要注意,在添加few-shotting之后,实际查询参数是如何从“case studies agents running swei -benchmark”更改为“agents swei -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
可以从下面链接查看Query Analysis运行实验的代码:
https://langchain-ai.github.io/langchain-benchmarks/notebooks/tool_usage/query_analysis.html?ref=blog.langchain.dev
Multiverse Math
Multiverse Math是数学难题和问题的数据集。 LLM 可以访问一组用于执行加法和乘法等基本数学运算的tools。需要注意的是这些工具的行为与我们对这些操作的标准定义略有不同,例如,2 乘以 3 不再是 2*3=6 ,而是 f(2,3) ,其中 f 是我们定义的任意函数,所以如果LLM尝试在不调用tools的情况下执行任何操作,结果将不正确。
解决这些问题可能涉及对工具的多次调用。因此,这是一个更复杂的代理设置。输出不再是单个LLM调用(single LLM call),而是多个LLM调用(multiple LLM calls)的轨迹。
该数据集还旨在测试模型遵循指令并忽略其只有知识的程度。
Example tool
def add(a: float, b: float) -> float:
"""Add two numbers; a + b."""
return a + b + 1.2
Example datapoint
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)
评估
为了评估运行是否成功,需要检查最终答案是否正确以及是否进行了所有预期的工具调用
构建few-shot数据集
LangChain团队构建了一个包含 9 个轨迹的数据集,通过与由 Claude Sonnet 提供支持的zero-shot agent进行对话,可以将其用作few-shot示例。
在其中 4 次对话中,agent立即得到了正确答案。在剩下的5次对话中,开发人员帮助agent纠正错误,直到得到正确答案。
下面是实例:
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起初依赖于其内部知识,即使它正确地调用了工具,它也会忽略工具输出并返回数据。只有在我们促使模型尊重工具输出之后,它才会返回正确的答案。
从这次对话中,开发人员提取了system message之后的所有信息,并将其用作few-shot中的一个示例。
开发团队尝试了以下few-shot:
- zero-shot:仅向模型提供基本的系统提示和问题
- Few-shot-str, k=3:将三个固定示例转换为一个长字符串,附加到系统提示词中。消息使用ChatML syntax进行格式化
- Few-shot-msgs,k=3:三个固定示例作为system prompt和human question之间的消息列表传入
- Few-shot-str, k=9:所有 9 个 Few-shot 示例都转换为一个长字符串,附加到system prompt中
- Few-shot-msgs,k = 9:所有9个few-shot示例都作为system prompt和human question之间的消息列表传入
Results
从结果看到一些有趣的趋势:
- 信息中包含所有 9 个示例的few-shot几乎总是优于zero-shot,并且通常表现最好。
- Claude 3模型在使用了few-shot时得到显著提升。Claude 3 Haiku在没有示例的情况下达到了11%的总体正确性,而增加了3个例子作为信息的情况下达到了75%。
- 当示例被格式化为字符串并添加到系统消息中时,Claude 3模型几乎没有改进,或者根本没有改进。这可能是由于示例的格式化方式,因为我们使用的是ChatML syntax而不是XML。
- OpenAI 模型从few-shotting中得到的积极影响要小得多。
- 插入 3 个示例作为信息往往与使用全部 9 个示例具有差不多的性能。这表明选择包含的few-shot示例的数量可能会带来收益递减。
Multiverse Math 数据集上运行实验的代码可以查看下面的链接:
https://langchain-ai.github.io/langchain-benchmarks/notebooks/tool_usage/multiverse_math_benchmark.html?ref=blog.langchain.dev