关于 arize-prompt-optimization
面向使用 Arize 和 `ax` 命令行的团队,指导开展提示词优化。流程涵盖从 Trace 提取提示词和效果数据、修订提示词,以及通过实验测试和比较变更。
主要功能
- 01从 Trace Span 提取提示词
- 02检查标注和评估结果
- 03关联数据集与实验输出
- 04修订提示词并保留变量
- 05通过实验比较提示词版本
适用场景
- 01排查失败的 LLM Trace
- 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查找你的空间。
概念
提示词在追踪数据中的位置
大模型应用按照 OpenInference 语义约定发出 span。根据 span 类型和埋点方式的不同,提示词存储在不同的 span 属性中:
| 列 | 包含内容 | 使用时机 |
|---|---|---|
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 | 序列化的提示词或用户问题(通用,适用于所有 span 类型) | 结构化消息不可用时的回退方案 |
attributes.llm.prompt_template.template | 带 {variable} 占位符的模板(例如 "Answer {question} using {context}") | 应用使用提示词模板时 |
attributes.llm.prompt_template.variables | 模板变量值(JSON 对象) | 查看替换到模板中的实际值 |
attributes.output.value | 模型响应文本 | 查看大模型生成了什么 |
attributes.llm.output_messages | 结构化模型输出(包括工具调用) | 检查工具调用响应 |
按 Span 类型查找提示词
- LLM span(
attributes.openinference.span.kind = 'LLM'):在attributes.llm.input_messages中查看结构化聊天消息,或在attributes.input.value中查看序列化的提示词。在attributes.llm.prompt_template.template中查看模板。 - Chain/Agent span:
attributes.input.value包含用户的问题。实际的 LLM 提示词位于子 LLM span 上——沿追踪树向下查找。 - Tool span:
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 | 追踪数据 | 输入到大模型的内容 |
attributes.output.value | 追踪数据 | 大模型生成的内容 |
{experiment_name}.output | 实验运行 | 特定实验的输出 |
前置条件
直接开始执行任务 —— 运行你所需要的 ax 命令。不要预先检查版本、环境变量或 profiles。
如果 ax 命令失败,根据错误进行排查:
command not found或版本错误 → 参见 references/ax-setup.md401 Unauthorized/ 缺少 API key → 运行ax profiles show以检查当前 profile。如果 profile 缺失或 API key 有误,请按照 references/ax-profiles.md 创建/更新它。如果用户没有 key,请引导他们前往 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检查是否有平台托管的凭据。如果不存在,请让用户提供 key,或通过 arize-ai-provider-integration skill 创建集成 - 安全: 绝不要读取
.env文件或在文件系统中搜索凭据。Arize 凭据使用ax profiles,LLM 提供商 key 使用ax ai-integrations。如果通过这些渠道无法获得凭据,请询问用户。
阶段 1:提取当前提示词
查找包含提示词的 LLM span
# 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
导出一个 trace 以检查提示词结构
# 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
将提示词重建为 messages
一旦有了 span 数据,将提示词重建为 messages 数组:
[
{"role": "system", "content": "You are a helpful assistant that..."},
{"role": "user", "content": "Given {input}, answer the question: {question}"}
]
如果 span 包含 attributes.llm.prompt_template.template,则提示词使用了变量。保留这些占位符({variable} 或 {{variable}})—— 它们会在运行时被替换。
阶段 2:收集性能数据
来自 traces(生产反馈)
# 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
合并数据集 + 实验以进行分析
通过 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:优化提示词
优化元提示词
使用此模板生成提示词的改进版本。填入三个占位符,并将其发送给你的 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 返回修订后的 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
A/B 比较两个提示词
- 针对同一数据集创建两个实验,每个实验使用不同的提示词版本
- 导出两者:
ax experiments export EXP_A和ax experiments export EXP_B - 比较平均分数、失败率和具体示例的翻转情况
- 检查回归 —— 使用提示词 A 通过但使用提示词 B 失败的示例
提示词工程最佳实践
在编写或修改提示词时,请应用以下实践:
| 技巧 | 适用场景 | 示例 |
|---|---|---|
| 清晰、详细的指令 | 输出含糊或偏离主题 | “将情感分类为恰好以下之一:正面、负面、中性” |
| 将指令放在开头 | 模型忽略了后面的指令 | 将任务描述放在示例之前 |
| 逐步拆解 | 复杂的多步骤流程 | “首先抽取实体,然后对每个实体分类,最后总结” |
| 明确的角色设定 | 需要一致的风格/语气 | “你是一位资深金融分析师,为机构投资者撰写内容” |
| 分隔符标记 | 各部分内容混在一起 | 使用 ---、### 或 XML 标签将输入与指令分隔开 |
| 少样本示例 | 输出格式需要明确 | 展示 2-3 组合成的输入/输出示例 |
| 输出长度说明 | 回复过长或过短 | “用恰好 2-3 句话回答” |
| 推理指令 | 准确性至关重要 | “在回答前逐步思考” |
| “我不知道”准则 | 存在幻觉风险 | “如果答案不在提供的上下文中,请说‘我没有足够的信息’” |
变量保留
在优化使用模板变量的提示词时:
- 单花括号(
{variable}):Python f-string / Jinja 风格。在 Arize 中最常见。 - 双花括号(
{{variable}}):Mustache 风格。在框架要求时使用。 - 在优化过程中绝不要添加或移除变量占位符
- 绝不要重命名变量——运行时替换依赖于精确的名称
- 如果添加少样本示例,请使用字面值,而不是变量占位符
工作流
根据失败 trace 优化提示词
- 查找失败的 trace:
ax traces list PROJECT --filter "status_code = 'ERROR'" --limit 5 - 导出该 trace:
ax spans export PROJECT --trace-id TRACE_ID - 从 LLM span 中提取提示词:
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 - 为元提示词准备连接后的数据
- 运行优化元提示词
- 使用修改后的提示词创建新实验以衡量改进效果
调试产生错误格式的提示词
- 导出输出格式错误的 span:
ax spans export PROJECT \ --filter "attributes.openinference.span.kind = 'LLM' AND annotation.format.label = 'incorrect'" \ -l 10 --stdout > bad_format.json - 查看 LLM 实际产生的内容与预期内容的差异
- 向提示词添加明确的格式指令(JSON schema、示例、分隔符)
- 常见修复方法:添加一个少样本示例,展示确切的期望输出格式
减少 RAG 提示词中的幻觉
- 查找模型产生幻觉的 trace:
ax spans export PROJECT \ --filter "annotation.faithfulness.label = 'unfaithful'" \ -l 20 --stdout - 同时导出并检查检索器 + LLM span:
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 | 未配置 profile。参见 references/ax-profiles.md 创建一个。 |
span 上没有 input_messages | 检查 span 类型 —— Chain/Agent span 将提示词存储在子 LLM span 上,而不是自身 |
提示词模板为 null | 并非所有插桩都会生成 prompt_template。请改用 input_messages 或 input.value |
| 优化后变量丢失 | 验证修改后的提示词是否保留了原始提示词中的所有 {var} 占位符 |
| 优化后效果变差 | 检查是否过拟合 —— 元提示词可能已记住了测试数据。确保少样本示例是合成的 |
| 没有 eval/annotation 列 | 先运行评估(通过 Arize UI 或 SDK),然后重新导出 |
| 找不到实验输出列 | 列名为 {experiment_name}.output —— 通过 ax experiments get 检查确切的实验名称 |
jq 在 span JSON 上报错 | 确保指向了正确的文件路径(例如 trace_*/spans.json) |