Skip to main content

测试 LLM 链

提示链是一种常见的模式,用于通过 LLM 执行更复杂的推理。它被 LangChain 等库使用,OpenAI 也通过 OpenAI 函数 提供了内置支持。

“链”由一系列按顺序(有时是条件性地)执行的 LLM 提示定义。每次 LLM 调用的输出都会被解析/操作/执行,然后将结果输入到下一个提示中。

本页解释了如何测试 LLM 链。从高层次来看,你有以下选项:

  • 将链分解为单独的调用,并测试这些调用。如果你的测试策略更接近单元测试,而不是端到端测试,这很有用。

  • 使用单个输入和单个输出测试完整的端到端链。如果你只关心最终结果,而不关心 LLM 链是如何实现的,这很有用。

单元测试 LLM 链

如上所述,最简单的测试方法是逐个提示进行测试。这可以通过基本的 promptfoo 配置 轻松完成。

运行 npx promptfoo@latest init chain_step_X 为链的第一步创建测试框架。为该步骤配置测试用例后,为第二步创建一组新的测试用例,依此类推。

端到端测试 LLM 链

使用脚本提供者

要测试你的链式 LLM,请提供一个脚本,该脚本接受提示输入并输出链的结果。这种方法与语言无关。

在这个示例中,我们将通过创建一个接受提示并生成输出的脚本来测试 LangChain 的 LLM Math 插件:

# langchain_example.py

import sys
import os

from langchain import OpenAI
from langchain.chains import LLMMathChain

llm = OpenAI(
temperature=0,
openai_api_key=os.getenv('OPENAI_API_KEY')
)

llm_math = LLMMathChain(llm=llm, verbose=True)

prompt = sys.argv[1]
llm_math.run(prompt)

这个脚本设置为我们可以这样运行它:

python langchain_example.py "What is 2+2?"

现在,让我们配置 promptfoo 使用一堆测试用例运行这个 LangChain 脚本:

prompts: prompt.txt
providers:
- openai:chat:gpt-4o
- exec:python langchain_example.py
tests:
- vars:
question: What is the cube root of 389017?
- vars:
question: If you have 101101 in binary, what number does it represent in base 10?
- vars:
question: What is the natural logarithm (ln) of 89234?
- vars:
question: If a geometric series has a first term of 3125 and a common ratio of 0.008, what is the sum of the first 20 terms?
- vars:
question: A number in base 7 is 3526. What is this number in base 10?
- vars:
question: If a complex number is represented as 3 + 4i, what is its magnitude?
- vars:
question: What is the fourth root of 1296?

有关配置的深入了解,请参阅 指南。请注意以下几点:

  • prompts: prompt.txt 只是一个包含 {{question}} 的文件,因为我们直接将问题传递给提供者。
  • providers: 我们列出了 GPT-4,以便将其输出与 LangChain 的 LLMMathChain 进行比较。我们还使用 exec 指令让 promptfoo 在评估中运行 Python 脚本。

在这个示例中,最终结果是 GPT-4 与 LangChain 数学性能的并排比较:

langchain eval

查看 Github 上的完整示例

使用自定义提供者

为了更细粒度的控制,使用 自定义提供者

自定义提供者是一个定义了 callApi 函数的简短 Javascript 文件。此函数可以调用你的链。即使你的链不是用 Javascript 实现的,你也可以编写一个自定义提供者,该提供者会调用 Python。

在下面的示例中,我们设置了一个自定义提供者,该提供者使用提示作为参数运行 Python 脚本。Python 脚本的输出是链的最终结果。

const { spawn } = require('child_process');

class ChainProvider {
id() {
return 'my-python-chain';
}

async callApi(prompt, context) {
return new Promise((resolve, reject) => {
const pythonProcess = spawn('python', ['./path_to_your_python_chain.py', prompt]);

let output = '';

pythonProcess.stdout.on('data', (data) => {
output += data.toString();
});

pythonProcess.stderr.on('data', (data) => {
reject(data.toString());
});

pythonProcess.on('close', (code) => {
if (code !== 0) {
reject(`python script exited with code ${code}`);
} else {
resolve({
output,
});
}
});
});
}
}

module.exports = ChainProvider;

请注意,如果你对这门语言感到舒适,你总是可以直接在JavaScript中编写逻辑。

现在,我们可以设置一个指向 chainProvider.js 的 promptfoo 配置:

prompts:
- file://prompt1.txt
- file://prompt2.txt
providers:
- './chainProvider.js'
tests:
- vars:
language: French
input: Hello world
- vars:
language: German
input: How's it going?

promptfoo 会将完整的构造提示传递给 chainProvider.js 和 Python 脚本,并替换变量。在这种情况下,脚本将被调用 # 提示 * # 测试用例 = 2 * 2 = 4 次。

使用这种方法,你可以端到端地测试你的 LLM 链,在 网页视图 中查看结果,设置 持续测试,等等。

检索增强生成 (RAG)

有关测试 RAG 管道的更多详细信息,请参阅 RAG 评估

其他提示

要引用先前测试用例的输出,请使用内置的 _conversation 变量