arize-prompt-optimization について
arize-prompt-optimizationは、Arizeのトレースデータ、データセット、実験結果を使ってLLMのプロンプトを改善するスキルです。プロンプトの抽出、フィードバックや失敗の分析、文面の改訂、実験結果の比較を支援します。
主な機能
- 01トレーススパンからプロンプトを抽出
- 02アノテーションと評価結果を分析
- 03データセットと実験出力を関連付け
- 04プロンプト改訂と変数確認を支援
- 05プロンプト実験を比較して退行を確認
活用シーン
- 01トレースのフィードバックから問題を特定
- 02データセットの例に基づくプロンプト改訂
- 03ベースラインと改訂版の結果を比較
- 04デプロイ前のテンプレート変数確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ arize-ai/ arize-skills --skill arize-prompt-optimizationインストール後、Claude Code で/arize-prompt-optimizationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/ax-profiles.mdax-setup.mdoptimization-meta-prompt.md詳細
Arize プロンプト最適化スキル
SPACE—--spaceフラグには、スペースの名前(例:my-workspace)または base64 形式のスペース ID(例:U3BhY2U6...)を指定します。既知の名前はax spaces get NAMEで確認してください。ax spaces listは人が閲覧するためのコマンドです。
関連スキル
- arize-prompts:
ax promptsを使って、Prompt Hub でプロンプトの作成、バージョン管理、ラベル付け(productionなど)を行います。成果物を Arize に保存する場合はこのスキルを使用し、トレース、データセット、実験を基にプロンプトテキストを改善する場合は、以下の arize-prompt-optimization を使用してください。
概念
トレースデータ内のプロンプトの場所
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 が不明 → Space を参照してください
- Project が不明確 → ユーザーに確認するか、
ax projects list -o json --limit 100を実行し、選択可能な候補として提示してください - LLM プロバイダーへの呼び出しが失敗(プロバイダーの認証情報がない) →
ax ai-integrations list --space SPACEを実行し、プラットフォーム管理の認証情報があるか確認してください。存在しない場合は、arize-ai-provider-integration スキルを使用してください。ユーザーにプロバイダーキーをチャットに貼り付けるよう求めてはいけません。 - セキュリティ:
.envファイルを読み取ったり、ファイルシステム内で認証情報を検索したりしてはいけません。例外は、シークレットではないARIZE_SPACE_IDの行です(Space を参照)。Arize の認証情報にはax profilesを、LLM プロバイダーキーにはax ai-integrationsを使用してください。ユーザーにシークレットをチャットに貼り付けるよう求めてはいけません。認証情報がない場合は、references/ax-profiles.md を参照してください。
最初にユーザーへの確認が必要な場合
自由回答形式で質問するより、ax による照会を優先してください。既知の名前は ax projects get NAME --space SPACE または ax datasets get NAME --space SPACE で確認します(list は人が閲覧するためのものです)。それでも先に進めない場合(たとえば、ユーザーが指定した名前に一致するプロジェクトが複数ある、トレースと実験のどちらの経路か不明確、または破壊的な操作の範囲が不明確な場合)、すぐに質問に飛びつかないでください。スコープや確認のために処理を止める arize-instrumentation と同じ明確な伝え方をしてください。
- スキルを確認したことを伝えます。例:このリポジトリで arize-prompt-optimization スキルを見つけました(必要であれば
skills/arize-prompt-optimization/SKILL.mdを追加してもかまいません)。 - 次に、明確な停止を示す一文を伝えます。例:実行する前に、いくつか確認させてください。
- このスキルで次の
ax手順に進むために必要なことだけを、最小限の番号付き質問または短い箇条書きで尋ねます。
フェーズ 1:現在のプロンプトを抽出する
プロンプトを含む LLM スパンを見つける
# Sample LLM spans (where prompts live)
ax spans export PROJECT --space SPACE --filter "attributes.openinference.span.kind = 'LLM'" -l 10 --stdout
# Filter by model
ax spans export PROJECT --space SPACE --filter "attributes.llm.model_name = 'gpt-4o'" -l 10 --stdout
# Filter by span name (e.g., a specific LLM call)
ax spans export PROJECT --space SPACE --filter "name = 'ChatCompletion'" -l 10 --stdout
トレースをエクスポートしてプロンプトの構造を調べる
# Export all spans in a trace
ax spans export PROJECT --space SPACE --trace-id TRACE_ID --stdout > spans.json
# Export a single span
ax spans export PROJECT --space SPACE --span-id SPAN_ID
エクスポートした JSON からプロンプトを抽出する
# Extract structured chat messages (system + user + assistant)
jq '.[0] | {
messages: .attributes.llm.input_messages,
model: .attributes.llm.model_name
}' spans.json
# Extract the system prompt specifically
jq '[.[] | select(.attributes.llm.input_messages.roles[]? == "system")] | .[0].attributes.llm.input_messages' spans.json
# Extract prompt template and variables
jq '.[0].attributes.llm.prompt_template' spans.json
# Extract from input.value (fallback for non-structured prompts)
jq '.[0].attributes.input.value' 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 --space SPACE \
--filter "status_code = 'ERROR' AND attributes.openinference.span.kind = 'LLM'" \
-l 20 --stdout
# Find spans with low eval scores
ax spans export PROJECT --space SPACE \
--filter "annotation.correctness.label = 'incorrect'" \
-l 20 --stdout
# Find spans with high latency (may indicate overly complex prompts)
ax spans export PROJECT --space SPACE \
--filter "attributes.openinference.span.kind = 'LLM' AND latency_ms > 10000" \
-l 20 --stdout
# Export error traces for detailed inspection
ax spans export PROJECT --space SPACE --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:プロンプトを最適化する
最適化メタプロンプト
references/optimization-meta-prompt.md にある 3 つのプレースホルダーを埋め、LLM(GPT-4o、Claude など)に送信して、改善版のプロンプトを生成します。
パフォーマンスデータの準備
レコードをテンプレートに貼り付ける前に、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
}]' spans.json
改訂したプロンプトを適用する
LLM が改訂した messages 配列を返したら:
- 元のプロンプトと改訂したプロンプトを並べて比較します
- すべてのテンプレート変数が保持されていることを確認します
- 書式に関する指示がそのまま維持されていることを確認します
- 全体に適用する前に、いくつかの例でテストします
フェーズ 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 --dataset DATASET_NAME --space SPACEを実行し、次にEXP_Bについても同様に実行します - 平均スコア、失敗率、個々の例での結果の変化を比較します
- リグレッションを確認します。つまり、プロンプト A では成功したものの、プロンプト B では失敗する例を確認します
プロンプトエンジニアリングのベストプラクティス
プロンプトを作成または改訂する際に、以下を適用してください:
| テクニック | 適用する状況 | 例 |
|---|---|---|
| 明確で詳細な指示 | 出力が曖昧、または話題から外れている場合 | 「感情を、positive、negative、neutral のいずれか 1 つだけで分類してください」 |
| 冒頭に指示を置く | モデルが後半の指示を無視する場合 | 例を示す前にタスクの説明を置きます |
| 段階的な分解 | 複雑な複数ステップの処理 | 「まずエンティティを抽出し、次にそれぞれを分類してから、要約してください」 |
| 具体的なペルソナ | 一貫したスタイルやトーンが必要な場合 | 「機関投資家向けに執筆する、経験豊富な金融アナリストです」 |
| 区切りトークン | セクションが混在してしまう場合 | ---、###、または XML タグを使用して、入力と指示を区切ります |
| 少数例による学習 | 出力形式を明確にする必要がある場合 | 合成した入出力のペアを 2~3 個示します |
| 出力の長さの指定 | 回答が長すぎる、または短すぎる場合 | 「ちょうど 2~3 文で回答してください」 |
| 推論に関する指示 | 正確性が重要な場合 | 「回答する前に、段階的に考えてください」 |
| 「わかりません」と答えるためのガイドライン | ハルシネーションのリスクがある場合 | 「回答が提供されたコンテキストに含まれていない場合は、『十分な情報がありません』と答えてください」 |
変数の保持
テンプレート変数を使うプロンプトを最適化する場合:
- 単一の波括弧(
{variable}):Python の f-string/Jinja 形式です。Arize では最も一般的です。 - 二重の波括弧(
{{variable}}):Mustache 形式です。フレームワークで必要な場合に使用します。 - 最適化中に変数プレースホルダーを追加または削除しないでください
- 変数名を変更しないでください。実行時の置換では名前が完全に一致している必要があります
- 少数例を追加する場合は、変数プレースホルダーではなくリテラル値を使用してください
ワークフロー
失敗したトレースからプロンプトを最適化する
- 失敗したトレース全体を 1 回の操作でエクスポートします:
ax traces export PROJECT --space SPACE --filter "status_code = 'ERROR'" -l 5 --stdout > failing.json - LLM スパン(エラーが発生した LLM スパンがある場合はそれ、ない場合は最初の LLM スパン)からプロンプトを抽出します:
jq '[.[] | select(.attributes.openinference.span.kind == "LLM")] | (map(select(.status_code == "ERROR"))[0] // .[0]) | { messages: .attributes.llm.input_messages, template: .attributes.llm.prompt_template, output: .attributes.output.value, error: .attributes.exception.message }' failing.json - エラーメッセージまたは出力から、何が失敗したのかを特定します
- プロンプトとエラーのコンテキストを使って、最適化用メタプロンプト(フェーズ 3)を埋めます
- 改訂したプロンプトを適用します
データセットと実験を使って最適化する
- データセットと実験をエクスポートします(不明な名前は
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 --space SPACE \ --filter "attributes.openinference.span.kind = 'LLM' AND annotation.format.label = 'incorrect'" \ -l 10 --stdout > bad_format.json - LLM の出力と期待される出力を比較します
- 明示的な形式の指示(JSON スキーマ、例、区切り文字)をプロンプトに追加します
- よくある修正方法:希望する出力形式を正確に示す少数例を追加します
RAG プロンプトのハルシネーションを減らす
- モデルがハルシネーションを起こしたトレースを見つけます:
ax spans export PROJECT --space SPACE \ --filter "annotation.faithfulness.label = 'unfaithful'" \ -l 20 --stdout - リトリーバーと LLM のスパンをまとめてエクスポートし、確認します:
ax spans export PROJECT --space SPACE --trace-id TRACE_ID --stdout > spans.json jq '[.[] | {kind: .attributes.openinference.span.kind, name, input: .attributes.input.value, output: .attributes.output.value}]' 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のエラー | 正しいファイルパスを指定していることを確認してください(例:--stdout > spans.jsonで出力したspans.json) |