Promptfoo:LLM 应用的提示词评测与红队测试工具|部署与使用全指南
适用版本段:本文基于 promptfoo npm 最新版
0.125.1(GitHub Release 发布于 2026-10-25)撰写,对应官方文档 "Last updated on Oct 25, 2026"。仓库promptfoo/promptfoo约 26.4k star、2.6k fork,main 分支当日仍有提交(2026-10-26),属于高活跃度项目。许可证为 MIT。需注意:README 顶部公告写明 "Promptfoo is now part of OpenAI",但项目仍然开源且保持 MIT 许可。

Promptfoo 是一个面向 LLM(Large Language Model)应用的评测(eval)与红队(red team)测试工具:你用一份 promptfooconfig.yaml 描述「提示词 × 模型 × 测试用例 × 断言」,它就把所有组合跑一遍,给出可量化的通过率、分数、成本与延迟,并在本地浏览器里以矩阵形式对比输出。它同时能自动生成上千条对抗性输入,对你的 AI 应用做漏洞扫描(越狱、提示注入、PII 泄露、越权等),产出合规风险报告。核心卖点是:纯本地运行、 prompts 不出机器、可接入 CI/CD 做质量门禁。

一、项目介绍与适用场景
1.1 它是什么
形态:一个 Node.js CLI(
promptfoo)+ 一个本地 Web viewer + 一个可自托管的 Express 服务端(Docker 镜像)。输入:YAML 配置(prompts / providers / tests / redteam 等)。
输出:终端表格、JSON / YAML / CSV / JSONL / HTML / JUnit XML 报告、Web 可视化矩阵、红队风险报告。
本质:把「改 prompt → 凭感觉上线」变成「改 prompt → 跑回归 → 看指标」的工程化流程。
1.2 技术定位
1.3 适合谁
正在做 RAG、Agent、聊天机器人的应用开发团队:需要在改 prompt / 换模型时防止回归。
平台 / SRE 团队:需要在 CI 里给 LLM 相关改动加质量门禁与成本门禁。
安全团队(AppSec):需要对 AI 应用做 OWASP LLM Top 10、NIST AI RMF、EU AI Act 对齐的漏洞扫描。
模型选型者:同一批测试集,横向对比多家模型的评分 / 延迟 / 成本。
个人开发者:本地
npx promptfoo@latest一条命令就能跑,无需注册账号。
1.4 不适合的场景
需要多人协作、RBAC、SSO、共享数据库的团队级 SaaS:官方自托管镜像明确写着 "not recommended for production use cases"(SQLite、单副本、无鉴权、无 SSO),这类需求要走 Enterprise 平台。
需要训练 / 微调模型:它只做推理侧的评测与扫描,不做训练。
完全没有 API key 的纯离线场景:大多数断言需要调用 LLM,本地模型(Ollama / llama.cpp / vLLM)可以替代但配置成本更高。
把这个 Docker 镜像当多租户服务对外售卖:自托管版本不具备多租户能力。
二、核心功能逐条拆解
多提示词 × 多模型矩阵评测:
prompts与providers做笛卡尔积,tests提供变量,一次性跑出完整矩阵;Web viewer 里逐格对比,配合 "Pass / Fail / Score / Comment" 人工标注。丰富的断言类型:40+ 确定性断言(equals、contains-any/all、regex、is-json、is-sql、is-xml、latency、cost、perplexity、levenshtein、rouge-n、bleu、meteor、tool-call-f1、trace-* 等)与 16 类模型辅助断言(llm-rubric、similar、classifier、moderation、factuality、g-eval、answer-relevance、context-faithfulness / recall / relevance 等)。
not-前缀取反:几乎所有断言类型都能加not-前缀(如not-equals、not-regex、not-contains),用来断言"不该出现什么"。加权与命名指标:每条
assert可设weight,同名metric会被聚合;还能用derivedMetrics基于命名分数算出 F1、平均值等复合指标。断言集(assert-set):把多条断言分组并设
threshold,例如"成本与延迟满足其一即可通过"(threshold 0.5)。缓存与并发控制:默认磁盘缓存(
~/.promptfoo/cache,TTL 14 天),429 自动指数退避,evaluateOptions.maxConcurrency默认 4,delay可限流,--no-cache可强制穿透。红队测试(red teaming):
redteam init → run → report三步走,自动生成数百条对抗输入(jailbreak、prompt injection、PII、BOLA/BFLA、competitors 等 50+ 插件),按严重级别(critical / high / medium / low)生成漏洞报告。合规框架映射:
redteam.frameworks可选owasp:llm、owasp:api、owasp:agentic、nist:ai:measure、mitre:atlas、eu:ai-act、iso:42001、gdpr、dod:ai:ethics,报告里直接呈现对应合规项。CI/CD 集成:命令行
npx promptfoo@latest eval -o results.junit.xml输出 JUnit;promptfoo/promptfoo-action@v1在 PR 里自动对比改动前后的 prompt 并贴评论。代码扫描(code scanning):
promptfoo code-scans run对仓库做 LLM 相关安全与合规问题的静态扫描。Web viewer 交互分析:支持搜索/正则过滤、按 metric 与 metadata 过滤、对比两次 eval(Compare)、导出 CSV/JSON/DPO JSON/Human Eval YAML/Burp payloads。
结果分享与自托管:
promptfoo share生成分享链接;也可把服务端部署在自己的机器上(ghcr.io/promptfoo/promptfoo),用sharing.apiBaseUrl指向它。

