promptfoo-evaluation について
Promptfoo Evaluationは、オープンソースのコマンドラインツールPromptfooでLLM評価を設定・実行するスキルです。プロンプト形式、テストケース、アサーション、Pythonによる独自チェック、設定のトラブルシューティングを扱います。
主な機能
- 01テキストとチャット形式のプロンプト設定
- 02テストケースとファイル入力の定義
- 03組み込みおよび独自アサーションの利用
- 04LLMルーブリックによる出力評価
- 05echoによるプロンプト表示のプレビュー
活用シーン
- 01テストケースごとのLLM出力比較
- 02独自基準による回答品質の確認
- 03API呼び出し前のプロンプト表示確認
- 04評価設定の問題の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ daymade/ claude-code-skills --skill promptfoo-evaluationインストール後、Claude Code で/promptfoo-evaluationを入力して読み込まれたか確認します。
同梱ファイルreferences/promptfoo_api.mdscripts/metrics.py
詳細
Promptfoo 評価
概要
このスキルでは、オープンソースの CLI ツールである Promptfoo を使用して、LLM の評価を設定および実行する方法を説明します。Promptfoo は、LLM の出力をテストおよび比較するためのツールです。
クイックスタート
# Initialize a new evaluation project
npx promptfoo@latest init
# Run evaluation
npx promptfoo@latest eval
# View results in browser
npx promptfoo@latest view
設定の構成
Promptfoo プロジェクトの一般的な構成は次のとおりです。
project/
├── promptfooconfig.yaml # Main configuration
├── prompts/
│ ├── system.md # System prompt
│ └── chat.json # Chat format prompt
├── tests/
│ └── cases.yaml # Test cases
└── scripts/
└── metrics.py # Custom Python assertions
コア設定(promptfooconfig.yaml)
# yaml-language-server: $schema=https://promptfoo.dev/config-schema.json
description: "My LLM Evaluation"
# Prompts to test
prompts:
- file://prompts/system.md
- file://prompts/chat.json
# Models to compare
providers:
- id: anthropic:messages:claude-sonnet-4-6
label: Claude-Sonnet-4.6
- id: openai:gpt-4.1
label: GPT-4.1
# Test cases
tests: file://tests/cases.yaml
# Concurrency control (MUST be under commandLineOptions, NOT top-level)
commandLineOptions:
maxConcurrency: 2
# Default assertions for all tests
defaultTest:
assert:
- type: python
value: file://scripts/metrics.py:custom_assert
- type: llm-rubric
value: |
Evaluate the response quality on a 0-1 scale.
threshold: 0.7
# Output path
outputPath: results/eval-results.json
プロンプト形式
テキストプロンプト(system.md)
You are a helpful assistant.
Task: {{task}}
Context: {{context}}
チャット形式(chat.json)
[
{"role": "system", "content": "{{system_prompt}}"},
{"role": "user", "content": "{{user_input}}"}
]
Few-Shot パターン
例をプロンプトに直接埋め込むか、アシスタントメッセージを含むチャット形式を使用します。
[
{"role": "system", "content": "{{system_prompt}}"},
{"role": "user", "content": "Example input: {{example_input}}"},
{"role": "assistant", "content": "{{example_output}}"},
{"role": "user", "content": "Now process: {{actual_input}}"}
]
テストケース(tests/cases.yaml)
- description: "Test case 1"
vars:
system_prompt: file://prompts/system.md
user_input: "Hello world"
# Load content from files
context: file://data/context.txt
assert:
- type: contains
value: "expected text"
- type: python
value: file://scripts/metrics.py:custom_check
threshold: 0.8
Python カスタムアサーション
カスタムアサーション用の Python ファイルを作成します(例:scripts/metrics.py)。
def get_assert(output: str, context: dict) -> dict:
"""Default assertion function."""
vars_dict = context.get('vars', {})
# Access test variables
expected = vars_dict.get('expected', '')
# Return result
return {
"pass": expected in output,
"score": 0.8,
"reason": "Contains expected content",
"named_scores": {"relevance": 0.9}
}
def custom_check(output: str, context: dict) -> dict:
"""Custom named assertion."""
word_count = len(output.split())
passed = 100 <= word_count <= 500
return {
"pass": passed,
"score": min(1.0, word_count / 300),
"reason": f"Word count: {word_count}"
}
重要なポイント:
- デフォルトの関数名は
get_assertです file://path.py:function_nameで関数を指定しますbool、float(スコア)、または pass/score/reason を含むdictを返しますcontext['vars']で変数にアクセスします
LLM-as-Judge(llm-rubric)
assert:
- type: llm-rubric
value: |
Evaluate the response based on:
1. Accuracy of information
2. Clarity of explanation
3. Completeness
Score 0.0-1.0 where 0.7+ is passing.
threshold: 0.7
provider: openai:gpt-4.1 # Optional: override grader model
リレー/プロキシ API を使用する場合、各 llm-rubric アサーションには、apiBaseUrl を含む独自の provider 設定が必要です。設定しない場合、採点器はデフォルトの Anthropic/OpenAI エンドポイントにフォールバックし、401 エラーが発生します。
assert:
- type: llm-rubric
value: |
Evaluate quality on a 0-1 scale.
threshold: 0.7
provider:
id: anthropic:messages:claude-sonnet-4-6
config:
apiBaseUrl: https://your-relay.example.com/api
ベストプラクティス:
- 明確な採点基準を提示します
thresholdを使用して合格に必要な最低スコアを設定します- デフォルトの採点器は、利用可能な API キー(OpenAI → Anthropic → Google)を使用します
- リレー/プロキシを使用する場合:すべての
llm-rubricに、apiBaseUrlを含む独自のproviderが必要です。メインプロバイダーのapiBaseUrlは継承されません
一般的なアサーションの種類
| 種類 | 用途 | 例 |
|---|---|---|
contains | 部分文字列の確認 | value: "hello" |
icontains | 大文字と小文字を区別しない確認 | value: "HELLO" |
equals | 完全一致 | value: "42" |
regex | パターンの一致 | value: "\\d{4}" |
python | カスタムロジック | value: file://script.py |
llm-rubric | LLM による採点 | value: "Is professional" |
latency | 応答時間 | threshold: 1000 |
ファイル参照
すべての file:// パスは、参照を含む YAML ファイルではなく、promptfooconfig.yaml のある場所を基準に解決されます。これは、tests: が別の YAML ファイルを参照している場合によくある落とし穴です。そのテストファイル内の file:// パスも、設定ルートを基準に解決されます。
# Load file content as variable
vars:
content: file://data/input.txt
# Load prompt from file
prompts:
- file://prompts/main.md
# Load test cases from file
tests: file://tests/cases.yaml
# Load Python assertion
assert:
- type: python
value: file://scripts/check.py:validate
評価の実行
# Basic run
npx promptfoo@latest eval
# With specific config
npx promptfoo@latest eval --config path/to/config.yaml
# Output to file
npx promptfoo@latest eval --output results.json
# Filter tests
npx promptfoo@latest eval --filter-metadata category=math
# View results
npx promptfoo@latest view
リレー/プロキシ API の設定
Anthropic/OpenAI のエンドポイントに直接接続するのではなく、API リレーまたはプロキシを使用する場合:
providers:
- id: anthropic:messages:claude-sonnet-4-6
label: Claude-Sonnet-4.6
config:
max_tokens: 4096
apiBaseUrl: https://your-relay.example.com/api # Promptfoo appends /v1/messages
# CRITICAL: maxConcurrency MUST be under commandLineOptions (NOT top-level)
commandLineOptions:
maxConcurrency: 1 # Respect relay rate limits
重要なルール:
apiBaseUrlはproviders[].configに設定します。Promptfoo が自動的に/v1/messagesを追加しますmaxConcurrencyはcommandLineOptions:の下に置く必要があります。トップレベルに置いても、無視されたことが通知されません- リレーと LLM-as-Judge を併用する場合は、同時リクエスト数の上限に達しないよう
maxConcurrency: 1を設定します(生成と採点で同じプールを共有します) - リレートークンは
ANTHROPIC_API_KEY環境変数として渡します
トラブルシューティング
Python が見つからない場合:
export PROMPTFOO_PYTHON=python3
大きな出力が切り詰められる場合:
30000 文字を超える出力は切り詰められます。アサーションで head_limit を使用してください。
ファイルが見つからないエラー:
すべての file:// パスは、promptfooconfig.yaml のある場所を基準に解決されます。
maxConcurrency が無視される場合(「up to N at a time」と表示される):
maxConcurrency は YAML のトップレベルではなく、commandLineOptions: の下に置く必要があります。これはよくある間違いです。
リレー API で LLM-as-Judge が 401 を返す場合:
各 llm-rubric アサーションには、apiBaseUrl を含む独自の provider が必要です。メインのプロバイダー設定は、採点器のアサーションに継承されません。
モデル出力内の HTML タグによってメトリクスが水増しされる場合:
モデルは構造化コンテンツ内に <br>、<b> などを出力することがあります。測定前に Python アサーションで HTML を取り除いてください:
import re
clean_text = re.sub(r'<[^>]+>', '', raw_text)
Echo Provider(プレビューモード)
API を呼び出さずにレンダリング済みプロンプトをプレビューするには、echo provider を使用します。
# promptfooconfig-preview.yaml
providers:
- echo # Returns prompt as output, no API calls
tests:
- vars:
input: "test content"
使用例:
- コストのかかる API 呼び出しの前にプロンプトのレンダリングをプレビューする
- Few-shot の例が正しく読み込まれていることを確認する
- 変数の置換に関する問題をデバッグする
- プロンプトの構成を検証する
# Run preview mode
npx promptfoo@latest eval --config promptfooconfig-preview.yaml
料金: 無料です。API トークンは消費されません。
高度な少数ショット実装
マルチターン会話パターン
完全な例を使った複雑な少数ショット学習の場合:
[
{"role": "system", "content": "{{system_prompt}}"},
// Few-shot Example 1
{"role": "user", "content": "Task: {{example_input_1}}"},
{"role": "assistant", "content": "{{example_output_1}}"},
// Few-shot Example 2 (optional)
{"role": "user", "content": "Task: {{example_input_2}}"},
{"role": "assistant", "content": "{{example_output_2}}"},
// Actual test
{"role": "user", "content": "Task: {{actual_input}}"}
]
テストケースの設定:
tests:
- vars:
system_prompt: file://prompts/system.md
# Few-shot examples
example_input_1: file://data/examples/input1.txt
example_output_1: file://data/examples/output1.txt
example_input_2: file://data/examples/input2.txt
example_output_2: file://data/examples/output2.txt
# Actual test
actual_input: file://data/test1.txt
ベストプラクティス:
- 少数ショットの例は1~3個使用します(多すぎると効果が薄れる可能性があります)
- 例がタスクの形式と完全に一致するようにします
- 保守性を高めるため、例はファイルから読み込みます
- まずecho providerを使って構造を検証します
長文の処理
中国語や長文コンテンツの評価(10k文字以上)の場合:
設定:
providers:
- id: anthropic:messages:claude-sonnet-4-6
config:
max_tokens: 8192 # Increase for long outputs
defaultTest:
assert:
- type: python
value: file://scripts/metrics.py:check_length
テキスト指標のPythonアサーション:
import re
def strip_tags(text: str) -> str:
"""Remove HTML tags for pure text."""
return re.sub(r'<[^>]+>', '', text)
def check_length(output: str, context: dict) -> dict:
"""Check output length constraints."""
raw_input = context['vars'].get('raw_input', '')
input_len = len(strip_tags(raw_input))
output_len = len(strip_tags(output))
reduction_ratio = 1 - (output_len / input_len) if input_len > 0 else 0
return {
"pass": 0.7 <= reduction_ratio <= 0.9,
"score": reduction_ratio,
"reason": f"Reduction: {reduction_ratio:.1%} (target: 70-90%)",
"named_scores": {
"input_length": input_len,
"output_length": output_len,
"reduction_ratio": reduction_ratio
}
}
実際の使用例
プロジェクト: 長いトランスクリプトから中国語のショート動画コンテンツを選定
構成:
tiaogaoren/
├── promptfooconfig.yaml # Production config
├── promptfooconfig-preview.yaml # Preview config (echo provider)
├── prompts/
│ ├── tiaogaoren-prompt.json # Chat format with few-shot
│ └── v4/system-v4.md # System prompt
├── tests/cases.yaml # 3 test samples
├── scripts/metrics.py # Custom metrics (reduction ratio, etc.)
├── data/ # 5 samples (2 few-shot, 3 eval)
└── results/
参照先: 完全な実装については、./tiaogaoren/(サンプルプロジェクトのルート)をご覧ください。
リソース
詳細なAPIリファレンスと高度なパターンについては、references/promptfoo_api.mdをご覧ください。