Promptfoo で LLM を YAML で回帰テストする — AI eval の実装者視点

Promptfoo で LLM を YAML で回帰テストする — AI eval の実装者視点

AI 評価ツール連載の 1 本として、本稿は Promptfoo を取り上げます。

Promptfoo は LLM アプリケーションの挙動を YAML ファイル 1 枚で宣言的に回帰テストできる OSS の CLI ツールです。プロンプトを変えたりモデルを差し替えたときに「前より良くなったのか、悪くなったのか」を手で確認するのをやめ、ユニットテストと同じ感覚で CI に組み込むことを狙っています。

評価サーベイで整理された 4 分類(Behavior / Capabilities / Reliability / Safety)で言えば、Promptfoo が得意なのは Behavior と Reliability です。プラグイン方式で Safety にも手を伸ばしています。

Promptfoo とは何か

ひとことで言えば、「プロンプトとモデルとテストケースを YAML で書くと、総当たりで走らせて pass/fail とスコアを出してくれるツール」です。

ローカルで完結し、クラウドに結果を送らずに済むのが特徴です。

作者とライセンス

Promptfoo は Ian Webster らが 2023 年に立ち上げた独立 OSS として始まりました。ライセンスは MIT で、GitHub のスター数は 2026 年 3 月時点で 2.5 万を超えています。もともと「本番で 1,000 万人超のユーザーに提供する LLM アプリ向けに作った」と README に書かれているとおり、プロダクションでの運用を前提に設計されています。

2026 年初頭に Promptfoo, Inc. は OpenAI に買収されました。README には “now part of OpenAI, remaining open source and MIT licensed” と明記されており、少なくとも現時点では OSS として維持される方針です。ベンダー中立性は買収前と比べて議論の余地が出てきますが、コード自体は MIT なのでフォークはいつでも可能です。

なぜ Promptfoo が必要か

既存のやり方の問題は、ざっくり 3 つあります。

まず、プロンプト改善を手動で確認するのは再現性がありません。同じ入力を 10 回貼り直すと、ある日「良くなった気がする」になり、翌日「悪くなった気がする」になります。

次に、モデルを差し替えたときの影響範囲が見えません。GPT-4o から GPT-5 に変えたら「ある質問だけ劣化する」ことが珍しくなく、手動テストでは発見漏れが必ず出ます。

最後に、本番で起きる Red Team 的な攻撃(間接プロンプト注入、ロール逸脱、PII 漏洩)は、通常のテストケースでは思いつきません。網羅的に試す仕組みが別途必要です。

Promptfoo はこの 3 つを 1 つの YAML で片付けることを狙っています。

主な機能

主要な機能を列挙します。

最小動作例

まず初期化します。

# プロジェクト直下で雛形生成
npx promptfoo@latest init --example getting-started
export OPENAI_API_KEY=sk-...

次に promptfooconfig.yaml を書きます。英仏翻訳をお題にした最小例です。

description: Translation smoke test

prompts:
  - "Translate the following English text to {{language}}: {{input}}"

providers:
  - openai:gpt-4o-mini
  - anthropic:claude-3-5-sonnet-latest

tests:
  - vars:
      language: French
      input: Hello, world.
    assert:
      - type: icontains
        value: "bonjour"
      - type: llm-rubric
        value: |
          The response must be a natural French translation,
          not include English, and preserve punctuation.

  - vars:
      language: Japanese
      input: Where is the library?
    assert:
      - type: contains-any
        value: ["図書館", "ライブラリ"]
      - type: latency
        threshold: 3000
      - type: cost
        threshold: 0.002

実行して結果を見るのは次の 2 コマンドです。

# 評価実行
npx promptfoo@latest eval

# ブラウザで比較ビューを開く
npx promptfoo@latest view

eval の時点で CLI にも pass/fail の表が出ますが、view で開くダッシュボードが本番です。プロンプト別・モデル別・テストケース別にスコアと出力が並び、差分の確認が格段に楽になります。

向くケース・向かないケース

向くケース

向かないケース

他ツールとの違い

DeepEval は pytest 統合を軸にした Python ライブラリで、評価を「コードとして書く」思想です。Promptfoo は YAML 中心なので、プロンプトエンジニアや QA が触りやすい一方、複雑なロジックは javascript/python アサーションに逃がす形になります。