三、全套官方链接
四、硬件与环境前置要求
五、多平台部署步骤
5.1 Linux / macOS(npm 全局安装)
# 1. 确认 Node 版本(必须 >= 22.22.0)
node --version
# 2. 如版本过低,用 nvm 升级
nvm install 24
nvm use 24
# 3. 全局安装
npm install -g promptfoo
# 4. 验证
promptfoo --version
# 5. 初始化一个项目(交互式向导,生成 promptfooconfig.yaml)
promptfoo init
# 6. 也可以用官方示例项目
promptfoo init --example getting-started
cd getting-started
# 7. 配置 API key
export OPENAI_API_KEY=sk-abc123
# 8. 跑评测 + 开 Web viewer
promptfoo eval
promptfoo view
5.2 macOS(Homebrew)
brew install promptfoo
promptfoo --version
promptfoo init --example getting-started
5.3 免安装方式(npx,跨平台,CI 首选)
# 不装全局包,直接跑
npx promptfoo@latest init --example getting-started
cd getting-started
export OPENAI_API_KEY=sk-abc123
npx promptfoo@latest eval
npx promptfoo@latest view
5.4 Windows(PowerShell)
# 确认 Node 版本
node --version
# 全局安装
npm install -g promptfoo
# 验证(若仍有残留路径,说明装了多份)
where.exe promptfoo
# 设置 API key(当前会话)
$env:OPENAI_API_KEY = "sk-abc123"
# 跑评测
promptfoo init
promptfoo eval
promptfoo view
Windows 上 Python provider 的检测顺序(官方文档):provider 的 config.pythonExecutable → PROMPTFOO_PYTHON → Windows 智能探测(where python,过滤 Microsoft Store 存根)→ python -c "import sys; print(sys.executable)" → 依次尝试 python / python3 / py -3 / py。装的是 Microsoft Store 版 Python 时建议显式设置:
$env:PROMPTFOO_PYTHON = "C:\Users\YourName\AppData\Local\Microsoft\WindowsApps\python.exe"
5.5 Docker(官方预构建镜像,用于自托管 Web UI 与结果存储)
官方镜像托管在 GitHub Container Registry,镜像名是
ghcr.io/promptfoo/promptfoo。官方文档未使用 Docker Hub 上的同名镜像,请以此为准。
# 1. 拉取(也可固定版本,例如 ghcr.io/promptfoo/promptfoo:0.109.1)
docker pull ghcr.io/promptfoo/promptfoo:latest
# 2. 校验镜像来源(可选)
# gh attestation verify oci://ghcr.io/promptfoo/promptfoo:latest --owner promptfoo
# 3. 启动:务必做卷映射,否则数据丢失
docker run -d \
--name promptfoo_container \
-p 3000:3000 \
-v ./promptfoo_data:/home/promptfoo/.promptfoo \
-e OPENAI_API_KEY=sk-abc123 \
ghcr.io/promptfoo/promptfoo:latest
访问 http://localhost:3000 打开 Web UI。
Docker Compose 版本:
# docker-compose.yml
version: '3.8'
services:
promptfoo_container:
image: ghcr.io/promptfoo/promptfoo:latest
ports:
- '3000:3000'
volumes:
- ./promptfoo_data:/home/promptfoo/.promptfoo
environment:
- PROMPTFOO_SHARE_CHUNK_SIZE=10
- OPENAI_API_KEY=your_key_here
mkdir -p ./promptfoo_data
docker compose up -d
让本地 CLI 指向自托管实例:
export PROMPTFOO_REMOTE_API_BASE_URL=http://your-server-address:3000
export PROMPTFOO_REMOTE_APP_BASE_URL=http://your-server-address:3000
promptfoo eval
promptfoo share
# 或一条命令
promptfoo eval --share
也可以写进配置文件(优先级最高):
sharing:
apiBaseUrl: http://your-server-address:3000
appBaseUrl: http://your-server-address:3000
自定义配置目录(容器内换路径):
mkdir -p ./my_custom_data
docker run -d --name promptfoo_container -p 3000:3000 \
-v ./my_custom_data:/app/data \
-e PROMPTFOO_CONFIG_DIR=/app/data \
ghcr.io/promptfoo/promptfoo:latest
限制 Web UI 里可用的 provider(成本控制 / 走内部网关): 在 .promptfoo 目录(与 promptfoo.db 同级)放 ui-providers.yaml:
providers:
- openai:gpt-5.1-mini
- id: openai:gpt-5.1
label: GPT-5.1 (Company Approved)
config:
temperature: 0.7
max_tokens: 4096
- id: 'http://llm-gateway.company.com/v1'
label: Internal Gateway
config:
method: POST
headers:
Authorization: 'Bearer {{ env.INTERNAL_API_KEY }}'
5.6 pip / pipx:不是官方主推方式
README 提到
pip install promptfoo也可用,但官方安装文档只列了 npm / npx / brew 三种。不建议使用
pipx:promptfoo 的核心是 Node 包,通过 pip 安装的本质仍是包装 Node 运行时;自定义 Python provider 只需要系统里有python3即可,不需要 pipx。官方未提供
pipx install promptfoo的说明,因此本文不给出该命令。
5.7 源码编译(不推荐,仅贡献者需要)
git clone https://github.com/promptfoo/promptfoo.git
cd promptfoo
npm install
npm run build
遇到原生依赖(libsql 等)编译失败时安装构建工具链:
# Ubuntu / Debian
sudo apt-get install build-essential
# macOS
xcode-select --install
# 强制本地编译
npm install --build-from-source
六、配置文件全部参数解释
6.1 顶层参数(Config)
6.2 evaluateOptions
对应环境变量:PROMPTFOO_EVAL_TIMEOUT_MS、PROMPTFOO_MAX_EVAL_TIME_MS。
6.3 Test Case(测试用例)
6.4 Assertion(断言)
6.5 Assertion Set
6.6 commandLineOptions(写入 YAML 的命令行默认值)
6.7 断言类型全表(官方 Assertions & Metrics)
确定性断言(Deterministic eval metrics)
模型辅助断言(Model-assisted eval metrics)
提示:每种类型都能加
not-前缀取反,例如not-equals、not-regex、not-javascript。
6.8 Provider 配置
Provider 语法有三种写法:
# 1) 简单字符串
providers:
- openai:gpt-5
- anthropic:messages:claude-opus-5
# 2) 对象 + config
providers:
- id: openai:gpt-5
label: gpt-5-prod
config:
max_completion_tokens: 150
temperature: 0.7
# 3) 引用外部文件
providers:
- file://provider.yaml # 单个 provider 对象
- file://providers.yaml # provider 数组
ProviderOptions 字段:id、label、config(含 cost / inputCost / outputCost 价格覆盖)、prompts(该 provider 跑哪些 prompt)、transform、delay、env(provider 级环境覆盖)、inputs(红队多输入定义)。
常用 config 选项:temperature、max_tokens、max_completion_tokens(OpenAI 推理模型用)、top_p、frequency_penalty、presence_penalty、stop、apiKey。
环境变量解析优先级:provider env → eval env → --env-file → shell 变量;显式写在 provider config 里的值优先级最高。
常用 provider 与 ID 示例(官方 Providers 表节选)
6.9 带注释的完整配置示例
# yaml-language-server: $schema=https://promptfoo.dev/config-schema.json
# ---------- 基础元信息 ----------
description: '中文客服机器人提示词回归测试'
tags:
env: production
application: support-bot
# ---------- 被测目标 ----------
providers:
- id: openai:gpt-5-mini
label: gpt-5-mini
config:
temperature: 0
max_completion_tokens: 512
- id: anthropic:messages:claude-sonnet-4-5-20250929
label: claude-sonnet
- id: ollama:chat:llama3.3
label: local-llama
delay: 200 # 本地模型限速
# 自定义 HTTP 端点
- id: https://api.example.com/v1/chat/completions
label: internal-gateway
config:
method: POST
headers:
Authorization: 'Bearer {{ env.INTERNAL_API_KEY }}'
# 自定义 Python provider
- id: file://./providers/my_provider.py:call_api
label: my-python-agent
# ---------- 提示词 ----------
prompts:
- '你是 {{company}} 的客服助手,请用中文回答:{{question}}'
- file://prompts/v2.txt
# ---------- 默认测试属性 ----------
defaultTest:
options:
provider:
text:
id: openai:gpt-5-mini # model-graded 断言用的打分模型
transform: 'output.trim()' # 输出先 trim 再断言
assert:
- type: latency
threshold: 5000
- type: cost
threshold: 0.02
# ---------- 测试用例 ----------
tests:
- description: '标准问候'
vars:
company: 示例科技
question: 你好
assert:
- type: contains
value: '你好'
- type: llm-rubric
value: '回复应当礼貌、简洁,且使用中文'
metric: Politeness
weight: 2
- type: not-contains
value: '抱歉,我不能'
- description: '退款政策问询'
vars:
company: 示例科技
question: 你们支持 7 天无理由退款吗?
assert:
- type: assert-set
threshold: 0.5 # 两条里过一条即可
assert:
- type: cost
threshold: 0.005
- type: latency
threshold: 2000
- type: similar
value: '支持 7 天无理由退款'
threshold: 0.8
- description: '结构化输出校验'
vars:
company: 示例科技
question: 查询订单 12345
options:
response_format: file://./schemas/order-response.json # 透传给 provider
assert:
- type: is-json
- type: javascript
value: 'output.orderId === "12345"'
# ---------- 运行参数 ----------
evaluateOptions:
maxConcurrency: 4
repeat: 1
delay: 0
cache: true
timeoutMs: 30000
maxEvalTimeMs: 600000
# ---------- 命令行默认值 ----------
commandLineOptions:
envPath:
- .env
- .env.local
grader: openai:gpt-5-mini
table: true
tableCellMaxLength: 100
# ---------- 输出 ----------
outputPath:
- results.json
- report.html
- results.junit.xml
# ---------- 本次运行的环境变量 ----------
env:
PROMPTFOO_EVAL_TIMEOUT_MS: 30000
PROMPTFOO_MAX_EVAL_TIME_MS: 300000
# ---------- 派生指标 ----------
derivedMetrics:
- name: 'quality'
value: '(helpfulness + accuracy) / 2'
七、启动、后台常驻、开机自启、改端口
7.1 两类"启动"要分清
7.2 修改端口
# Web viewer 换端口
promptfoo view -p 15500
promptfoo view -p 8080 -y # -y 自动打开浏览器
promptfoo view -p 8080 -n # -n 不打开浏览器
# 红队报告换端口
promptfoo redteam report -p 8080
# 自托管容器换端口(改 host 侧映射,容器内仍是 3000)
docker run -d -p 8080:3000 \
-v ./promptfoo_data:/home/promptfoo/.promptfoo \
ghcr.io/promptfoo/promptfoo:latest
若使用了
PROMPTFOO_CONFIG_DIR改过输出目录,需要显式指定目录:promptfoo view [directory]。
7.3 Linux 后台常驻(systemd)
自托管服务端建议直接让 Docker 托管(restart: unless-stopped)。如果确实要用 systemd 包一层:
# /etc/systemd/system/promptfoo.service
[Unit]
Description=Promptfoo self-hosted server
After=docker.service
Requires=docker.service
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/docker start -a promptfoo_container
ExecStop=/usr/bin/docker stop -t 10 promptfoo_container
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now promptfoo
sudo systemctl status promptfoo
Compose 版本更简洁:
# /etc/systemd/system/promptfoo-compose.service
[Unit]
Description=Promptfoo compose stack
After=docker.service
Requires=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/promptfoo
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
[Install]
WantedBy=multi-user.target
7.4 Supervisor(备选)
[program:promptfoo]
command=/usr/bin/docker start -a promptfoo_container
autostart=true
autorestart=true
stderr_logfile=/var/log/promptfoo.err.log
stdout_logfile=/var/log/promptfoo.out.log
7.5 Windows 计划任务 / NSSM
Promptfoo 的 eval 是批处理任务,Windows 下用「任务计划程序」定时跑即可:
# 创建一个每周一 09:00 跑评测的计划任务
$action = New-ScheduledTaskAction -Execute "npx" -Argument "promptfoo@latest eval -c C:\evals\promptfooconfig.yaml -o C:\evals\results.json"
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At 9am
Register-ScheduledTask -TaskName "Promptfoo Weekly Eval" -Action $action -Trigger $trigger -Description "Weekly LLM eval"
如需把 Web viewer 做成 Windows 服务,可用 NSSM:
nssm install promptfoo-view "C:\Program Files\nodejs\node.exe"
nssm set promptfoo-view AppParameters "C:\Users\me\AppData\Roaming\npm\node_modules\promptfoo\dist\src\main.js view -p 15500 -n"
nssm start promptfoo-view
7.6 Docker Compose 自启
Compose 文件里加 restart: unless-stopped(官方示例已包含),然后:
docker compose up -d # 会随 docker daemon 重启而自动拉起
docker compose logs -f promptfoo_container
7.7 反向代理示例(Nginx)
server {
listen 80;
server_name promptfoo.internal.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Web UI 用到 SSE / WebSocket 长连接
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
}
}
⚠️ 官方明确说明自托管版本没有内置鉴权与 SSO,放到公司内网时必须由反向代理或网关提供认证,不要直接暴露到公网。
八、功能实操教程
8.1 场景一:从零跑通第一个 eval
mkdir my-evals && cd my-evals
npx promptfoo@latest init --example getting-started
cd getting-started
export OPENAI_API_KEY=sk-abc123
npx promptfoo@latest eval
npx promptfoo@latest view
生成的 promptfooconfig.yaml 形如:
prompts:
- 'Convert the following English text to {{language}}: {{input}}'
providers:
- openai:gpt-6-sol
- openai:gpt-6-luna
tests:
- vars:
language: French
input: Hello world
assert:
- type: contains
value: 'Bonjour le monde'
- vars:
language: Spanish
input: Where is the library?
assert:
- type: icontains
value: 'Dónde está la biblioteca'
终端输出是一张矩阵表,Web viewer 里可以逐格查看完整输出、prompt、变量与打分理由。

