Promptfoo 测试用例编写指南
1. 概念
1.1 什么是 Promptfoo
Promptfoo 是一个用于测试和评估 LLM(大语言模型)Prompt 质量的工具。它允许开发者:
- 定义多个测试用例验证 Prompt 输出
- 支持确定性断言和 LLM 评判两种验证方式
- 通过配置文件管理测试套件
1.2 核心配置文件
yaml
# promptfooconfig.yaml 基本结构
prompts:
- file://prompts/prompt_from_doc.py:main # prompt 文件
providers:
- python:./providers/llm.py # LLM 提供商
tests:
- name: 测试用例名称
description: 测试描述
vars: # 变量配置
doc_id: "1"
assert: # 断言配置
- type: icontains
value: 期望包含的内容
2. 用例的编写维度
2.1 格式规范维度
检查输出是否符合预定的格式要求:
| 检查项 | 说明 | 示例 |
|---|---|---|
| 标签结构 | 输出必须包含特定 XML 标签 | <brief>...</brief> |
| 标题完整性 | 必须包含规定的章节标题 | 包含"综合评估摘要"等5个标题 |
| 开头结尾 | 必须以特定内容开头/结尾 | 以 <brief> 开头 |
示例配置:
yaml
- name: brief标签结构验证
assert:
- type: regex
value: '^<brief>' # 必须以 <brief> 开头
- type: contains
value: '</brief>' # 必须包含结束标签
2.2 内容维度
检查输出内容是否符合质量标准:
| 检查项 | 说明 | 示例 |
|---|---|---|
| 分数计算 | 总分等于各维度之和 | 35+35+15+15=100 |
| 分数范围 | 评分在预期范围内 | 60-80分 |
| 评级一致性 | 分数与评级匹配 | 60-69分对应C级 |
| 关键内容 | 包含必要的描述性内容 | 必须包含问题清单 |
2.3 正向用例 vs 负向用例
正向用例(应该通过的测试)
检测输出符合预期的正向标准:
yaml
# 正向用例:检测输出包含预期内容
- name: 标题完整性检查
assert:
- type: contains
value: "综合评估摘要" # 应该包含此标题
- type: contains
value: "关键问题清单" # 应该包含此内容
负向用例(不应该出现的测试)
检测输出不应该包含的负向内容:
yaml
# 负向用例:检测输出不包含错误内容
- name: 无错误标记检查
assert:
- type: icontains
value: "错误:" # 不应该包含错误标记
- type: icontains
value: "暂未开发" # 不应该包含未完成标记
3. Promptfoo 支持的测试方法
3.1 确定性断言(Deterministic Assertions)
不需要调用 LLM,直接通过规则匹配验证输出,执行速度快:
3.1.1 字符串匹配类
| 类型 | 说明 | 示例 |
|---|---|---|
contains |
输出包含指定字符串(区分大小写) | value: "综合评估摘要" |
icontains |
输出包含指定字符串(不区分大小写) | value: "综合评估摘要" |
equals |
输出完全等于指定值 | value: "A级" |
contains-any |
输出包含数组中任一元素 | value: ["A级", "B级"] |
3.1.2 模式匹配类
| 类型 | 说明 | 示例 |
|---|---|---|
regex |
输出匹配正则表达式 | value: '^<brief>' |
contains-json |
输出包含有效 JSON | value: {required: [lat]} |
is-json |
输出是完全有效的 JSON | 无需 value 参数 |
3.1.3 自定义函数类
| 类型 | 说明 | 示例 |
|---|---|---|
javascript |
自定义 JS 函数验证 | 提取分数计算验证 |
python |
自定义 Python 函数验证 | 读取文件内容验证 |
webhook |
发送到 webhook 进行验证 | 外部服务验证 |
3.2 LLM 评判器(Model-Graded Assertions)
使用另一个 LLM 来评估输出质量,适合语义理解类的验证:
3.2.1 llm-rubric
通用的 LLM 评分工具,根据自定义标准评估输出:
yaml
- name: 分数校验
assert:
- type: llm-rubric
provider: python:./providers/llm.py # 指定评判用的LLM
value: |
请仔细检查评估报告中的分数计算是否正确。
评分体系:需求符合性35+架构设计合理性35+设计完整性15+可实施性15=100分
输出要求:
- 如果分数计算完全正确,输出PASS
- 如果发现任何分数计算错误,输出FAIL
3.2.2 其他 Model-Graded 类型
| 类型 | 说明 |
|---|---|
similar |
语义相似度评估(需设置 threshold) |
model-graded-closedqa |
LLM 判断答案是否正确 |
model-graded-factuality |
LLM 评估事实准确性 |
model-graded-safety |
LLM 评估安全性 |
3.3 测试方法选择指南
┌─────────────────────────────────────────────────────────┐
│ 如何选择测试方法 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ 格式/结构类 │ │ 语义/质量类 │ │
│ │ 精确匹配 │ │ 需要理解 │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ regex │ │ llm-rubric │ │
│ │ contains │ │ model-graded│ │
│ │ equals │ │ similar │ │
│ └─────────────┘ └─────────────┘ │
│ │
│ 确定性断言(快) LLM 评判(慢但灵活) │
│ │
└─────────────────────────────────────────────────────────┘
选择建议:
- 格式验证 → 使用
regex、contains、is-json - 分数计算 → 使用
javascript或llm-rubric - 语义理解 → 使用
llm-rubric - 网络限制环境 → 必须指定内部 LLM 作为评判器
4. 完整示例
yaml
# promptfooconfig.yaml
prompts:
- file://prompts/prompt_from_doc.py:main
providers:
- id: python:./providers/llm.py
label: LLM
tests:
# 正向用例 - 格式规范
- name: brief标签结构验证
vars:
doc_id: "1"
assert:
- type: regex
value: '^<brief>'
- type: contains
value: '</brief>'
# 正向用例 - 内容完整性
- name: 标题完整性检查
vars:
doc_id: "1"
assert:
- type: contains
value: "综合评估摘要"
- type: contains
value: "分阶段评估详情"
- type: contains
value: "关键问题清单"
- type: contains
value: "改进建议"
- type: contains
value: "归档决策建议"
# 正向用例 - 分数验证(LLM评判)
- name: 分数校验
vars:
doc_id: "1"
assert:
- type: llm-rubric
provider: python:./providers/llm.py
value: |
检查分数计算是否正确。
输出PASS或FAIL。
# 正向用例 - 范围验证(LLM评判)
- name: truth分数范围校验
vars:
doc_id: "2"
assert:
- type: llm-rubric
provider: python:./providers/llm.py
value: |
验证评分是否在60-80分范围内。
输出PASS或FAIL。
output:
- type: table
filename: results/table.html
5. 最佳实践
- 分层验证:先用确定性断言验证格式,再用 LLM 评判验证内容质量
- 指定评判器 :在网络受限环境,为
llm-rubric显式指定内部 LLM provider - 正负结合:同时编写正向用例(应该通过)和负向用例(应该失败)
- 结果可视化:配置 HTML/JSON 输出,便于查看测试结果