mcpField
P
promptfoo-evaluation

promptfoo-evaluation

github.com/daymadeテスト・品質1.5k1.6k 回インストール今日更新
リポジトリ

promptfoo-evaluation について

Promptfoo Evaluationは、オープンソースのコマンドラインツールPromptfooでLLM評価を設定・実行するスキルです。プロンプト形式、テストケース、アサーション、Pythonによる独自チェック、設定のトラブルシューティングを扱います。

主な機能

  1. 01テキストとチャット形式のプロンプト設定
  2. 02テストケースとファイル入力の定義
  3. 03組み込みおよび独自アサーションの利用
  4. 04LLMルーブリックによる出力評価
  5. 05echoによるプロンプト表示のプレビュー

活用シーン

  1. 01テストケースごとのLLM出力比較
  2. 02独自基準による回答品質の確認
  3. 03API呼び出し前のプロンプト表示確認
  4. 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-rubricLLM による採点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をご覧ください。

コメント