8.2 场景二:横向对比多家模型(含本地模型)
providers:
- openai:gpt-5-mini
- anthropic:messages:claude-sonnet-4-5-20250929
- vertex:gemini-3.8-flash
- bedrock:us.anthropic.claude-opus-5
- ollama:chat:llama3.3
prompts:
- '用一句话解释 {{concept}}'
tests:
- vars: { concept: '向量数据库' }
assert:
- type: llm-rubric
value: '解释必须准确、不超过 50 字、且用中文'
metric: Accuracy
- type: cost
threshold: 0.01
- type: latency
threshold: 8000
设置各家 key:
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...
export GOOGLE_API_KEY=... # Google AI Studio
# Vertex / Bedrock 走各自云凭证,见官方 provider 文档
只跑某几家:
promptfoo eval --filter-providers 'openai.*'
promptfoo eval --filter-providers 'ollama.*'
8.3 场景三:自定义 HTTP / Python provider
HTTP 端点(打你自己的服务):
providers:
- id: https://myapp.internal/generate
label: my-app
config:
method: POST
headers:
'Content-Type': 'application/json'
Authorization: 'Bearer {{ env.MYAPP_TOKEN }}'
body:
message: '{{prompt}}'
responseParser: 'json.choices[0].message.content'
Python provider(my_provider.py):
def call_api(prompt, options, context):
# context["vars"] 可拿到测试用例变量
return {
"output": f"echo: {prompt}",
"tokenUsage": {"total": 10, "prompt": 5, "completion": 5},
}
providers:
- id: file://./my_provider.py:call_api
调试 Python provider:
LOG_LEVEL=debug npx promptfoo eval
# 或
npx promptfoo eval --verbose
# 启用 pdb 断点
export PROMPTFOO_PYTHON_DEBUG_ENABLED=true
8.4 场景四:RAG 质量评估(上下文类断言)
prompts:
- |
仅根据以下上下文回答问题,若上下文没有答案请回答"不知道"。
上下文:{{context}}
问题:{{question}}
providers: [openai:gpt-5-mini]
tests:
- vars:
context: '公司成立于 2019 年,总部位于杭州。'
question: '公司总部在哪里?'
assert:
- type: context-faithfulness # 答案必须来自上下文
threshold: 0.6
- type: context-relevance
threshold: 0.5
- type: answer-relevance
threshold: 0.5
- type: factuality
value: '公司总部位于杭州'
需要自定义上下文来源时用 contextTransform(把 RAG 检索结果转成 context)。
8.5 场景五:缓存管理与"改了 prompt 没生效"
# 查看是否被缓存命中(输出里会有 cached 标记)
promptfoo eval
# 强制穿透缓存
promptfoo eval --no-cache
# 清空缓存
promptfoo cache clear
rm -rf ~/.promptfoo/cache
# 自定义缓存位置与类型
export PROMPTFOO_CACHE_TYPE=disk
export PROMPTFOO_CACHE_PATH=/data/promptfoo/cache
export PROMPTFOO_CACHE_TTL=604800 # 单位秒,默认 14 天
export PROMPTFOO_CACHE_ENABLED=false # 全局关闭
缓存关键行为(官方 Caching 文档):
缓存键包含 provider 标识 + 请求内容摘要 + provider 配置 + 上下文变量。
错误响应不缓存,便于重试;空响应不缓存。
--repeat > 1时每个 repeat 索引使用独立缓存命名空间。429 响应自动指数退避;HTTP 500 可通过
PROMPTFOO_RETRY_5XX=true重试。缓存不随"修改 prompt 文件的时间戳"失效 —— 它看的是内容摘要。若你改了 prompt 但结果没变,检查是否改的是未被 include 的文件,或直接用
--no-cache。
8.6 场景六:红队测试全流程
# 方式 A:Web 向导(默认 15500 端口)
npx promptfoo@latest redteam setup
# 方式 B:命令行初始化,不打开浏览器
npx promptfoo@latest redteam init --no-gui
# 生成对抗用例并立即执行
npx promptfoo@latest redteam run
# 查看报告
npx promptfoo@latest redteam report -p 15500
redteam run = redteam generate + redteam eval,生成的用例默认写到 redteam.yaml。
典型红队配置:
targets:
- id: openai:gpt-5
label: customer-service-agent
redteam:
numTests: 10
purpose: |
应用是一个电商客服机器人,帮助用户查询订单、申请退款。
用户是已登录的普通用户,不能查看他人订单,不能执行管理员操作。
plugins:
- id: 'harmful:hate'
numTests: 8
severity: 'critical'
- id: 'pii'
severity: 'high'
- id: 'bola'
- id: 'bfla'
- id: 'prompt-injection'
strategies:
- 'basic'
- id: 'jailbreak'
config:
plugins:
- 'harmful:hate'
frameworks:
- owasp:llm
- nist:ai:measure
language: Chinese
maxConcurrency: 4
delay: 0
攻击 HTTP 端点:
targets:
- id: https
label: 'travel-agent'
config:
url: 'https://example.com/generate'
method: 'POST'
headers:
'Content-Type': 'application/json'
body:
myPrompt: '{{prompt}}'
命令参数速查:

