arize-prompt-optimization について
Arize と `ax` コマンドラインを使うチーム向けの、プロンプト最適化スキルです。トレースからプロンプトと性能データを抽出し、修正したうえで、実験によるテストと比較を行う手順を案内します。
主な機能
- 01トレーススパンからプロンプトを抽出
- 02アノテーションと評価結果を確認
- 03データセットと実験出力を結合
- 04変数を保ってプロンプトを修正
- 05実験でプロンプトの版を比較
活用シーン
- 01失敗した LLM トレースの調査
- 02低スコアの原因となるプロンプト傾向の特定
- 03データセットを使った修正版のテスト
- 04回帰を確認しながら二つの版を比較
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ github/ awesome-copilot --skill arize-prompt-optimizationインストール後、Claude Code で/arize-prompt-optimizationを入力して読み込まれたか確認します。
同梱ファイルreferences/ax-profiles.mdreferences/ax-setup.md
詳細
Arize プロンプト最適化スキル
SPACE— すべての--spaceフラグとARIZE_SPACE環境変数には、スペースの名前(例:my-workspace)または base64 形式のスペースID(例:U3BhY2U6...)を指定できます。ax spaces listを実行して確認してください。
概念
トレースデータ内のプロンプトの保存場所
LLM アプリケーションは、OpenInference のセマンティック規約に従ったスパンを出力します。プロンプトは、スパンの種類や計装方法に応じて異なるスパン属性に保存されます。
| 列 | 含まれる内容 | 使用する場面 |
|---|---|---|
attributes.llm.input_messages | ロールベース形式の構造化チャットメッセージ(system、user、assistant、tool) | チャットベースの LLM プロンプトの主なデータソース |
attributes.llm.input_messages.roles | system、user、assistant、tool のロールの配列 | 個々のメッセージのロールを抽出する |
attributes.llm.input_messages.contents | メッセージ内容の文字列の配列 | メッセージテキストを抽出する |
attributes.input.value | シリアライズされたプロンプトまたはユーザーの質問(すべてのスパン種類に共通) | 構造化メッセージがない場合の代替データソース |
attributes.llm.prompt_template.template | {variable} プレースホルダーを含むテンプレート(例:"Answer {question} using {context}") | アプリでプロンプトテンプレートを使用している場合 |
attributes.llm.prompt_template.variables | テンプレート変数の値(JSON オブジェクト) | テンプレートに代入された値を確認する |
attributes.output.value | モデルの応答テキスト | LLM が生成した内容を確認する |
attributes.llm.output_messages | 構造化されたモデル出力(ツール呼び出しを含む) | ツール呼び出しの応答を調べる |
スパンの種類別にプロンプトを見つける
- LLM スパン(
attributes.openinference.span.kind = 'LLM'):構造化チャットメッセージはattributes.llm.input_messages、シリアライズされたプロンプトはattributes.input.valueを確認します。テンプレートはattributes.llm.prompt_template.templateを確認します。 - Chain/Agent スパン:
attributes.input.valueにユーザーの質問が含まれます。実際の LLM プロンプトは子 LLM スパンにあります。トレースツリーをたどって確認してください。 - Tool スパン:
attributes.input.valueにツールへの入力、attributes.output.valueにツールの結果が含まれます。通常、プロンプトが保存される場所ではありません。
パフォーマンスシグナルの列
これらの列には、最適化に使用するフィードバックデータが含まれます。
| 列のパターン | ソース | 内容 |
|---|---|---|
annotation.<name>.label | 人間のレビュアー | カテゴリ別の評価(例:correct、incorrect、partial) |
annotation.<name>.score | 人間のレビュアー | 数値による品質スコア(例:0.0 - 1.0) |
annotation.<name>.text | 人間のレビュアー | 評価についての自由記述 |
eval.<name>.label | LLM-as-judge 評価 | 自動によるカテゴリ別の評価 |
eval.<name>.score | LLM-as-judge 評価 | 自動による数値スコア |
eval.<name>.explanation | LLM-as-judge 評価 | 評価でそのスコアが付けられた理由 — 最適化に最も役立つ情報 |
attributes.input.value | トレースデータ | LLM に渡された内容 |
attributes.output.value | トレースデータ | LLM が生成した内容 |
{experiment_name}.output | 実験の実行結果 | 特定の実験からの出力 |
前提条件
タスクに直接進み、必要な ax コマンドを実行してください。事前にバージョン、環境変数、プロファイルを確認しないでください。
ax コマンドが失敗した場合は、エラーに基づいてトラブルシューティングしてください。
command not foundまたはバージョンエラー → references/ax-setup.md を参照してください401 Unauthorized/ API キーがない →ax profiles showを実行して現在のプロファイルを確認してください。プロファイルがない場合、または API キーが間違っている場合は、references/ax-profiles.md に従って作成/更新してください。ユーザーがキーを持っていない場合は、https://app.arize.com/admin > API Keys を案内してください- Space が不明 →
ax spaces listを実行して名前で選ぶか、ユーザーに尋ねてください - Project が不明確 → ユーザーに尋ねるか、
ax projects list -o json --limit 100を実行し、選択可能なオプションとして提示してください - LLM プロバイダーへの呼び出しが失敗(OPENAI_API_KEY / ANTHROPIC_API_KEY がない)→
ax ai-integrations list --space SPACEを実行して、プラットフォーム管理の認証情報があるか確認してください。ない場合は、ユーザーにキーを提供してもらうか、arize-ai-provider-integration スキルを使ってインテグレーションを作成してください - セキュリティ:
.envファイルを読み取ったり、ファイルシステムを検索して認証情報を探したりしないでください。Arize の認証情報にはax profilesを、LLM プロバイダーのキーにはax ai-integrationsを使用してください。これらの方法で認証情報を入手できない場合は、ユーザーに尋ねてください。
フェーズ 1:現在のプロンプトを抽出する
プロンプトを含む LLM スパンを見つける
# Sample LLM spans (where prompts live)
ax spans export PROJECT --filter "attributes.openinference.span.kind = 'LLM'" -l 10 --stdout
# Filter by model
ax spans export PROJECT --filter "attributes.llm.model_name = 'gpt-4o'" -l 10 --stdout
# Filter by span name (e.g., a specific LLM call)
ax spans export PROJECT --filter "name = 'ChatCompletion'" -l 10 --stdout
トレースをエクスポートしてプロンプトの構造を確認する
# Export all spans in a trace
ax spans export PROJECT --trace-id TRACE_ID
# Export a single span
ax spans export PROJECT --span-id SPAN_ID
エクスポートした JSON からプロンプトを抽出する
# Extract structured chat messages (system + user + assistant)
jq '.[0] | {
messages: .attributes.llm.input_messages,
model: .attributes.llm.model_name
}' trace_*/spans.json
# Extract the system prompt specifically
jq '[.[] | select(.attributes.llm.input_messages.roles[]? == "system")] | .[0].attributes.llm.input_messages' trace_*/spans.json
# Extract prompt template and variables
jq '.[0].attributes.llm.prompt_template' trace_*/spans.json
# Extract from input.value (fallback for non-structured prompts)
jq '.[0].attributes.input.value' trace_*/spans.json
プロンプトをメッセージとして再構成する
スパンデータを取得したら、プロンプトをメッセージ配列として再構成します。
[
{"role": "system", "content": "You are a helpful assistant that..."},
{"role": "user", "content": "Given {input}, answer the question: {question}"}
]
スパンに attributes.llm.prompt_template.template がある場合、プロンプトでは変数が使用されています。これらのプレースホルダー({variable} または {{variable}})は保持してください。実行時に置き換えられます。
フェーズ 2:パフォーマンスデータを収集する
トレースから(本番環境のフィードバック)
# Find error spans -- these indicate prompt failures
ax spans export PROJECT \
--filter "status_code = 'ERROR' AND attributes.openinference.span.kind = 'LLM'" \
-l 20 --stdout
# Find spans with low eval scores
ax spans export PROJECT \
--filter "annotation.correctness.label = 'incorrect'" \
-l 20 --stdout
# Find spans with high latency (may indicate overly complex prompts)
ax spans export PROJECT \
--filter "attributes.openinference.span.kind = 'LLM' AND latency_ms > 10000" \
-l 20 --stdout
# Export error traces for detailed inspection
ax spans export PROJECT --trace-id TRACE_ID
データセットと実験から
# Export a dataset (ground truth examples)
ax datasets export DATASET_NAME --space SPACE
# -> dataset_*/examples.json
# Export experiment results (what the LLM produced)
ax experiments export EXPERIMENT_NAME --dataset DATASET_NAME --space SPACE
# -> experiment_*/runs.json
データセットと実験を結合して分析する
2 つのファイルを example_id で結合し、入力と出力、評価を確認します。
# Count examples and runs
jq 'length' dataset_*/examples.json
jq 'length' experiment_*/runs.json
# View a single joined record
jq -s '
.[0] as $dataset |
.[1][0] as $run |
($dataset[] | select(.id == $run.example_id)) as $example |
{
input: $example,
output: $run.output,
evaluations: $run.evaluations
}
' dataset_*/examples.json experiment_*/runs.json
# Find failed examples (where eval score < threshold)
jq '[.[] | select(.evaluations.correctness.score < 0.5)]' experiment_*/runs.json
最適化する項目を特定する
失敗の傾向を確認します。
- 出力を正解データと比較する:LLM の出力は、期待される内容とどこが異なりますか?
- 評価の説明を読む:
eval.*.explanationには、失敗した理由が記載されています - アノテーションのテキストを確認する:人によるフィードバックには、具体的な問題が記載されています
- 冗長さの不一致を確認する:出力が正解データと比べて長すぎたり短すぎたりしていませんか?
- 形式への準拠を確認する:出力は期待される形式になっていますか?
フェーズ 3:プロンプトを最適化する
最適化用メタプロンプト
このテンプレートを使って、改善版のプロンプトを生成します。3 つのプレースホルダーを埋めて、LLM(GPT-4o、Claude など)に送信してください。
You are an expert in prompt optimization. Given the original baseline prompt
and the associated performance data (inputs, outputs, evaluation labels, and
explanations), generate a revised version that improves results.
ORIGINAL BASELINE PROMPT
========================
{PASTE_ORIGINAL_PROMPT_HERE}
========================
PERFORMANCE DATA
================
The following records show how the current prompt performed. Each record
includes the input, the LLM output, and evaluation feedback:
{PASTE_RECORDS_HERE}
================
HOW TO USE THIS DATA
1. Compare outputs: Look at what the LLM generated vs what was expected
2. Review eval scores: Check which examples scored poorly and why
3. Examine annotations: Human feedback shows what worked and what didn't
4. Identify patterns: Look for common issues across multiple examples
5. Focus on failures: The rows where the output DIFFERS from the expected
value are the ones that need fixing
ALIGNMENT STRATEGY
- If outputs have extra text or reasoning not present in the ground truth,
remove instructions that encourage explanation or verbose reasoning
- If outputs are missing information, add instructions to include it
- If outputs are in the wrong format, add explicit format instructions
- Focus on the rows where the output differs from the target -- these are
the failures to fix
RULES
Maintain Structure:
- Use the same template variables as the current prompt ({var} or {{var}})
- Don't change sections that are already working
- Preserve the exact return format instructions from the original prompt
Avoid Overfitting:
- DO NOT copy examples verbatim into the prompt
- DO NOT quote specific test data outputs exactly
- INSTEAD: Extract the ESSENCE of what makes good vs bad outputs
- INSTEAD: Add general guidelines and principles
- INSTEAD: If adding few-shot examples, create SYNTHETIC examples that
demonstrate the principle, not real data from above
Goal: Create a prompt that generalizes well to new inputs, not one that
memorizes the test data.
OUTPUT FORMAT
Return the revised prompt as a JSON array of messages:
[
{"role": "system", "content": "..."},
{"role": "user", "content": "..."}
]
Also provide a brief reasoning section (bulleted list) explaining:
- What problems you found
- How the revised prompt addresses each one
パフォーマンスデータを準備する
テンプレートに貼り付ける前に、レコードを JSON 配列として整形してください。
# From dataset + experiment: join and select relevant columns
jq -s '
.[0] as $ds |
[.[1][] | . as $run |
($ds[] | select(.id == $run.example_id)) as $ex |
{
input: $ex.input,
expected: $ex.expected_output,
actual_output: $run.output,
eval_score: $run.evaluations.correctness.score,
eval_label: $run.evaluations.correctness.label,
eval_explanation: $run.evaluations.correctness.explanation
}
]
' dataset_*/examples.json experiment_*/runs.json
# From exported spans: extract input/output pairs with annotations
jq '[.[] | select(.attributes.openinference.span.kind == "LLM") | {
input: .attributes.input.value,
output: .attributes.output.value,
status: .status_code,
model: .attributes.llm.model_name
}]' trace_*/spans.json
改訂版プロンプトを適用する
LLM が改訂版のメッセージ配列を返したら、次の手順を実行します。
- 元のプロンプトと改訂版のプロンプトを並べて比較する
- テンプレート変数がすべて保持されていることを確認する
- 形式に関する指示がそのまま残っていることを確認する
- 全面展開の前に、いくつかの例でテストする
フェーズ 4:反復する
最適化ループ
1. Extract prompt -> Phase 1 (once)
2. Run experiment -> ax experiments create ...
3. Export results -> ax experiments export EXPERIMENT_NAME --dataset DATASET_NAME --space SPACE
4. Analyze failures -> jq to find low scores
5. Run meta-prompt -> Phase 3 with new failure data
6. Apply revised prompt
7. Repeat from step 2
改善を測定する
# Compare scores across experiments
# Experiment A (baseline)
jq '[.[] | .evaluations.correctness.score] | add / length' experiment_a/runs.json
# Experiment B (optimized)
jq '[.[] | .evaluations.correctness.score] | add / length' experiment_b/runs.json
# Find examples that flipped from fail to pass
jq -s '
[.[0][] | select(.evaluations.correctness.label == "incorrect")] as $fails |
[.[1][] | select(.evaluations.correctness.label == "correct") |
select(.example_id as $id | $fails | any(.example_id == $id))
] | length
' experiment_a/runs.json experiment_b/runs.json
2 つのプロンプトを A/B 比較する
- 同じデータセットに対して、それぞれ異なるプロンプトバージョンを使う 2 つの実験を作成する
- 両方をエクスポートする:
ax experiments export EXP_Aとax experiments export EXP_B - 平均スコア、失敗率、個別の例での結果の変化を比較する
- リグレッションを確認する。つまり、プロンプト A では成功したものの、プロンプト B では失敗した例を確認する
プロンプトエンジニアリングのベストプラクティス
プロンプトを作成または改訂する際は、以下を適用します。
| テクニック | 適用する場面 | 例 |
|---|---|---|
| 明確で詳細な指示 | 出力が曖昧、または話題から逸れている場合 | 「感情を、ポジティブ、ネガティブ、ニュートラルのいずれか1つだけに分類してください」 |
| 冒頭に指示を置く | モデルが後半の指示を無視する場合 | 例の前にタスクの説明を置きます |
| 段階的な分解 | 複雑な複数ステップのプロセス | 「まずエンティティを抽出し、次にそれぞれを分類してから、要約してください」 |
| 具体的なペルソナ | 一貫したスタイルやトーンが必要な場合 | 「あなたは、機関投資家向けに執筆するシニア金融アナリストです」 |
| 区切りトークン | セクションが混ざり合う場合 | ---、###、または XML タグを使って、入力と指示を分けます |
| 少数ショットの例 | 出力形式を明確にする必要がある場合 | 合成した入出力のペアを2~3個提示します |
| 出力の長さの指定 | 回答が長すぎる、または短すぎる場合 | 「ちょうど2~3文で回答してください」 |
| 推論の指示 | 正確性が重要な場合 | 「回答する前に、段階的に考えてください」 |
| 「わかりません」と答えるための指針 | 幻覚のリスクがある場合 | 「回答が提示されたコンテキストに含まれていない場合は、『十分な情報がありません』と答えてください」 |
変数の保持
テンプレート変数を使うプロンプトを最適化する際は、次の点に注意してください。
- 単一の波括弧(
{variable}):Python の f-string/Jinja スタイルです。Arize で最も一般的です。 - 二重の波括弧(
{{variable}}):Mustache スタイルです。フレームワークで必要な場合に使用します。 - 最適化中に変数のプレースホルダーを追加または削除しないでください
- 変数名を変更しないでください。実行時の置換では正確な名前が必要です
- 少数ショットの例を追加する場合は、変数のプレースホルダーではなく、具体的な値を使ってください
ワークフロー
失敗したトレースからプロンプトを最適化する
- 失敗したトレースを探します。
ax traces list PROJECT --filter "status_code = 'ERROR'" --limit 5 - トレースをエクスポートします。
ax spans export PROJECT --trace-id TRACE_ID - LLM スパンからプロンプトを抽出します。
jq '[.[] | select(.attributes.openinference.span.kind == "LLM")][0] | { messages: .attributes.llm.input_messages, template: .attributes.llm.prompt_template, output: .attributes.output.value, error: .attributes.exception.message }' trace_*/spans.json - エラーメッセージまたは出力から、何が失敗したかを特定します
- プロンプトとエラーのコンテキストを使って、最適化メタプロンプト(フェーズ3)を記入します
- 改訂したプロンプトを適用します
データセットと実験を使って最適化する
- データセットと実験を探します。
ax datasets list --space SPACE ax experiments list --dataset DATASET_NAME --space SPACE - 両方をエクスポートします。
ax datasets export DATASET_NAME --space SPACE ax experiments export EXPERIMENT_NAME --dataset DATASET_NAME --space SPACE - メタプロンプト用に結合データを準備します
- 最適化メタプロンプトを実行します
- 改訂したプロンプトを使って新しい実験を作成し、改善を測定します
誤った形式を出力するプロンプトをデバッグする
- 出力形式が誤っているスパンをエクスポートします。
ax spans export PROJECT \ --filter "attributes.openinference.span.kind = 'LLM' AND annotation.format.label = 'incorrect'" \ -l 10 --stdout > bad_format.json - LLM が生成している内容と、期待される内容を確認します
- プロンプトに明示的な形式の指示を追加します(JSON スキーマ、例、区切り文字など)
- よくある修正方法:望ましい出力形式を正確に示す少数ショットの例を追加します
RAG プロンプトの幻覚を減らす
- モデルが幻覚を起こしたトレースを探します。
ax spans export PROJECT \ --filter "annotation.faithfulness.label = 'unfaithful'" \ -l 20 --stdout - retriever と LLM のスパンを一緒にエクスポートして確認します。
ax spans export PROJECT --trace-id TRACE_ID jq '[.[] | {kind: .attributes.openinference.span.kind, name, input: .attributes.input.value, output: .attributes.output.value}]' trace_*/spans.json - 取得したコンテキストに実際に回答が含まれていたかを確認します
- システムプロンプトに根拠付けの指示を追加します:「提示されたコンテキストの情報のみを使用してください。回答がコンテキストに含まれていない場合は、そのように伝えてください。」
トラブルシューティング
| 問題 | 解決策 |
|---|---|
ax: command not found | references/ax-setup.md を参照してください |
No profile found | プロファイルが設定されていません。作成方法については references/ax-profiles.md を参照してください。 |
スパンに input_messages がない | スパンの種類を確認してください。Chain/Agent スパンでは、プロンプトは自身ではなく子の LLM スパンに保存されます |
プロンプトテンプレートが null | すべての計装が prompt_template を出力するわけではありません。代わりに input_messages または input.value を使用してください |
| 最適化後に変数が失われる | 修正後のプロンプトに、元のプロンプトのすべての {var} プレースホルダーが保持されていることを確認してください |
| 最適化によって結果が悪化する | 過剰適合がないか確認してください。メタプロンプトがテストデータを記憶している可能性があります。少数ショットの例が合成データであることを確認してください |
| 評価/アノテーションの列がない | まず評価を実行してから(Arize UI または SDK 経由)、再度エクスポートしてください |
| 実験出力の列が見つからない | 列名は {experiment_name}.output です。ax experiments get で実験名が正確か確認してください |
スパンの JSON で jq エラーが発生する | 正しいファイルパス(例:trace_*/spans.json)を指定していることを確認してください |