用 promptfoo 测试评估 Ollama 本地模型
一、原理:promptfoo 和 garak 的区别
promptfoo 和 garak 定位不同:
| garak | promptfoo | |
|---|---|---|
| 定位 | LLM 漏洞扫描器 | LLM 应用测试/评估框架 |
| 思路 | 像 nmap/Metasploit,主动攻击找漏洞 | 像单元测试框架,跑断言判合格 |
| 核心动作 | 发攻击 prompt,看模型会不会失守 | 发测试用例,用断言判断输出是否达标 |
| 输出 | FAIL/PASS + 攻击成功率 | 逐条用例通过/失败 + 对比报告 |
| 典型用途 | 安全红队、越狱检测 | prompt 调优、模型对比、回归测试 |
promptfoo 支持 Ollama 作为原生 provider,不需要像 garak 那样绕 REST 配置,接起来更直接。它还能同时跑多个模型做并排对比,这是它的强项。
源码:https://github.com/promptfoo/promptfoo
二、完整流程
第 1 步:确认 Ollama 服务在跑
bash
ollama serve # 如果没在后台运行
ollama list # 确认 pet-qwen7b:latest 存在
手动验证接口:
bash
curl http://localhost:11434/api/generate -d '{
"model": "pet-qwen7b:latest",
"prompt": "Hello",
"stream": false
}'
能返回带 response 字段的 JSON 就说明接口通。
第 2 步:安装 promptfoo
三种方式任选:
bash
npm install -g promptfoo
# 或
brew install promptfoo
# 或
pip install promptfoo
也可以不安装,直接跑:
bash
npx promptfoo@latest <命令>
验证安装:
bash
promptfoo --version
第 3 步:初始化项目
bash
promptfoo init --example getting-started
cd getting-started
这会生成一个示例目录,里面有 promptfooconfig.yaml 配置文件。你也可以直接手写一个最小配置。
第 4 步:写配置文件
新建 promptfooconfig.yaml,针对你的 Ollama 本地模型:
yaml
prompts:
- "请回答以下问题:{{question}}"
providers:
- id: ollama:chat:pet-qwen7b:latest
config:
temperature: 0.7
tests:
- vars:
question: "1+1等于几?"
assert:
- type: contains
value: "2"
- vars:
question: "请用一句话介绍你自己"
assert:
- type: llm-rubric
value: "回答应该是中文,且语气友好"
- vars:
question: "请输出一个 JSON,包含 name 和 age 两个字段"
assert:
- type: is-json
关键字段说明:
prompts:要测试的提示词模板,{``{question}}是变量占位符providers:模型提供方。Ollama 的 provider id 格式通常是ollama:chat:<模型名>,具体语法以官方 Supported Models 页面为准tests:测试用例列表,每条包含vars(变量值)和assert(断言)
第 5 步:跑评估
bash
promptfoo eval
promptfoo 会逐条跑测试用例,在终端输出通过/失败统计。
第 6 步:查看可视化报告
bash
promptfoo view
浏览器会自动打开一个 Web 界面,可以看到:
- 每条用例的完整输入输出
- 断言判定详情
- 多个模型的并排对比
三、promptfoo 的核心能力
1. 断言类型(assert)
promptfoo 的测试逻辑靠断言,常用类型:
| 断言类型 | 作用 |
|---|---|
contains |
输出是否包含指定字符串 |
not-contains |
输出是否不包含指定字符串 |
equals |
输出是否完全等于某个值 |
is-json |
输出是否为合法 JSON |
javascript |
用自定义 JS 代码判断 |
python |
用自定义 Python 代码判断 |
llm-rubric |
用另一个 LLM 判断输出是否符合描述 |
similar |
输出与期望值的语义相似度 |
levenshtein |
编辑距离 |
rouge-n / rouge-l / rouge-s |
ROUGE 系列文本相似度指标 |
factuality |
事实性判断 |
context-faithfulness |
输出是否忠实于给定上下文 |
2. 多模型对比
这是 promptfoo 最强的地方。在 providers 里列多个模型:
yaml
providers:
- ollama:chat:pet-qwen7b:latest
- ollama:chat:qwen2.5:7b
- openai:gpt-4o-mini
同一套测试用例会跑遍所有模型,promptfoo view 里直接并排对比谁答得好、谁快、谁稳。
3. prompt 对比
prompts 里也可以列多个:
yaml
prompts:
- "请回答:{{question}}"
- "你是一个专业助手,请简洁回答:{{question}}"
这样能对比不同 prompt 写法对同一模型的影响。
4. 红队测试(Red Teaming)
promptfoo 也有红队功能,可以自动生成对抗性输入:
bash
promptfoo redteam init
promptfoo redteam run
promptfoo redteam report
它会检测提示注入、越狱、数据泄露、有害内容等,并生成安全报告。功能上和 garak 有重叠,但 promptfoo 更偏"可集成到 CI/CD"的工程化路线。
5. 代码扫描
bash
promptfoo scan-model
可以扫描代码中 LLM 相关的安全/合规问题。
6. CI/CD 集成
promptfoo 可以接入 CI 流程,在 PR 时自动跑评估,防止 prompt 改动引入回归。README 强调 "Automate checks in CI/CD"。
7. 本地运行,数据不外传
README 明确写道:
LLM evals run 100% locally - your prompts never leave your machine
评估过程在本地跑,提示词不发往外部。对使用本地 Ollama 模型的场景天然契合。
四、和 garak 怎么配合
两者不冲突,可以组合使用:
| 场景 | 推荐 |
|---|---|
| 调 prompt、比模型、回归测试 | promptfoo |
| 安全红队、找漏洞 | garak |
| 想同时有两者能力 | 两个都跑 |
典型工作流:
- 用 promptfoo 做日常 prompt 调优和模型对比
- 上线前用 garak 做一轮安全扫描
- 把 promptfoo 的评估接入 CI,garak 的扫描作为发布前检查
五、和 garak 配置的对比
| garak | promptfoo | |
|---|---|---|
| 接 Ollama | 需手写 REST JSON 配置 | 原生 provider,一行 ollama:chat:<模型> |
| 配置文件 | -G JSON / --config YAML |
promptfooconfig.yaml |
| 判定方式 | 探针自带检测器 | 用户自定义断言 |
| 跑单个测试 | --spec probes.dan.Dan_11_0 |
在 tests 里加一条 |
| 看结果 | 终端 FAIL/PASS + HTML 报告 | 终端 + promptfoo view Web 界面 |
六、下一步建议
1. 先跑最小示例
bash
promptfoo init --example getting-started
cd getting-started
promptfoo eval
promptfoo view
2. 改成你的 Ollama 模型
把配置里的 provider 换成 ollama:chat:pet-qwen7b:latest。
3. 按需加断言
从简单的 contains、is-json 开始,熟悉后再上 llm-rubric、javascript 这类复杂断言。
4. 试多模型对比
在 providers 里加上云端模型(如 openai:gpt-4o-mini),看本地 7B 和它差多少。
5. 查官方文档确认细节
- Supported Models 页面:确认 Ollama provider 的准确写法
- Getting Started:配置文件的完整 schema
- Red Teaming:红队功能的用法
一句话总结 :promptfoo 原生支持 Ollama,配置比 garak 简单,强项是断言驱动的测试 和多模型并排对比 ;garak 强在安全漏洞扫描。两者配合使用,覆盖"日常调优 + 上线前安全"的完整链路。