8.7 场景七:CI 集成(GitHub Action + 命令行质量门禁)
GitHub Action(官方 promptfoo/promptfoo-action@v1):
name: 'Prompt Evaluation'
on:
pull_request:
paths:
- 'prompts/**'
jobs:
evaluate:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '24'
- name: Set up promptfoo cache
uses: actions/cache@v4
with:
path: ~/.cache/promptfoo
key: ${{ runner.os }}-promptfoo-v1
restore-keys: |
${{ runner.os }}-promptfoo-
- name: Run promptfoo evaluation
uses: promptfoo/promptfoo-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
github-token: ${{ secrets.GITHUB_TOKEN }}
prompts: 'prompts/**/*.json'
config: 'prompts/promptfooconfig.yaml'
cache-path: ~/.cache/promptfoo
Action 参数:github-token(必填)、prompts(必填)、config(必填)、openai-api-key、cache-path。Action 依赖环境变量 PROMPTFOO_CONFIG_DIR 与 PROMPTFOO_CACHE_PATH。要求 runner 上 Node.js ≥ 22.22.0,推荐 24。
命令行 + JUnit(通用 CI):
# 生成 JUnit XML,交给 CI 的测试报告面板
npx promptfoo@latest eval -c promptfooconfig.yaml -o results.junit.xml
# 同时产出多种格式
npx promptfoo@latest eval -o results.json -o report.html -o results.junit.xml
# 红队扫描
npx promptfoo@latest redteam run
# 附加流水线上下文标签
npx promptfoo@latest eval --tag ci.run-id="$CI_PIPELINE_ID" --tag git.sha="$CI_COMMIT_SHA"
JUnit 结构要点:每个 prompt/provider 对一个 testsuite,每条 eval 结果一个 testcase,断言失败为 failure,provider / 运行时错误为 error。
退出码与质量门禁:
至少 1 条用例失败,或通过率低于
PROMPTFOO_PASS_RATE_THRESHOLD→ 退出码 100。其他错误 → 退出码 1。
失败退出码可用
PROMPTFOO_FAILED_TEST_EXIT_CODE覆盖。
export PROMPTFOO_PASS_RATE_THRESHOLD=0.9
npx promptfoo@latest eval -o results.json || echo "质量门禁未通过"
# 用 jq 自己算通过率
PASS_RATE=$(jq '.results.stats.successes / (.results.stats.successes + .results.stats.failures) * 100' results.json)
CI 里缓存 npx 下载:
- uses: actions/setup-node@v4
with:
node-version: '24'
cache: 'npm'
cache-dependency-path: '**/.github/workflows/*.yml'
- run: npx promptfoo@latest redteam run -c config.yaml -o output.json
8.8 场景八:代码扫描(code scanning)
npx promptfoo@latest code-scans run [repo-path]
扫描结果用于在 PR 里标注 LLM 相关的安全与合规问题。