LangSmith は LangChain 社の商用プラットフォームで、trace とデータセット管理が強みです。本番ログからの評価セット作成までを一気通貫で面倒を見てくれる代わりに、SaaS 前提でローカル完結はできません。

Arize Phoenix は OpenTelemetry ベースの観測性に軸足を置いており、「本番トレースを可視化して eval も回す」というポジションです。Promptfoo が静的な YAML、Phoenix が動的な trace、と対比するとわかりやすいです。

OpenAI Evals は OpenAI 公式ですが、どちらかというとモデル評価研究向けの文法で、プロダクション CI にはやや固い印象があります。OpenAI による Promptfoo 買収は、ここを埋める動きだとも読めます。

ハマりポイント

LLM-as-a-judge の揺れ

llm-rubric や factuality は便利ですが、採点モデル自体がブレるため、同じ出力でも実行ごとにスコアが変わります。採点モデルの温度を 0 にし、rubric を可能な限り具体化し、重要なケースは決定論的なアサーション(contains, regex, javascript)に落とすのが定石です。

キャッシュと「直したつもり」

Promptfoo はデフォルトでレスポンスをキャッシュします。プロンプトを微修正したつもりが、ハッシュが衝突して旧出力を返してくる事故が起きます。--no-cache か PROMPTFOO_CACHE_ENABLED=false を CI では付けておくと安全です。

コストの爆発

直積評価はテストケース数 × プロバイダ数 × プロンプト数 で膨らみます。cost アサーションでガードし、--max-concurrency と --filter-first-n で小さく始めるのを推奨します。

Red Team の結果の読み方

Red Team モードが「10 件通した」と出たとして、それが本当に脆弱性なのかは人間が判断する必要があります。レポートはあくまでトリアージの入り口で、全件を issue にすると現場が疲弊します。

日本語採点の弱さ

英語の rubric と日本語の出力を混ぜると、採点モデルが rubric を無視して英語で返答することがあります。rubric も日本語で書き、「必ず日本語で判定理由を返せ」と明示的に指示するのが実用上のコツです。

2026 年のロードマップとエコシステム

OpenAI 傘下に入ったことで、公式サンプルが OpenAI モデル寄りに最適化されていく可能性はありますが、Anthropic・Google・ローカルモデルのプロバイダは引き続きメンテされています。Red Team プラグインの追加ペースが加速しており、OWASP LLM Top 10 への対応が公式ドキュメントで整理されました。

VS Code 拡張、GitHub Actions の公式アクション、MCP サーバ経由での呼び出しなど、周辺エコシステムも 2026 年に入って充実してきています。

まとめ

Promptfoo は「LLM アプリの回帰テストを YAML で宣言的に書く」という一点に特化していて、既存のユニットテスト文化と馴染みがよいツールです。評価サーベイで言う Behavior / Reliability を日常的に守るための実装者向けの道具として、まず最初に導入する候補になります。

一方で、長期エージェントの trajectory 評価や、本番トレースからの評価セット抽出は不得意なので、Phoenix や LangSmith と役割分担するのが現実解です。OpenAI 傘下での中立性は注視する必要がありますが、MIT ライセンスである限り、少なくとも手元で止めることはできません。

まずは 10 ケースの YAML を書いて、promptfoo eval && promptfoo view を打つところから始めてみてください。

chaff grade との連携 — 決定論的採点を混ぜる

LLM-judge は確率的にブレます。一方で、「引用が原文にあるか」「数値の合計が合うか」「文体規則の違反率」といった決定論的な採点は、同じ入力に対して必ず同じ結果を返します。

chaffjs の grade コマンドは、この決定論的な採点を受け持つツールです。LLM-judge で「意見」を測り、chaff で「事実」を測ることで、両者を分離できます。

Promptfoo の場合、JavaScript assertion として chaff grade を呼び出します:

assertions:
  - type: javascript
    value: file://./chaff-assertion.cjs

chaff-assertion.cjs が pass / score / reason を返す形。実装例: isamu/lab: examples/evals/promptfoo

関連リンク

関連記事


Singularity Society はテクノロジー集団として MulmoClaude / MulmoTerminal / MulmoCast を開発しています。エンジニア・起業家向けの実践プログラム BootCamp も運営しています。

この記事をシェア

関連記事

記事一覧に戻る