九、全套报错故障排查
十、升级、回滚与卸载
10.1 查看版本
promptfoo --version
npx promptfoo@latest --version
npm view promptfoo version # 查看 npm 上的最新版
10.2 升级
# npm 全局
npm install -g promptfoo@latest
# 项目依赖
npm install promptfoo@latest --save
# brew
brew upgrade promptfoo
# npx(天然总是最新)
npx promptfoo@latest eval
官方要求:升级前先确认 Node ≥ 22.22.0(推荐 24 LTS),切换运行时后用
node --version验证再装/升 promptfoo。
10.3 回滚到指定版本
# 全局回滚
npm install -g promptfoo@0.125.0
# 项目内回滚
npm install promptfoo@0.125.0 --save-dev
# npx 指定版本
npx promptfoo@0.125.0 eval
# Docker 固定版本
docker pull ghcr.io/promptfoo/promptfoo:0.109.1
docker run -d -p 3000:3000 \
-v ./promptfoo_data:/home/promptfoo/.promptfoo \
ghcr.io/promptfoo/promptfoo:0.109.1
10.4 Docker 升级
docker compose pull
docker compose up -d
docker image prune -f # 清理旧镜像
10.5 完整卸载
# 1. 卸载包(如果你用多种方式装过,每种都要卸一遍)
npm uninstall -g promptfoo
npm uninstall promptfoo # 项目依赖
brew uninstall promptfoo # 若用 brew 装过
# 2. 验证没有残留
which -a promptfoo # Mac / Linux
where.exe promptfoo # Windows
# 项目局部安装(node_modules/.bin/promptfoo)不会被上面命令发现,需删项目依赖
# 3.(可选)删除配置、历史与缓存 —— 会永久删除 eval 历史、数据库与缓存
rm -rf ~/.promptfoo # Mac / Linux
rmdir /s %USERPROFILE%\.promptfoo # Windows CMD
# 4. 若自定义过路径,也一并清理
# PROMPTFOO_CONFIG_DIR / PROMPTFOO_CACHE_PATH / PROMPTFOO_LOG_DIR
# 5. Docker 清理
docker stop promptfoo_container && docker rm promptfoo_container
docker rmi ghcr.io/promptfoo/promptfoo:latest
docker volume rm promptfoo_data # 谨慎:会删除所有 eval 数据
十一、商用许可与合规风险提示
11.1 License
MIT(GitHub License 徽标与 npm 包元数据均为 MIT)。
义务:保留版权与许可声明;无 copyleft 传染性,可自由商用、修改、再分发。
README 公告:Promptfoo 已加入 OpenAI,但依旧开源、依旧 MIT。
注意区分:开源 CLI / 自托管镜像(MIT) 与 Promptfoo Enterprise / Cloud 平台 是不同产品,后者涉及商业协议与付费。
11.2 商标与品牌
"Promptfoo" 名称与 logo 归项目方所有。MIT 只授予代码使用权,不含商标授权;对外宣传时不要暗示官方背书。
11.3 API 费用与额度
Promptfoo 本身免费,但每次 eval 都会真实调用 LLM API 并产生费用。
红队扫描会生成数百到数千条对抗输入,官方提示"单次红队从几分钱到数百美元不等",务必先设
numTests、maxConcurrency、delay与 provider 侧配额上限。用缓存、
--filter-sample、按--filter-range分片跑,可显著省钱。cost断言 +derivedMetrics可把成本纳入门禁。
11.4 数据隐私与出网
默认本地执行,prompts 不出机器;但你调用的 LLM provider 会收到你的 prompt 与测试数据。若数据敏感:
只使用本地模型(Ollama / vLLM / llama.cpp)或私有化部署;
对测试数据脱敏;
通过内部网关 provider 统一出口与审计。
Web viewer / 自托管服务端默认没有任何鉴权:不要直接暴露公网,必须置于 VPN / 反向代理认证之后。
自托管 SQLite 数据库
promptfoo.db里存有所有 prompt、输出与变量,属于敏感资产,要控制文件权限与备份加密。promptfoo share会把结果上传到分享目标(默认官方云,可指向自托管实例);使用--show-auth会带上认证信息,公开分享前要确认。
11.5 生产环境风险
自托管镜像官方明确 "not recommended for production use cases"(SQLite、单副本、无 RBAC、无 SSO、无水平扩展、多副本会 "Job not found")。生产协作需求请评估 Enterprise。
红队扫描会生成有害 / 有毒 / 攻击性输入,官方在文档里加了 danger 警告;只在测试环境对自有系统执行,并保留授权记录。
CI 中把 prompt 改动与模型改动都纳入回归;建议同时设通过率门禁与成本 / 延迟门禁,避免"指标变好但成本翻十倍"。
附录:命令速查
# ===== 安装与版本 =====
npm install -g promptfoo
brew install promptfoo
npx promptfoo@latest --version
promptfoo --version
# ===== 初始化 =====
promptfoo init
promptfoo init --example getting-started
promptfoo init --no-interactive
# ===== 评测 =====
promptfoo eval
promptfoo eval -c path/to/promptfooconfig.yaml
promptfoo eval -o results.json -o report.html -o results.junit.xml
promptfoo eval --no-cache
promptfoo eval -j 8 # maxConcurrency
promptfoo eval --repeat 3
promptfoo eval --delay 500
promptfoo eval --filter-pattern 'auth.*'
promptfoo eval --filter-providers 'openai.*'
promptfoo eval --filter-range 0:100
promptfoo eval --filter-sample 50 --filter-sample-seed 42
promptfoo eval --filter-failing results.json
promptfoo eval --retry-errors
promptfoo eval --resume
promptfoo eval --tag env=ci --tag run-id=$CI_RUN_ID
promptfoo eval --share / --no-share
promptfoo eval -w # watch 模式,改动即重跑
promptfoo optimize # 提示词自动优化
# ===== 查看与分享 =====
promptfoo view
promptfoo view -p 15500 -y
promptfoo share
promptfoo share --show-auth
promptfoo list evals / prompts / datasets
promptfoo show <id>
promptfoo delete <id>
promptfoo export eval <evalId>
promptfoo export logs
# ===== 缓存 =====
promptfoo cache clear
rm -rf ~/.promptfoo/cache
# ===== 日志 =====
promptfoo logs
promptfoo logs -n 50
promptfoo logs -f
promptfoo logs --list
promptfoo logs --type error
promptfoo logs --grep "openai"
promptfoo debug
# ===== 红队 =====
promptfoo redteam setup # 默认端口 15500
promptfoo redteam init --no-gui
promptfoo redteam run
promptfoo redteam run --tag ci.run-id=$CI_RUN_ID
promptfoo redteam generate --purpose '...' --injectVar message
promptfoo redteam eval
promptfoo redteam report -p 8080
promptfoo redteam plugins --default
promptfoo redteam discover -c promptfooconfig.yaml
promptfoo code-scans run
# ===== 账号 =====
promptfoo auth login -k <API_KEY>
promptfoo auth whoami
promptfoo auth logout
promptfoo config set email you@example.com
# ===== 常用环境变量 =====
export OPENAI_API_KEY=sk-...
export ANTHROPIC_API_KEY=sk-ant-...
export PROMPTFOO_CONFIG_DIR=/data/promptfoo # 配置与数据库目录
export PROMPTFOO_CACHE_PATH=/data/promptfoo/cache # 缓存目录
export PROMPTFOO_LOG_DIR=/data/promptfoo/logs # 日志目录
export PROMPTFOO_CACHE_ENABLED=true
export PROMPTFOO_CACHE_TYPE=disk # disk | memory
export PROMPTFOO_CACHE_TTL=1209600 # 秒,默认 14 天
export PROMPTFOO_RETRY_5XX=true
export PROMPTFOO_EVAL_TIMEOUT_MS=30000
export PROMPTFOO_MAX_EVAL_TIME_MS=300000
export PROMPTFOO_PASS_RATE_THRESHOLD=0.9
export PROMPTFOO_FAILED_TEST_EXIT_CODE=101
export PROMPTFOO_REMOTE_API_BASE_URL=http://host:3000
export PROMPTFOO_REMOTE_APP_BASE_URL=http://host:3000
export PROMPTFOO_CA_CERT_PATH=/path/to/ca-bundle.crt
export PROMPTFOO_PYTHON=/usr/local/bin/python3
export HTTPS_PROXY=http://proxy.company.com:8080
export NO_PROXY=localhost,127.0.0.1
export NODE_OPTIONS="--max-old-space-size=8192"