chore: import zh skill reasoning-trace-optimizer
This commit is contained in:
@@ -0,0 +1,619 @@
|
||||
# Reasoning Trace Optimizer
|
||||
|
||||
<p align="center">
|
||||
<strong>通过 MiniMax M2.1 的交错式思考能力,分析和调试 AI 智能体的推理过程并进行优化</strong>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#key-features">功能特性</a> |
|
||||
<a href="#quick-start">快速开始</a> |
|
||||
<a href="#how-it-works">工作原理</a> |
|
||||
<a href="#examples">示例</a> |
|
||||
<a href="#api-reference">API 参考</a>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## 问题
|
||||
|
||||
传统 AI 智能体以不透明的方式失败。你只能看到最终输出,却看不到决策背后的**原因**。当智能体:
|
||||
- 调用了错误的工具
|
||||
- 偏离了目标
|
||||
- 编造信息
|
||||
|
||||
……你只能猜测问题出在哪里。
|
||||
|
||||
## 解决方案
|
||||
|
||||
**Reasoning Trace Optimizer** 利用 MiniMax M2.1 独特的**交错式思考**能力,在每次工具调用之间暴露智能体的推理过程。这使得以下功能成为可能:
|
||||
|
||||
1. **深度调试** —— 准确找出推理偏离预期行为的位置
|
||||
2. **模式检测** —— 自动识别失败模式(上下文退化、工具混淆等)
|
||||
3. **自动优化** —— 根据检测到的问题生成改进后的提示词
|
||||
4. **可分享的技能** —— 将学习成果转换为可复用的 Agent Skill,供团队共享
|
||||
|
||||
## 为什么选择 MiniMax M2.1?
|
||||
|
||||
M2.1 的**交错式思考**与传统推理模型有本质区别:
|
||||
|
||||
```
|
||||
传统模型: 思考 → 行动 → 行动 → 行动 → 完成
|
||||
↑
|
||||
(仅在开始时推理)
|
||||
|
||||
M2.1: 思考 → 行动 → 思考 → 行动 → 思考 → 行动 → 完成
|
||||
↑ ↑ ↑
|
||||
(在每次工具调用之间持续推理)
|
||||
```
|
||||
|
||||
这对智能体至关重要,因为:
|
||||
- **长任务**需要在多次交互中保持专注
|
||||
- **工具输出**会引入意料之外的信息,需要自适应调整
|
||||
- **调试**需要洞察决策过程,而不仅仅是输出结果
|
||||
|
||||
`thinking` 块(Anthropic SDK)或 `reasoning_details` 字段(OpenAI SDK)将推理过程暴露出来供分析。
|
||||
|
||||
---
|
||||
|
||||
## 关键特性
|
||||
|
||||
| 组件 | 描述 |
|
||||
|-----------|-------------|
|
||||
| **TraceCapture** | 包装 M2.1 API,捕获所有思考块及其完整上下文 |
|
||||
| **TraceAnalyzer** | 检测上下文退化、工具混淆、指令漂移等模式 |
|
||||
| **PromptOptimizer** | 基于分析结果,利用 M2.1 生成改进后的提示词 |
|
||||
| **OptimizationLoop** | 自动化的捕获 → 分析 → 改进 → 重新运行的循环 |
|
||||
| **SkillGenerator** | 将学习成果转换为可分享的 Agent Skill |
|
||||
|
||||
### 模式检测
|
||||
|
||||
分析器会自动识别以下失败模式:
|
||||
|
||||
| 模式 | 描述 | 严重程度 |
|
||||
|---------|-------------|----------|
|
||||
| `context_degradation` | 模型在长上下文中丢失信息 | 高 |
|
||||
| `tool_confusion` | 模型误解工具能力 | 高 |
|
||||
| `instruction_drift` | 模型偏离原始指令 | 中 |
|
||||
| `hallucination` | 模型生成无依据的信息 | 严重 |
|
||||
| `goal_abandonment` | 模型不再追求原始目标 | 高 |
|
||||
| `circular_reasoning` | 模型重复类似动作而无进展 | 中 |
|
||||
| `premature_conclusion` | 模型在完成任务前提前得出结论 | 中 |
|
||||
| `missing_validation` | 模型不验证结果 | 高 |
|
||||
|
||||
每个检测到的模式包括:
|
||||
- **证据** —— 思考块中的具体摘录
|
||||
- **严重程度** —— 严重/高/中/低
|
||||
- **建议** —— 对提示词的具体改进方案
|
||||
- **置信度** —— 检测结果的可靠程度
|
||||
|
||||
---
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 安装
|
||||
|
||||
```bash
|
||||
cd examples/interleaved-thinking
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
### 配置
|
||||
|
||||
设置你的 MiniMax API 密钥:
|
||||
|
||||
```bash
|
||||
export ANTHROPIC_API_KEY=your_minimax_api_key
|
||||
export ANTHROPIC_BASE_URL=https://api.minimax.io/anthropic
|
||||
```
|
||||
|
||||
或者创建一个 `.env` 文件:
|
||||
|
||||
```env
|
||||
ANTHROPIC_API_KEY=your_minimax_api_key
|
||||
ANTHROPIC_BASE_URL=https://api.minimax.io/anthropic
|
||||
```
|
||||
|
||||
### 基本用法
|
||||
|
||||
```python
|
||||
from reasoning_trace_optimizer import TraceCapture, TraceAnalyzer
|
||||
|
||||
# 捕获推理轨迹
|
||||
capture = TraceCapture()
|
||||
trace = capture.run(
|
||||
task="解释量子计算",
|
||||
system_prompt="你是一名科学教育者。"
|
||||
)
|
||||
|
||||
print(f"捕获到 {len(trace.thinking_blocks)} 个思考块")
|
||||
|
||||
# 分析推理过程
|
||||
analyzer = TraceAnalyzer()
|
||||
analysis = analyzer.analyze(trace)
|
||||
|
||||
print(f"总体评分:{analysis.overall_score}/100")
|
||||
for pattern in analysis.patterns:
|
||||
print(f" [{pattern.severity.value}] {pattern.type.value}")
|
||||
print(f" 建议:{pattern.suggestion}")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 工作原理
|
||||
|
||||
### 优化循环
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ 优化循环 │
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ 智能体 │───▶│ 捕获 │───▶│ 分析 │───▶│ 优化 │ │
|
||||
│ │ 执行 │ │ 轨迹 │ │ 模式 │ │ 提示词 │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
|
||||
│ ▲ │ │
|
||||
│ └───────────────────────────────────────────────┘ │
|
||||
│ (循环直至收敛或达到最大迭代次数) │
|
||||
│ │
|
||||
│ 收敛条件:评分改善 < 阈值 或 评分 > 目标值 │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 捕获的内容
|
||||
|
||||
每次智能体执行时,我们捕获:
|
||||
|
||||
1. **思考块** —— M2.1 在每次动作之前的推理过程
|
||||
2. **工具调用** —— 调用了哪些工具以及相应的输入
|
||||
3. **工具结果** —— 每个工具返回的结果
|
||||
4. **最终响应** —— 智能体的输出
|
||||
5. **元数据** —— 使用的 Token 数、交互次数、成功/失败状态
|
||||
|
||||
### 分析的内容
|
||||
|
||||
分析器检查思考块以了解:
|
||||
|
||||
- **当前理解** —— 智能体对任务的理解是什么?
|
||||
- **工具解读** —— 它如何解读每个工具的结果?
|
||||
- **备选方案** —— 它评估了哪些选项?
|
||||
- **目标意识** —— 它是否仍在追求原始目标?
|
||||
|
||||
---
|
||||
|
||||
## 示例
|
||||
|
||||
### 示例 1:基本轨迹捕获
|
||||
|
||||
```python
|
||||
# examples/01_basic_capture.py
|
||||
from reasoning_trace_optimizer import TraceCapture
|
||||
|
||||
capture = TraceCapture()
|
||||
trace = capture.run(
|
||||
task="解释什么是交错式思考,以及它为什么对 AI 智能体很重要。",
|
||||
system_prompt="你是一名 AI 研究员,需清晰地解释概念。"
|
||||
)
|
||||
|
||||
# 输出:
|
||||
# 捕获到 1 个思考块
|
||||
# 第 0 轮:"用户要求我解释'交错式思考'..."
|
||||
```
|
||||
|
||||
### 示例 2:带分析的工具使用
|
||||
|
||||
```python
|
||||
# examples/02_tool_usage.py
|
||||
from reasoning_trace_optimizer import TraceCapture, TraceAnalyzer
|
||||
|
||||
# 定义工具
|
||||
tools = [
|
||||
{
|
||||
"name": "get_weather",
|
||||
"description": "获取指定城市的当前天气",
|
||||
"input_schema": {...}
|
||||
}
|
||||
]
|
||||
|
||||
capture = TraceCapture()
|
||||
trace = capture.run(
|
||||
task="比较旧金山和纽约的天气",
|
||||
tools=tools,
|
||||
tool_executor=execute_tool
|
||||
)
|
||||
|
||||
# 分析
|
||||
analyzer = TraceAnalyzer()
|
||||
analysis = analyzer.analyze(trace)
|
||||
|
||||
# 输出:
|
||||
# 评分:85/100
|
||||
# 思考块数:3
|
||||
# 工具调用次数:4(get_weather x2,get_forecast x2)
|
||||
# 模式:未检测到
|
||||
```
|
||||
|
||||
### 示例 3:完整优化循环
|
||||
|
||||
本示例演示了一个包含 7 个工具(网页搜索、文件操作、笔记记录)的复杂研究任务:
|
||||
|
||||
```python
|
||||
# examples/03_full_optimization.py
|
||||
from reasoning_trace_optimizer import OptimizationLoop, LoopConfig, SkillGenerator
|
||||
|
||||
config = LoopConfig(
|
||||
max_iterations=3,
|
||||
min_score_threshold=85.0,
|
||||
convergence_threshold=5.0,
|
||||
save_artifacts=True,
|
||||
)
|
||||
|
||||
loop = OptimizationLoop(config=config)
|
||||
result = loop.run(
|
||||
task="""研究"面向 AI 智能体的上下文工程"并创建一份摘要……""",
|
||||
initial_prompt="你是一名研究助手。",
|
||||
tools=TOOLS,
|
||||
tool_executor=execute_tool,
|
||||
)
|
||||
|
||||
# 生成可分享的技能
|
||||
generator = SkillGenerator()
|
||||
skill_path = generator.generate(result, skill_name="research-agent")
|
||||
```
|
||||
|
||||
**示例 3 的实际输出:**
|
||||
|
||||
```
|
||||
======================================================================
|
||||
优化结果
|
||||
======================================================================
|
||||
|
||||
总迭代次数:3
|
||||
已收敛:是
|
||||
|
||||
迭代 1(评分:69/100)
|
||||
├── 任务完成:是
|
||||
├── 思考块数:6
|
||||
├── 工具调用次数:16
|
||||
├── 发现模式数:2
|
||||
│ ├── [低] missing_validation
|
||||
│ └── [低] incomplete_reasoning
|
||||
├── 优势:出色的目标保持力,全面的来源多样性
|
||||
└── 警告:提示词过大(2979 字符),已限制增长
|
||||
|
||||
迭代 2(评分:60/100) ← 检测到退化!
|
||||
├── 任务完成:是
|
||||
├── 思考块数:8
|
||||
├── 工具调用次数:16
|
||||
├── 发现模式数:3
|
||||
│ ├── [中] incomplete_reasoning
|
||||
│ ├── [中] missing_validation
|
||||
│ └── [低] tool_misuse
|
||||
|
||||
迭代 3(评分:66/100)
|
||||
├── 任务完成:是
|
||||
├── 思考块数:8
|
||||
├── 工具调用次数:16
|
||||
└── 发现模式数:3
|
||||
|
||||
→ 使用来自迭代 1 的最佳提示词(评分:67.6)
|
||||
|
||||
所有迭代中的工具使用情况:
|
||||
├── read_url:20 次调用
|
||||
├── web_search:12 次调用
|
||||
├── list_directory:7 次调用
|
||||
├── save_note:6 次调用
|
||||
└── write_file:3 次调用
|
||||
|
||||
已保存的笔记:6 篇研究笔记,含标签化发现
|
||||
已写入的文件:./output/research_summary.md(11,357 字符)
|
||||
|
||||
已生成的技能:./generated_skills/comprehensive-research-agent/SKILL.md
|
||||
```
|
||||
|
||||
**演示的关键特性:**
|
||||
|
||||
1. **提示词增长限制** —— 将提示词扩展限制为原始大小的 3 倍,防止膨胀
|
||||
2. **最佳评分追踪** —— 自动使用表现最佳的提示词,即使后续迭代出现退化
|
||||
3. **退化检测** —— 在评分下降时发出警告,可在连续退化后停止
|
||||
|
||||
---
|
||||
|
||||
## 生成的产物
|
||||
|
||||
### 优化产物
|
||||
|
||||
每次优化运行都会创建可供检查的产物:
|
||||
|
||||
```
|
||||
optimization_artifacts/
|
||||
├── summary.json # 总体结果
|
||||
├── final_prompt.txt # 优化后的提示词
|
||||
├── iteration_1/
|
||||
│ ├── trace.json # 完整推理轨迹
|
||||
│ ├── analysis.json # 模式检测结果
|
||||
│ └── optimization.json # 提示词变更记录
|
||||
├── iteration_2/
|
||||
│ └── ...
|
||||
└── iteration_3/
|
||||
└── ...
|
||||
```
|
||||
|
||||
### 生成的技能
|
||||
|
||||
SkillGenerator 将优化学习成果转换为可分享的 Agent Skill:
|
||||
|
||||
```
|
||||
generated_skills/
|
||||
└── comprehensive-research-agent/
|
||||
├── SKILL.md # 可分享的技能
|
||||
└── references/
|
||||
├── optimization_summary.json
|
||||
├── optimized_prompt.txt
|
||||
└── patterns_found.json
|
||||
```
|
||||
|
||||
**生成的技能内容示例:**
|
||||
|
||||
```markdown
|
||||
## 需避免的模式
|
||||
|
||||
- **缺少验证**:对工具响应照单全收,未验证实际状态变更是否发生。
|
||||
- **编造来源**:引用加载失败的来源。
|
||||
- **忽略矛盾**:在工具结果相互冲突时仍继续执行。
|
||||
|
||||
## 推荐实践
|
||||
|
||||
- 每次工具调用后,明确陈述结果
|
||||
- 分别追踪来源:'已尝试' 与 '已成功'
|
||||
- 使用替代方法实现错误恢复
|
||||
- 对关键声明进行多来源交叉验证
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API 参考
|
||||
|
||||
### TraceCapture
|
||||
|
||||
```python
|
||||
capture = TraceCapture(
|
||||
api_key="...", # MiniMax API 密钥
|
||||
base_url="https://api.minimax.io/anthropic", # API 端点
|
||||
model="MiniMax-M2.1" # 使用的模型
|
||||
)
|
||||
|
||||
trace = capture.run(
|
||||
task="...", # 要执行的任务
|
||||
system_prompt="...", # 系统提示词
|
||||
tools=[...], # 工具定义(Anthropic 格式)
|
||||
tool_executor=fn, # 执行工具的函数
|
||||
max_turns=10, # 最大对话轮数
|
||||
max_tokens=4096 # 每次响应的最大 Token 数
|
||||
)
|
||||
```
|
||||
|
||||
### TraceAnalyzer
|
||||
|
||||
```python
|
||||
analyzer = TraceAnalyzer(
|
||||
api_key="...",
|
||||
base_url="https://api.minimax.io/anthropic",
|
||||
model="MiniMax-M2.1"
|
||||
)
|
||||
|
||||
analysis = analyzer.analyze(trace)
|
||||
# 返回:包含模式、评分和建议的 AnalysisResult
|
||||
|
||||
quick_score = analyzer.quick_score(trace)
|
||||
# 返回:快速反馈用的浮点数(0-100)
|
||||
```
|
||||
|
||||
### OptimizationLoop
|
||||
|
||||
```python
|
||||
config = LoopConfig(
|
||||
# 迭代控制
|
||||
max_iterations=5, # 最大优化迭代次数
|
||||
convergence_threshold=3.0, # 改善幅度低于此值时停止
|
||||
min_score_threshold=75.0, # 评分超过此值时停止
|
||||
regression_threshold=8.0, # 评分下降幅度超过此值时发出警告
|
||||
|
||||
# 优化行为
|
||||
use_best_prompt=True, # 使用表现最佳的提示词,而非最后一轮的
|
||||
max_prompt_growth=5.0, # 提示词扩展限制为原始大小的 5 倍
|
||||
|
||||
# 输出选项
|
||||
save_artifacts=True, # 保存轨迹和分析结果
|
||||
artifacts_dir="./artifacts" # 保存位置
|
||||
)
|
||||
|
||||
loop = OptimizationLoop(config=config)
|
||||
result = loop.run(task, initial_prompt, tools, tool_executor)
|
||||
# 返回:包含迭代记录、最终提示词和评分的 LoopResult
|
||||
```
|
||||
|
||||
**优化安全保障:**
|
||||
|
||||
- **最佳提示词追踪**:保留产生最高评分的提示词
|
||||
- **提示词增长限制**:限制提示词大小膨胀
|
||||
- **退化检测**:在评分下降时发出警告,连续退化后停止
|
||||
|
||||
**评分预期:**
|
||||
|
||||
| 任务复杂度 | 典型评分范围 | 说明 |
|
||||
|-----------------|---------------------|-------|
|
||||
| 简单(1-2 个工具) | 80-95 | 直接任务快速收敛 |
|
||||
| 中等(3-5 个工具) | 70-85 | 多工具协同增加变数 |
|
||||
| 复杂(6+ 个工具,多步骤) | 60-75 | 长推理链的固有波动 |
|
||||
|
||||
包含大量工具和步骤的复杂研究任务通常稳定在 **65-75** 分,原因包括:
|
||||
- 工具输出差异影响推理路径
|
||||
- 多种有效方法导致不同评分
|
||||
- 多步智能体执行的随机性
|
||||
|
||||
优化器侧重于**相对改进**和**模式消除**,而非追求特定的绝对分数。
|
||||
|
||||
### SkillGenerator
|
||||
|
||||
```python
|
||||
generator = SkillGenerator()
|
||||
skill_path = generator.generate(
|
||||
result=loop_result, # 来自 OptimizationLoop
|
||||
skill_name="my-skill", # 小写加连字符
|
||||
output_dir="./generated_skills",
|
||||
title="人类可读的标题"
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CLI 使用
|
||||
|
||||
```bash
|
||||
# 捕获推理轨迹
|
||||
rto capture "解释交错式思考" -s "你是一名 AI 研究员。"
|
||||
|
||||
# 分析任务并输出结果
|
||||
rto analyze "调试这段代码片段" -o analysis.txt
|
||||
|
||||
# 运行完整优化循环
|
||||
rto optimize "研究 AI 论文" --max-iterations 5 --generate-skill
|
||||
|
||||
# 从之前的优化生成技能
|
||||
rto generate-skill my-skill-name --artifacts-dir ./optimization_artifacts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 使用的真实来源
|
||||
|
||||
示例 3 使用真实文档 URL 进行逼真模拟:
|
||||
|
||||
| 来源 | URL |
|
||||
|--------|-----|
|
||||
| Anthropic 文档 | `docs.anthropic.com/en/docs/build-with-claude/*` |
|
||||
| Anthropic 研究 | `anthropic.com/research/building-effective-agents` |
|
||||
| OpenAI 文档 | `platform.openai.com/docs/guides/*` |
|
||||
| MiniMax M2.1 | `minimax.io/platform/docs/M2.1` |
|
||||
| DAIR.AI | `promptingguide.ai/techniques` |
|
||||
| LangChain | `python.langchain.com/docs/how_to/debugging` |
|
||||
| arXiv 论文 | `arxiv.org/abs/2307.03172`(Lost in the Middle) |
|
||||
|
||||
---
|
||||
|
||||
## 健壮性特性
|
||||
|
||||
优化器包含多项安全保障以应对现实中的不确定性:
|
||||
|
||||
### 解析弹性
|
||||
|
||||
LLM 响应并不总是产生有效的 JSON。系统能优雅处理此问题:
|
||||
|
||||
| 组件 | 降级行为 |
|
||||
|-----------|-------------------|
|
||||
| **Analyzer** | JSON 失败时通过正则表达式提取评分;默认为 50/100(而非 0) |
|
||||
| **Optimizer** | 多策略提示词提取:JSON → 正则 → 标记检测 → 代码块 |
|
||||
| **Loop** | 最终提示词未变化时发出警告;追踪表现最佳的迭代 |
|
||||
|
||||
### 扩展测试结果(10 次迭代)
|
||||
|
||||
真实环境测试揭示了重要见解:
|
||||
|
||||
```
|
||||
迭代 评分 模式数 工具调用次数 备注
|
||||
────────────────────────────────────────────────
|
||||
1 69/100 4 22 基线
|
||||
2 66/100 3 14 -
|
||||
3 61/100 3 17 -
|
||||
4 72/100 3 20 ← 最佳评分
|
||||
5 59/100 4 16 -
|
||||
6 50/100* 0 15 *解析器降级触发
|
||||
7 70/100 3 12 恢复
|
||||
8 64/100 3 14 -
|
||||
9 64/100 3 18 -
|
||||
10 70/100 3 19 最终
|
||||
|
||||
* 迭代 6:JSON 解析失败,降级返回中性评分
|
||||
```
|
||||
|
||||
**关键发现:**
|
||||
- 由于模型的随机行为,迭代间评分波动 ±15 分
|
||||
- 最佳评分(72)出现在运行中期,而非末尾
|
||||
- `use_best_prompt=True` 正确选择了迭代 4 的提示词
|
||||
- 解析失败现在被优雅处理,而非返回 0 分
|
||||
|
||||
---
|
||||
|
||||
## 架构
|
||||
|
||||
```
|
||||
reasoning_trace_optimizer/
|
||||
├── __init__.py # 公共 API 导出
|
||||
├── models.py # 数据模型(Pydantic)
|
||||
│ ├── ThinkingBlock # 单个推理片段
|
||||
│ ├── ToolCall # 工具调用记录
|
||||
│ ├── ReasoningTrace # 完整执行轨迹
|
||||
│ ├── Pattern # 检测到的失败模式
|
||||
│ ├── AnalysisResult # 完整分析输出
|
||||
│ └── LoopResult # 优化循环结果
|
||||
├── capture.py # TraceCapture - M2.1 API 包装器
|
||||
├── analyzer.py # TraceAnalyzer - 模式检测(含降级解析)
|
||||
├── optimizer.py # PromptOptimizer - 提示词改进(含降级提取)
|
||||
├── loop.py # OptimizationLoop - 完整循环(含最佳评分追踪)
|
||||
├── skill_generator.py # SkillGenerator - 创建技能
|
||||
└── cli.py # 命令行界面
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 集成
|
||||
|
||||
### Claude Code Skill
|
||||
|
||||
本项目包含一个 Claude Code 技能(`SKILL.md`),支持:
|
||||
|
||||
- **失败时自动触发** —— 当智能体任务失败时自动进行分析
|
||||
- **按需分析** —— 使用 `/reasoning-trace-optimizer` 命令
|
||||
- **会话分析** —— 分析当前对话中的思考过程
|
||||
|
||||
### Python 库
|
||||
|
||||
```python
|
||||
from reasoning_trace_optimizer import (
|
||||
TraceCapture,
|
||||
TraceAnalyzer,
|
||||
PromptOptimizer,
|
||||
OptimizationLoop,
|
||||
LoopConfig,
|
||||
SkillGenerator,
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 贡献
|
||||
|
||||
本项目是 [Agent Skills for Context Engineering](https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering) 系列的一部分。
|
||||
|
||||
---
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT License
|
||||
|
||||
---
|
||||
|
||||
## 参考资料
|
||||
|
||||
- [MiniMax M2.1 文档](https://www.minimax.io/platform/docs)
|
||||
- [MiniMax API 参考](https://www.minimax.io/platform/docs/M2.1)
|
||||
- [交错式思考指南](./docs/interleavedthinking.md)
|
||||
- [智能体泛化研究](./docs/agentthinking.md)
|
||||
- [Anthropic API 兼容性](./docs/m2-1.md)
|
||||
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
<strong>与 MiniMax AI 合作构建</strong><br>
|
||||
展示交错式思考在智能体调试中的强大能力
|
||||
</p>
|
||||
@@ -0,0 +1,9 @@
|
||||
# WeHub 来源说明
|
||||
|
||||
- Skill 名称:`reasoning-trace-optimizer`
|
||||
- 中文类目:上下文退化诊断与 Agent 调试
|
||||
- 上游仓库:`muratcankoylan__agent-skills-for-context-engineering`
|
||||
- 上游路径:`examples/interleaved-thinking/SKILL.md`
|
||||
- 上游链接:https://github.com/muratcankoylan/agent-skills-for-context-engineering/blob/HEAD/examples/interleaved-thinking/SKILL.md
|
||||
- 本仓库为 WeHub 中文 Skill 汉化包,基于 skill 市场筛选 Top200 清单整理
|
||||
- 原作者、版权和许可证信息以上游仓库为准
|
||||
@@ -0,0 +1,221 @@
|
||||
---
|
||||
name: reasoning-trace-optimizer
|
||||
description: "调试和优化 AI 智能体——通过分析推理轨迹、上下文退化、工具混淆、指令漂移、重复任务失败及性能回归。"
|
||||
---
|
||||
|
||||
# 推理轨迹优化器
|
||||
|
||||
通过分析 AI 智能体的推理轨迹来调试和优化它们。本技能利用 MiniMax M2.1 的交错式思考,深入洞察智能体的决策过程,并生成具体的改进方案。
|
||||
|
||||
## 何时激活
|
||||
|
||||
- 需要对智能体推理轨迹进行调试、分析或提示词优化时
|
||||
- 智能体任务失败,用户想了解原因时
|
||||
- 用户提到"上下文退化"、"工具混淆"或"指令漂移"时
|
||||
- 需要提升智能体性能或减少错误时
|
||||
- 用户希望从调试会话中生成可分享的经验时
|
||||
- 类似任务反复失败后
|
||||
|
||||
## 核心概念
|
||||
|
||||
### 交错式思考
|
||||
|
||||
与标准推理模型在开始时一次性思考不同,交错式思考允许在每次工具交互之间进行推理。这一点至关重要,因为:
|
||||
|
||||
1. **长程任务** 需要在多个轮次中保持专注
|
||||
2. **外部扰动**(工具输出、环境变化)需要实时适应
|
||||
3. **调试** 需要了解决策是**如何**做出的,而不仅仅是输出了**什么**
|
||||
|
||||
### 优化循环
|
||||
|
||||
```
|
||||
执行智能体 → 捕获轨迹 → 分析模式 → 优化提示词 → 重新运行
|
||||
↑____________|
|
||||
```
|
||||
|
||||
每次迭代根据检测到的模式改进提示词,直至收敛。
|
||||
|
||||
### 模式检测
|
||||
|
||||
分析器可检测的常见失败模式:
|
||||
|
||||
| 模式 | 描述 |
|
||||
|---------|-------------|
|
||||
| `context_degradation` | 模型在长上下文中丢失信息 |
|
||||
| `tool_confusion` | 模型误解工具能力或输出 |
|
||||
| `instruction_drift` | 模型逐渐偏离原始指令 |
|
||||
| `goal_abandonment` | 模型停止追求原始目标 |
|
||||
| `circular_reasoning` | 模型重复相似动作而无进展 |
|
||||
| `premature_conclusion` | 模型在完成任务前过早得出结论 |
|
||||
|
||||
## 使用模式
|
||||
|
||||
### 模式 1:M2.1 智能体调试
|
||||
|
||||
通过 M2.1 运行任务并分析其推理过程:
|
||||
|
||||
```python
|
||||
from reasoning_trace_optimizer import TraceCapture, TraceAnalyzer
|
||||
|
||||
capture = TraceCapture()
|
||||
trace = capture.run(
|
||||
task="搜索 Python 教程并总结它们",
|
||||
system_prompt="你是一名研究助手。",
|
||||
tools=[search_tool],
|
||||
tool_executor=execute_search
|
||||
)
|
||||
|
||||
analyzer = TraceAnalyzer()
|
||||
analysis = analyzer.analyze(trace)
|
||||
|
||||
print(f"得分: {analysis.overall_score}/100")
|
||||
for pattern in analysis.patterns:
|
||||
print(f"发现: {pattern.type.value} - {pattern.suggestion}")
|
||||
```
|
||||
|
||||
### 模式 2:完整优化循环
|
||||
|
||||
自动迭代直至提示词优化完成:
|
||||
|
||||
```python
|
||||
from reasoning_trace_optimizer import OptimizationLoop, LoopConfig
|
||||
|
||||
config = LoopConfig(
|
||||
max_iterations=5,
|
||||
min_score_threshold=80.0,
|
||||
)
|
||||
|
||||
loop = OptimizationLoop(config=config)
|
||||
result = loop.run(
|
||||
task="分析此代码库并提出改进建议",
|
||||
initial_prompt="你是一名代码审查者。",
|
||||
tools=[read_file_tool, search_tool],
|
||||
tool_executor=execute_tool
|
||||
)
|
||||
|
||||
print(f"改进: {result.initial_score} → {result.final_score}")
|
||||
print(f"最终提示词:\n{result.final_prompt}")
|
||||
```
|
||||
|
||||
### 模式 3:通用会话分析
|
||||
|
||||
分析任意智能体的过往思考(适用于 Claude、GPT 等):
|
||||
|
||||
当本技能在 Claude Code 中被激活时,它可以分析当前会话的思考块,以识别问题并提出改进建议。
|
||||
|
||||
```
|
||||
/reasoning-trace-optimizer analyze-session
|
||||
```
|
||||
|
||||
### 模式 4:生成可分享的技能
|
||||
|
||||
将优化经验转化为可复用的智能体技能:
|
||||
|
||||
```python
|
||||
from reasoning_trace_optimizer import SkillGenerator
|
||||
|
||||
generator = SkillGenerator()
|
||||
skill_path = generator.generate(
|
||||
result=loop_result,
|
||||
skill_name="web-search-best-practices",
|
||||
output_dir="./skills"
|
||||
)
|
||||
```
|
||||
|
||||
## CLI 命令
|
||||
|
||||
```bash
|
||||
# 捕获推理轨迹
|
||||
rto capture "搜索 Python 教程" -s "你是一名有用的助手。"
|
||||
|
||||
# 分析任务
|
||||
rto analyze "调试此代码" -o analysis.txt
|
||||
|
||||
# 运行优化循环
|
||||
rto optimize "研究 AI 论文" --max-iterations 5 --generate-skill
|
||||
|
||||
# 从产物生成技能
|
||||
rto generate-skill my-skill-name --artifacts-dir ./optimization_artifacts
|
||||
```
|
||||
|
||||
## 与 Claude Code 集成
|
||||
|
||||
### 失败时自动触发
|
||||
|
||||
添加到你的 hooks 中以自动分析失败:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"post_tool_error": {
|
||||
"command": "rto analyze-session --last-error"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 按需分析
|
||||
|
||||
使用斜杠命令分析当前会话:
|
||||
|
||||
```
|
||||
/reasoning-trace-optimizer
|
||||
```
|
||||
|
||||
将:
|
||||
1. 提取当前会话中的思考块
|
||||
2. 识别模式与问题
|
||||
3. 提出提示词改进建议
|
||||
4. 可选地更新系统提示词
|
||||
|
||||
## 使用指南
|
||||
|
||||
1. **保留完整上下文**:M2.1 需要包含思考块的完整响应历史以获得最佳性能
|
||||
2. **使用合适的工具**:用明确无歧义的描述定义工具
|
||||
3. **设置合理的收敛阈值**:每次迭代提升 5–10% 为典型范围
|
||||
4. **审查生成的技能**:自动生成的技能在分享前应经过审查
|
||||
5. **监控 Token 用量**:每次优化迭代会消耗大量 Token
|
||||
|
||||
## 示例
|
||||
|
||||
### 优化前
|
||||
|
||||
```
|
||||
System: 你是一名有用的助手。
|
||||
|
||||
问题: 智能体调用了错误的工具,3 轮后丢失了目标
|
||||
得分: 45/100
|
||||
模式: tool_confusion, goal_abandonment
|
||||
```
|
||||
|
||||
### 优化后
|
||||
|
||||
```
|
||||
System: 你是一名专注于查找准确信息的研究助手。
|
||||
|
||||
重要指南:
|
||||
- 在总结之前务必验证搜索结果
|
||||
- 如果工具返回错误,尝试替代方法
|
||||
- 在整个任务过程中始终记住你的原始目标
|
||||
- 尽可能通过多个来源验证发现
|
||||
|
||||
问题: 无
|
||||
得分: 85/100
|
||||
模式: 未检测到
|
||||
```
|
||||
|
||||
## 参考资料
|
||||
|
||||
- MiniMax M2.1 文档:https://platform.minimax.io/docs
|
||||
- 交错式思考指南:参见 `docs/interleavedthinking.md`
|
||||
- 智能体泛化:参见 `docs/agentthinking.md`
|
||||
|
||||
---
|
||||
|
||||
## 技能元数据
|
||||
|
||||
**创建日期**:2025-01-11
|
||||
**作者**:Muratcan Koylan
|
||||
**版本**:0.1.0
|
||||
**技术支持**:MiniMax M2.1
|
||||
**合作**:与 MiniMax AI 协作构建
|
||||
@@ -0,0 +1,67 @@
|
||||
# 对齐到什么?重新思考 MiniMax M2 中的智能体泛化
|
||||
|
||||
很高兴看到社区深入使用我们的新模型 [**MiniMax M2**](https://huggingface.co/MiniMaxAI/MiniMax-M2),许多人对其在复杂智能体任务中的出色能力给予了高度评价。这尤其令我激动,因为我的工作重点正是其后训练阶段中的智能体对齐部分。在这篇文章中,我想分享我们在这一过程中收获的一些关键见解与经验教训。
|
||||
|
||||
## **真正的智能体对齐问题:基准测试还是现实?**
|
||||
|
||||
如果你曾使用过 LLM 智能体,你一定感受过这种痛苦:同一个模型在一个框架中表现卓越,在另一个框架中却毫无用处。一个智能体可能在工具使用排行榜上称王称霸,却在简单的现实任务中一败涂地。基准测试表现与实际可用性之间的鸿沟,正是该领域面临的最大挑战之一。
|
||||
|
||||
在设计 M2 时,我们知道必须直面这个问题。这引导我们确立了两个核心的、有时相互冲突的目标:
|
||||
|
||||
1. 在开源基准测试上表现出色。基准测试对于衡量"纯粹"能力至关重要。例如 BrowseComp 这样的基准测试,考察的是复杂的搜索能力。虽然用户极少会问出像"找到那篇论文,其中第 n 位作者姓名的第三个字母是 'x'"这样刻意设计的问题,但一个能解决此类问题的模型,证明了它具备扎实的基础能力。
|
||||
2. 在现实世界中实现鲁棒泛化。这是更困难、也更重要的一点。一个优秀的智能体必须能够在不熟悉的工具、IDE/CLI、智能体框架以及用户环境中可靠运行。它不能只会一招鲜,而是需要具备泛化能力。
|
||||
|
||||
那么,我们应该对齐谁?答案是两者兼顾。我们通过对齐基准测试来构建技能,但最终必须通过对齐用户来确保这些技能在任何地方都能发挥作用。
|
||||
|
||||
虽然攻克基准测试的方法本身是一个值得另文深谈的话题,但我想聚焦于第二个、也更棘手的目标:我们如何训练一个能在真实环境中游刃有余的智能体?
|
||||
|
||||
## **交错式思维的必要性**
|
||||
|
||||
项目早期,我们遇到了一个令人沮丧的瓶颈。智能体的表现很不稳定,而我们难以诊断出原因。经过多次讨论,特别是与何俊贤教授和陈文虎教授的交流之后,我们得出了第一个重要结论:智能体需要**交错式思维**。
|
||||
|
||||
这意味着,智能体的内心独白——即它的"思考"——可以在任务的任何阶段发生,而不像标准推理模型那样只在开始时进行一次。这种设计之所以关键,有两个原因:
|
||||
|
||||
1. 在长周期任务中保持专注。复杂的智能体任务拥有极长的上下文。仅靠初始阶段的一次思维过程,不足以维持指令遵循能力和连贯性。
|
||||
2. 适应外部扰动。这是最关键的区别。智能体任务会持续引入来自外部世界的、不可预测的扰动(即工具输出)。模型必须具备足够的鲁棒性来处理这些扰动、诊断错误并提取有用信息。"思考"过程使模型能够持续重新评估并适应环境中涌现的新信息。
|
||||
|
||||
这一原则成为 M2 有效性的基石。
|
||||
|
||||
> "***M2 用户小贴士:由于 M2 依赖于交错式思维,其上下文就是它的记忆。为了获得最佳性能,你必须保留完整的会话历史,包括思考步骤。我们发现,许多关于性能差距的社区反馈,其根源正是在于意外丢弃了这一至关重要的上下文——而这在使用更简单的推理模型时是常见做法。***"
|
||||
|
||||
## **真正的泛化关乎扰动**
|
||||
|
||||
我们最初的假设很简单:工具扩展就是智能体泛化。
|
||||
|
||||
我们从一组最小的工具(一个 Python 解释器、搜索引擎、浏览器)入手,构建了工具调用能力的基线。路线图很清晰:扩大工具的数量和种类,智能体泛化到未见工具的能力就会自然跟上。
|
||||
|
||||
起初,这确实奏效了。我们的基准测试分数攀升到了可观的水平。但随着研究的深入,我们意识到自己解决的是错误的问题。模型在测试中表现出色,但只要我们对环境稍作改变——比如切换到不同的框架——它的性能就会急剧下降。我们距离"实用模型"的目标仍然很远。
|
||||
|
||||
这引导我们得出了第二个、也更深刻的领悟:**智能体泛化不仅仅是对新工具的适应,更是对模型整个运作空间中各种扰动的适应。**
|
||||
|
||||

|
||||
|
||||
这听起来很抽象,让我们来分解一下。想想在一个智能体任务中,有哪些因素可能发生变化:
|
||||
|
||||
* **工具信息**及可用工具集
|
||||
* 定义智能体角色和规则的**系统提示**
|
||||
* **用户提示**及其具体目标
|
||||
* **环境**本身(文件、代码库、API)
|
||||
* 每一步返回的**工具响应**
|
||||
|
||||
我们过去"工具扩展"的方法只解决了第一个问题,而忽略了流程中其他所有部分的扰动。有了这一新的认识,我们的团队构建了一个专门用于**全轨迹泛化**的综合数据管道。该管道生成的数据能够训练模型抵御每一步的扰动,保持稳定。
|
||||
|
||||
结果令人备受鼓舞。在内部测试中,我们将陌生的、"冷启动"的框架抛给 M2——那些我们几乎未曾考虑过的框架——它的表现超出了我们的预期。它的工具调用能力和指令遵循能力都实现了出色的泛化。
|
||||
|
||||
## **下一步是什么?**
|
||||
|
||||
在 M2 的工作让我们对智能体、泛化和数据有了极其深刻的认识,但它提出的问题远比回答的要多。我们的许多想法仍然停留在白板上。在接下来的几个月里,我们将更深入地探索这些前沿领域,并迫不及待地想为大家带来下一代强大且真正有用的模型。
|
||||
|
||||
## **参与进来**
|
||||
|
||||
* **使用模型**:我们真诚地希望你能对 M2 进行检验。你可以通过我们的官方渠道访问它,或查找开源版本进行自己的研究。
|
||||
* **加入我们的团队**:如果这类挑战让你感到兴奋,我们正在招聘。我们始终在寻找充满热情的人加入我们,共同建设 AGI。请将你的简历发送给我们!
|
||||
|
||||
|
||||
---
|
||||
|
||||
> 要查找本文档中的导航及其他页面,请获取以下地址的 llms.txt 文件:https://platform.minimax.io/docs/llms.txt
|
||||
@@ -0,0 +1,13 @@
|
||||
已翻译完成。以下是翻译要点说明:
|
||||
|
||||
1. **Markdown 结构与 YAML frontmatter**:全文标题层级、列表、表格、代码围栏、引用、链接位置、`<Columns>` / `<Card>` / `<Note>` 标签结构完全保留不变。
|
||||
|
||||
2. **代码块**:所有 ` ```python `、` ```json `、` ```nushell `、` ```bash `、` ``` ``` 块中的代码内容、英文注释、模型输出(thinking 文本、tool call 等)均原样保留,未作翻译。
|
||||
|
||||
3. **技术标识符**:`tools`、`tool_calls`、`function.name`、`function.arguments`、`reasoning_split`、`reasoning_details`、`thinking` 标签、API 端点 URL、环境变量名(`ANTHROPIC_BASE_URL`、`ANTHROPIC_API_KEY` 等)、包名(`anthropic`、`openai`)、函数名(`send_messages`、`process_response`、`get_weather`)等均保持原样。
|
||||
|
||||
4. **英文专有名词**:MiniMax-M2.1、OpenAI SDK、Anthropic SDK、San Francisco、Interleaved Thinking、SOTA、SWE、BrowseCamp、xBench 等保留原文。
|
||||
|
||||
5. **标点**:正文使用中文标点(句号、逗号),代码与 URL 内标点不动。
|
||||
|
||||
6. **重要/提醒/关键**等强调性标注:原文中 `⚠️ Critical` 译为 `⚠️ 关键`,`Important Note` 译为 `重要提示`,`Important Reminder` 译为 `重要提醒`,保持一致的语义强度。
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
# 兼容 Anthropic API
|
||||
|
||||
> 使用 Anthropic SDK 调用 MiniMax 模型
|
||||
|
||||
为满足开发者对 Anthropic API 生态的需求,我们的 API 现已支持 Anthropic API 格式。通过简单配置,您可以将 MiniMax 能力集成到 Anthropic API 生态中。
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 1. 安装 Anthropic SDK
|
||||
|
||||
<CodeGroup>
|
||||
```bash Python theme={null}
|
||||
pip install anthropic
|
||||
```
|
||||
|
||||
```bash Node.js theme={null}
|
||||
npm install @anthropic-ai/sdk
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 2. 配置环境变量
|
||||
|
||||
国际用户请使用 `https://api.minimax.io/anthropic`;中国用户请使用 `https://api.minimaxi.com/anthropic`
|
||||
|
||||
```bash theme={null}
|
||||
export ANTHROPIC_BASE_URL=https://api.minimax.io/anthropic
|
||||
export ANTHROPIC_API_KEY=${YOUR_API_KEY}
|
||||
```
|
||||
|
||||
### 3. 调用 API
|
||||
|
||||
```python Python theme={null}
|
||||
import anthropic
|
||||
|
||||
client = anthropic.Anthropic()
|
||||
|
||||
message = client.messages.create(
|
||||
model="MiniMax-M2.1",
|
||||
max_tokens=1000,
|
||||
system="You are a helpful assistant.",
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "Hi, how are you?"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
for block in message.content:
|
||||
if block.type == "thinking":
|
||||
print(f"Thinking:\n{block.thinking}\n")
|
||||
elif block.type == "text":
|
||||
print(f"Text:\n{block.text}\n")
|
||||
```
|
||||
|
||||
### 4. 重要说明
|
||||
|
||||
在多轮函数调用对话中,必须将完整的模型响应(即 assistant 消息)追加到对话历史中,以保持推理链的连续性。
|
||||
|
||||
* 将完整的 `response.content` 列表追加到消息历史中(包含所有内容块:thinking/text/tool\_use)
|
||||
|
||||
## 支持的模型
|
||||
|
||||
使用 Anthropic SDK 时,支持 `MiniMax-M2.1` `MiniMax-M2.1-lightning` `MiniMax-M2` 模型:
|
||||
|
||||
| 模型名称 | 描述 |
|
||||
| :--------------------- | :------------------------------------------------------------------------------------------------------------- |
|
||||
| MiniMax-M2.1 | 强大的多语言编程能力,全面增强的编程体验(输出速度约 60 tps) |
|
||||
| MiniMax-M2.1-lightning | 更快更敏捷(输出速度约 100 tps) |
|
||||
| MiniMax-M2 | Agent 能力,高级推理 |
|
||||
|
||||
<Note>
|
||||
Anthropic API 兼容接口目前仅支持
|
||||
`MiniMax-M2.1` `MiniMax-M2.1-lightning` `MiniMax-M2` 模型。其他模型请使用标准 MiniMax API
|
||||
接口。
|
||||
</Note>
|
||||
|
||||
## 兼容性
|
||||
|
||||
### 支持的参数
|
||||
|
||||
使用 Anthropic SDK 时,我们支持以下输入参数:
|
||||
|
||||
| 参数 | 支持状态 | 描述 |
|
||||
| :------------------- | :----------- | :--------------------------------------------------------------- |
|
||||
| `model` | 完全支持 | 支持 `MiniMax-M2.1` `MiniMax-M2.1-lightning` `MiniMax-M2` 模型 |
|
||||
| `messages` | 部分支持 | 支持文本和工具调用,不支持图片/文档输入 |
|
||||
| `max_tokens` | 完全支持 | 最大生成 token 数 |
|
||||
| `stream` | 完全支持 | 流式响应 |
|
||||
| `system` | 完全支持 | 系统提示词 |
|
||||
| `temperature` | 完全支持 | 范围 (0.0, 1.0],控制输出随机性,推荐值:1 |
|
||||
| `tool_choice` | 完全支持 | 工具选择策略 |
|
||||
| `tools` | 完全支持 | 工具定义 |
|
||||
| `top_p` | 完全支持 | 核采样参数 |
|
||||
| `metadata` | 完全支持 | 元数据 |
|
||||
| `thinking` | 完全支持 | 推理内容 |
|
||||
| `top_k` | 被忽略 | 该参数将被忽略 |
|
||||
| `stop_sequences` | 被忽略 | 该参数将被忽略 |
|
||||
| `service_tier` | 被忽略 | 该参数将被忽略 |
|
||||
| `mcp_servers` | 被忽略 | 该参数将被忽略 |
|
||||
| `context_management` | 被忽略 | 该参数将被忽略 |
|
||||
| `container` | 被忽略 | 该参数将被忽略 |
|
||||
|
||||
### Messages 字段支持
|
||||
|
||||
| 字段类型 | 支持状态 | 描述 |
|
||||
| :-------------------- | :----------- | :------------------------------- |
|
||||
| `type="text"` | 完全支持 | 文本消息 |
|
||||
| `type="tool_use"` | 完全支持 | 工具调用 |
|
||||
| `type="tool_result"` | 完全支持 | 工具调用结果 |
|
||||
| `type="thinking"` | 完全支持 | 推理内容 |
|
||||
| `type="image"` | 不支持 | 暂不支持图片输入 |
|
||||
| `type="document"` | 不支持 | 暂不支持文档输入 |
|
||||
|
||||
## 示例
|
||||
|
||||
### 流式响应
|
||||
|
||||
```python Python theme={null}
|
||||
import anthropic
|
||||
|
||||
client = anthropic.Anthropic()
|
||||
|
||||
print("Starting stream response...\n")
|
||||
print("=" * 60)
|
||||
print("Thinking Process:")
|
||||
print("=" * 60)
|
||||
|
||||
stream = client.messages.create(
|
||||
model="MiniMax-M2.1",
|
||||
max_tokens=1000,
|
||||
system="You are a helpful assistant.",
|
||||
messages=[
|
||||
{"role": "user", "content": [{"type": "text", "text": "Hi, how are you?"}]}
|
||||
],
|
||||
stream=True,
|
||||
)
|
||||
|
||||
reasoning_buffer = ""
|
||||
text_buffer = ""
|
||||
|
||||
for chunk in stream:
|
||||
if chunk.type == "content_block_start":
|
||||
if hasattr(chunk, "content_block") and chunk.content_block:
|
||||
if chunk.content_block.type == "text":
|
||||
print("\n" + "=" * 60)
|
||||
print("Response Content:")
|
||||
print("=" * 60)
|
||||
|
||||
elif chunk.type == "content_block_delta":
|
||||
if hasattr(chunk, "delta") and chunk.delta:
|
||||
if chunk.delta.type == "thinking_delta":
|
||||
# Stream output thinking process
|
||||
new_thinking = chunk.delta.thinking
|
||||
if new_thinking:
|
||||
print(new_thinking, end="", flush=True)
|
||||
reasoning_buffer += new_thinking
|
||||
elif chunk.delta.type == "text_delta":
|
||||
# Stream output text content
|
||||
new_text = chunk.delta.text
|
||||
if new_text:
|
||||
print(new_text, end="", flush=True)
|
||||
text_buffer += new_text
|
||||
|
||||
print("\n")
|
||||
```
|
||||
|
||||
### 工具调用与交错思维
|
||||
|
||||
了解如何使用 Anthropic SDK 调用 M2.1 的工具使用(Tool Use)和交错思维(Interleaved Thinking)能力,请参考以下文档。
|
||||
|
||||
<Columns cols={1}>
|
||||
<Card title="M2.1 工具使用与交错思维" icon="book-open" href="/guides/text-m2-function-call#anthropic-sdk" arrow="true" cta="点击查看">
|
||||
了解如何利用 MiniMax-M2.1 的工具调用和交错思维能力,在复杂任务中提升表现。
|
||||
</Card>
|
||||
</Columns>
|
||||
|
||||
## 重要说明
|
||||
|
||||
<Warning>
|
||||
1. Anthropic API 兼容接口目前仅支持 `MiniMax-M2.1` `MiniMax-M2` 模型
|
||||
|
||||
2. `temperature` 参数范围是 (0.0, 1.0],超出此范围的值将返回错误
|
||||
|
||||
3. 部分 Anthropic 参数(如 `thinking`、`top_k`、`stop_sequences`、`service_tier`、`mcp_servers`、`context_management`、`container`)将被忽略
|
||||
|
||||
4. 目前不支持图片和文档类型的输入
|
||||
</Warning>
|
||||
|
||||
## 相关链接
|
||||
|
||||
* [Anthropic SDK 文档](https://docs.anthropic.com/en/api/client-sdks)
|
||||
* [MiniMax 文本生成 API](/api-reference/text-intro)
|
||||
* [M2.1 工具使用与交错思维](/guides/text-m2-function-call)
|
||||
|
||||
## 推荐阅读
|
||||
|
||||
<Columns cols={2}>
|
||||
<Card title="文本生成" icon="book-open" href="/guides/text-generation" arrow="true" cta="点击查看">
|
||||
通过兼容的 Anthropic API 和 OpenAI API 支持文本生成。
|
||||
</Card>
|
||||
|
||||
<Card title="兼容 OpenAI API" icon="book-open" href="/api-reference/text-openai-api" arrow="true" cta="点击查看">
|
||||
将 OpenAI SDK 与 MiniMax 模型配合使用
|
||||
</Card>
|
||||
|
||||
<Card title="M2.1 适用于 AI 编程工具" icon="book-open" href="/guides/text-ai-coding-tools" arrow="true" cta="点击查看">
|
||||
MiniMax-M2.1 在代码理解、对话和推理方面表现出色。
|
||||
</Card>
|
||||
|
||||
<Card title="M2.1 工具使用与交错思维" icon="book-open" href="/guides/text-m2-function-call" arrow="true" cta="点击查看">
|
||||
AI 模型可以调用外部函数来扩展其能力。
|
||||
</Card>
|
||||
</Columns>
|
||||
|
||||
---
|
||||
|
||||
> 要查找本文档中的导航页面及其他页面,请获取 llms.txt 文件:https://platform.minimax.io/docs/llms.txt
|
||||
@@ -0,0 +1,76 @@
|
||||
"""
|
||||
Example 1: Basic Trace Capture
|
||||
|
||||
Demonstrates capturing reasoning traces from M2.1 for a simple task.
|
||||
This shows how interleaved thinking provides visibility into agent decisions.
|
||||
"""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from reasoning_trace_optimizer import TraceCapture
|
||||
from reasoning_trace_optimizer.capture import format_trace_for_display
|
||||
|
||||
# Load environment variables from the project root
|
||||
env_path = Path(__file__).parent.parent / ".env"
|
||||
load_dotenv(env_path)
|
||||
|
||||
|
||||
def main():
|
||||
"""Run a simple task and capture the reasoning trace."""
|
||||
|
||||
# Initialize capture with M2.1
|
||||
capture = TraceCapture(
|
||||
api_key=os.getenv("ANTHROPIC_API_KEY"),
|
||||
base_url="https://api.minimax.io/anthropic",
|
||||
model="MiniMax-M2.1",
|
||||
)
|
||||
|
||||
# Define a simple task
|
||||
task = "Explain what interleaved thinking is and why it matters for AI agents."
|
||||
system_prompt = "You are an AI researcher explaining concepts clearly."
|
||||
|
||||
print("=" * 60)
|
||||
print("BASIC TRACE CAPTURE EXAMPLE")
|
||||
print("=" * 60)
|
||||
print(f"\nTask: {task}")
|
||||
print(f"System Prompt: {system_prompt}")
|
||||
print("\nCapturing reasoning trace...\n")
|
||||
|
||||
# Capture the trace
|
||||
trace = capture.run(
|
||||
task=task,
|
||||
system_prompt=system_prompt,
|
||||
max_turns=5,
|
||||
)
|
||||
|
||||
# Display the trace
|
||||
print(format_trace_for_display(trace))
|
||||
|
||||
# Summary statistics
|
||||
print("\n" + "=" * 60)
|
||||
print("TRACE STATISTICS")
|
||||
print("=" * 60)
|
||||
print(f"Session ID: {trace.session_id}")
|
||||
print(f"Model: {trace.model}")
|
||||
print(f"Success: {trace.success}")
|
||||
print(f"Total Turns: {trace.total_turns}")
|
||||
print(f"Thinking Blocks: {len(trace.thinking_blocks)}")
|
||||
print(f"Tool Calls: {len(trace.tool_calls)}")
|
||||
print(f"Total Tokens: {trace.total_tokens}")
|
||||
|
||||
# Show each thinking block summary
|
||||
if trace.thinking_blocks:
|
||||
print("\n" + "=" * 60)
|
||||
print("THINKING BLOCK SUMMARIES")
|
||||
print("=" * 60)
|
||||
for i, thinking in enumerate(trace.thinking_blocks):
|
||||
print(f"\n[Turn {thinking.turn_index}] ({len(thinking.content)} chars)")
|
||||
# Show first 200 chars
|
||||
preview = thinking.content[:200].replace("\n", " ")
|
||||
print(f" Preview: {preview}...")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,187 @@
|
||||
"""
|
||||
Example 2: Tool Usage with Trace Capture
|
||||
|
||||
Demonstrates how M2.1's interleaved thinking reasons between tool calls.
|
||||
This is where interleaved thinking really shines - you can see the model
|
||||
adapting to tool outputs in real-time.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from reasoning_trace_optimizer import TraceCapture
|
||||
from reasoning_trace_optimizer.capture import format_trace_for_display
|
||||
|
||||
# Load environment variables from the project root
|
||||
env_path = Path(__file__).parent.parent / ".env"
|
||||
load_dotenv(env_path)
|
||||
|
||||
|
||||
# Define mock tools
|
||||
TOOLS = [
|
||||
{
|
||||
"name": "get_weather",
|
||||
"description": "Get current weather for a location. Returns temperature and conditions.",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "City name, e.g., 'San Francisco, CA'",
|
||||
}
|
||||
},
|
||||
"required": ["location"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "get_forecast",
|
||||
"description": "Get 3-day weather forecast for a location.",
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "City name",
|
||||
},
|
||||
"days": {
|
||||
"type": "integer",
|
||||
"description": "Number of days (1-3)",
|
||||
"default": 3,
|
||||
},
|
||||
},
|
||||
"required": ["location"],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Mock tool executor
|
||||
def execute_tool(name: str, input_data: dict) -> str:
|
||||
"""Execute a mock tool and return results."""
|
||||
if name == "get_weather":
|
||||
location = input_data.get("location", "Unknown")
|
||||
# Simulate different weather for different cities
|
||||
if "san francisco" in location.lower():
|
||||
return json.dumps({
|
||||
"location": location,
|
||||
"temperature": "18°C",
|
||||
"conditions": "Foggy",
|
||||
"humidity": "85%",
|
||||
})
|
||||
elif "new york" in location.lower():
|
||||
return json.dumps({
|
||||
"location": location,
|
||||
"temperature": "22°C",
|
||||
"conditions": "Partly cloudy",
|
||||
"humidity": "60%",
|
||||
})
|
||||
else:
|
||||
return json.dumps({
|
||||
"location": location,
|
||||
"temperature": "20°C",
|
||||
"conditions": "Clear",
|
||||
"humidity": "50%",
|
||||
})
|
||||
|
||||
elif name == "get_forecast":
|
||||
location = input_data.get("location", "Unknown")
|
||||
days = input_data.get("days", 3)
|
||||
forecast = []
|
||||
for i in range(days):
|
||||
forecast.append({
|
||||
"day": i + 1,
|
||||
"high": f"{20 + i * 2}°C",
|
||||
"low": f"{12 + i}°C",
|
||||
"conditions": ["Sunny", "Cloudy", "Rainy"][i % 3],
|
||||
})
|
||||
return json.dumps({
|
||||
"location": location,
|
||||
"forecast": forecast,
|
||||
})
|
||||
|
||||
return json.dumps({"error": f"Unknown tool: {name}"})
|
||||
|
||||
|
||||
def main():
|
||||
"""Run a task with tools and observe interleaved thinking."""
|
||||
|
||||
capture = TraceCapture(
|
||||
api_key=os.getenv("ANTHROPIC_API_KEY"),
|
||||
base_url="https://api.minimax.io/anthropic",
|
||||
model="MiniMax-M2.1",
|
||||
)
|
||||
|
||||
task = """Compare the current weather in San Francisco and New York City.
|
||||
Then tell me which city would be better for outdoor activities this weekend."""
|
||||
|
||||
system_prompt = """You are a helpful weather assistant.
|
||||
Use the available tools to get accurate weather information.
|
||||
Always provide specific data to support your recommendations."""
|
||||
|
||||
print("=" * 60)
|
||||
print("TOOL USAGE WITH INTERLEAVED THINKING")
|
||||
print("=" * 60)
|
||||
print(f"\nTask: {task}")
|
||||
print(f"\nTools available: {', '.join(t['name'] for t in TOOLS)}")
|
||||
print("\nCapturing trace with tool usage...\n")
|
||||
|
||||
# Capture the trace (using non-streaming for reliability)
|
||||
trace = capture.run(
|
||||
task=task,
|
||||
system_prompt=system_prompt,
|
||||
tools=TOOLS,
|
||||
tool_executor=execute_tool,
|
||||
max_turns=10,
|
||||
)
|
||||
|
||||
print("\n\n" + "=" * 60)
|
||||
print("TRACE ANALYSIS")
|
||||
print("=" * 60)
|
||||
|
||||
print(f"\nSuccess: {trace.success}")
|
||||
print(f"Total Turns: {trace.total_turns}")
|
||||
print(f"Thinking Blocks: {len(trace.thinking_blocks)}")
|
||||
print(f"Tool Calls: {len(trace.tool_calls)}")
|
||||
|
||||
# Show how thinking evolved between tool calls
|
||||
print("\n" + "=" * 60)
|
||||
print("THINKING EVOLUTION ACROSS TOOL CALLS")
|
||||
print("=" * 60)
|
||||
|
||||
for i, thinking in enumerate(trace.thinking_blocks):
|
||||
print(f"\n[Turn {thinking.turn_index}] Thinking Block {i + 1}")
|
||||
print("-" * 40)
|
||||
|
||||
# Show what tool was called after this thinking
|
||||
turn_tools = trace.get_tool_calls_at_turn(thinking.turn_index)
|
||||
if turn_tools:
|
||||
print(f"Following action: Called {', '.join(t.name for t in turn_tools)}")
|
||||
else:
|
||||
print("Following action: Generated response")
|
||||
|
||||
# Show key reasoning points (first 300 chars)
|
||||
print(f"\nReasoning preview:\n{thinking.content[:300]}...")
|
||||
|
||||
# Show tool call results
|
||||
print("\n" + "=" * 60)
|
||||
print("TOOL CALL SUMMARY")
|
||||
print("=" * 60)
|
||||
|
||||
for tc in trace.tool_calls:
|
||||
status = "✅" if tc.success else "❌"
|
||||
print(f"\n{status} {tc.name}")
|
||||
print(f" Input: {json.dumps(tc.input)}")
|
||||
print(f" Result: {tc.result[:100]}..." if tc.result and len(tc.result) > 100 else f" Result: {tc.result}")
|
||||
|
||||
# Final response
|
||||
if trace.final_response:
|
||||
print("\n" + "=" * 60)
|
||||
print("FINAL RESPONSE")
|
||||
print("=" * 60)
|
||||
print(trace.final_response)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,90 @@
|
||||
---
|
||||
name: comprehensive-research-agent
|
||||
description: "确保在研究任务中通过多次工具调用实现彻底的验证、错误恢复和透明的推理"
|
||||
---
|
||||
|
||||
# 综合研究 Agent 最佳实践
|
||||
|
||||
本技能针对多步骤研究任务中常见的失败场景:未处理的工具错误、缺失的验证、不透明的推理以及过早得出结论。它提供了关于源验证、错误恢复和思考透明度的结构化协议,能显著提升研究质量和可靠性。
|
||||
|
||||
## 何时激活
|
||||
|
||||
- 任务涉及使用 search、read_url 或 fetch 操作的网络研究
|
||||
- 任务需要从多个来源收集信息
|
||||
- 任务对完整性或验证有明确要求
|
||||
- 任务包含需要验证的文件操作(save、write、read)
|
||||
- 任何涉及 3 次以上工具交互的研究或信息收集工作流
|
||||
|
||||
## 核心概念
|
||||
|
||||
- **验证检查点**:在阶段转换处进行显式验证步骤,确认工具输出、源相关性和信息完整性,然后再继续执行
|
||||
- **错误恢复协议**:强制承认并处理工具失败,采用回退策略而非静默继续执行
|
||||
- **源可追溯性**:清晰跟踪哪些源是实际检索到的,哪些是来自先验知识的引用,以防止幻觉
|
||||
- **实质性思考块**:详细推理痕迹,记录每一步的见解、关联、空白和决策依据
|
||||
- **跨源验证**:针对多个来源验证关键声明,并明确标注共识、矛盾和信息空白
|
||||
|
||||
## 应避免的模式
|
||||
|
||||
- **静默工具失败**:工具调用返回错误(404、超时、无效 URL),但 Agent 未加承认就继续执行,可能遗漏关键信息。务必记录失败并尝试恢复或记录该空白。
|
||||
- **模糊的完成声明**:Agent 声明"我已拥有足够的信息"或"研究已完成",而未说明学到了什么、哪些来源支持该声明、或存在哪些空白。应替换为具体的覆盖范围摘要。
|
||||
- **未经评估的源选择**:Agent 未经评估相关性、可信度或时效性就直接读取搜索结果中的 URL。这会浪费工具调用在低质量来源上。务必在深入阅读前对来源进行排序和优先级划分。
|
||||
- **泛泛的思考块**:思考内容仅包含下一步行动描述("现在我将搜索 X"),而不分析学到了什么、如何与目标相关联、或还有哪些问题。思考应具有实质性和反思性。
|
||||
- **验证方法错误**:使用 list_directory 来验证文件创建可能因缓存问题产生假阴性。应始终使用 read_file 进行实际内容验证。
|
||||
- **未检索的引用**:在最终报告中引用从未成功获取或阅读的来源(URL、论文标题)。应显式跟踪来源,禁止引用未检索的内容。
|
||||
- **冗余的工具调用**:进行重复搜索或阅读来源,而不跟踪已获取的内容。应维护一个"已发现资源"跟踪器以避免重复。
|
||||
|
||||
## 推荐做法
|
||||
|
||||
- **实施预读源评估**:在阅读 URL 之前,按相关性、可信度、时效性和权威性对搜索结果排序。在思考块中记录选择依据。
|
||||
- **使用结构化思考块**:每个思考块必须包含:(a) 从该来源/操作中学到了什么,(b) 它与研究目标的关联,(c) 发现的任何矛盾/空白,(d) 做出的策略决策。避免泛泛的下一步行动声明。
|
||||
- **添加强制性错误承认**:当任何工具失败时,下一个思考块必须显式处理:说明失败类型,提出恢复策略(重试、替代来源或记录空白),并解释所选方案的理由。
|
||||
- **创建完成前验证清单**:在宣布研究完成之前,验证:所有必需部分都有具体证据,所有来源均已成功检索,关键声明已交叉验证,空白已记录。
|
||||
- **实施跨源验证**:从多个来源收集信息后,显式比较结果。标注各来源一致之处、矛盾之处以及仍未验证的内容。据此评估整体可信度。
|
||||
- **维护源跟踪表**:在思考中创建一个简单表格,显示哪些 URL 已获取、哪些失败、哪些用于特定声明。切勿引用未检索的来源。
|
||||
- **使用 read_file 进行验证**:确认文件写入时,使用 read_file 验证实际内容,而非 list_directory,后者可能因缓存问题导致假阴性。
|
||||
- **添加显式验证阶段**:阅读来源后,写一段简短的综合摘要,确认其有用性,说明与研究目标的相关性,并在进入下一阶段前识别剩余空白。
|
||||
|
||||
## 指南
|
||||
|
||||
1. 每次工具调用后,显式检查响应中的错误,并在下一个思考块中承认失败并说明恢复策略
|
||||
2. 在阅读 URL 之前,按相关性/可信度对来源排序并记录选择依据——绝不在未经评估的情况下阅读结果
|
||||
3. 思考块至少要有 3-5 个句子,并包含:学到了什么、与目标的关联、空白/矛盾以及后续步骤
|
||||
4. 创建完成前清单验证:所有需求已覆盖、来源已检索、声明已验证、空白已记录
|
||||
5. 维护源跟踪——仅引用已成功获取的 URL;禁止引用未检索的来源
|
||||
6. 撰写最终报告时,包含"限制与空白"部分,记录已尝试但失败或仍未验证的内容
|
||||
7. 使用 read_file(而非 list_directory)在保存操作后验证文件内容
|
||||
8. 尽可能对关键声明进行至少 2 个来源的交叉验证;显式标注共识或矛盾
|
||||
9. 跟踪已收集的信息以避免重复搜索——为多阶段研究实现"已发现资源"跟踪器
|
||||
10. 用具体的摘要替换模糊的"全面"声明:"已覆盖 Y 主题上的 X 个来源;缺少 Z 方面"
|
||||
|
||||
## 示例
|
||||
|
||||
- **之前(反模式)**:"我搜索了上下文工程并找到了几个结果。现在我将阅读一些 URL,然后撰写报告。我已拥有足够的信息继续。"
|
||||
|
||||
**之后(模式)**:"搜索返回了 15 个关于上下文工程的结果。评估相关性:Liu 等人(2024)在'中间迷失'现象方面似乎最具权威性;Anthropic 文档可能包含最新的上下文窗口规格;Patel(2023)涵盖了 RAG 最佳实践。将这三者列为最优先。先阅读最高优先级的结果。如果主要来源失败(URL 错误),将尝试备用搜索以找到正确的文档 URL,并在最终报告中注明该空白。"
|
||||
- **之前(反模式)**:工具返回了 Anthropic 上下文窗口 URL 的 404 错误。Agent 未加承认继续执行。后来引用"Claude 拥有 200K 上下文窗口"而未显示来源。最终报告引用了从未获取的 Google Research 论文。
|
||||
|
||||
**之后(模式)**:工具返回了 Anthropic URL 的 404 错误。思考:"主要来源失败。回退方案:搜索替代的 Anthropic 文档 URL 或查找存档版本。如果不可用,仅从次要来源引用上下文窗口数据,并添加关于验证状态的免责声明。"然后:"交叉验证了 Claude 上下文窗口:Anthropic 博客(已成功读取)和两个开发者文档来源均一致认为是 200K。对该声明有把握。"源跟踪表显示:Anthropic URL(失败,使用了备用来源)、博客(成功)、开发者文档(成功)。
|
||||
|
||||
---
|
||||
|
||||
## 评分预期
|
||||
|
||||
包含多个工具(6 次以上)和多步骤推理链的复杂研究任务通常得分在 **65-75 分** 范围内。这并非提示词的局限,而是反映了:
|
||||
|
||||
- 工具输出的固有变异性会影响推理路径
|
||||
- 多种有效方法会导致不同的中间分数
|
||||
- 长周期 Agent 执行的随机性
|
||||
|
||||
**关注相对改进和模式消除**,而非绝对分数。对于复杂任务而言,通过优化获得 5-10% 的提升已经意义重大。
|
||||
|
||||
---
|
||||
|
||||
## 技能元数据
|
||||
|
||||
**生成日期**:2026-01-11
|
||||
**来源**:推理轨迹优化器
|
||||
**优化迭代次数**:10
|
||||
**最佳得分**:72/100(第 4 次迭代)
|
||||
**最终得分**:70.0/100
|
||||
**得分提升**:67.6 → 70.0(+3.6%)
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"task": "Research the topic of \"context engineering for AI agents\" and create a comprehensive summary.\n\nYour research should:\n1. Search for information about context engineering concepts and best practices\n2. Read relevant sources to gather detailed information\n3. Check the local project files for any existing research notes\n4. Save important findings as notes for future reference\n5. Write a final summary report to ./output/research_summary.md\n\nThe summary should include:\n- Key concepts and definitions\n- Best practices and techniques (including the \"lost in the middle\" problem)\n- Practical recommendations for agent developers\n- References to sources consulted (use actual URLs from your research)",
|
||||
"iterations": 10,
|
||||
"initial_score": 67.6,
|
||||
"final_score": 70,
|
||||
"improvement": 3.550295857988174,
|
||||
"converged": true,
|
||||
"generated_at": "2026-01-11T18:02:57.336789"
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
description: 研究助理,利用可用工具协助完成研究任务。
|
||||
---
|
||||
|
||||
你是一名研究助理。使用可用工具协助完成研究任务。
|
||||
|
||||
可用于 Agent 工具的代理类型:
|
||||
|
||||
- claude:通用代理,适用于任何没有更专门代理与之匹配的任务。FleetView 在未输入代理名称时的默认选项。(工具:*)
|
||||
- Explore:只读搜索代理,用于广泛的发散搜索——当回答需要扫描大量文件、目录或命名约定,而你只需要结论而非文件内容时使用。它读取的是文件摘录而非完整文件,因此能定位代码,但不会审查或审计代码。指定搜索广度:"medium" 表示适度探索,"very thorough" 表示多个位置和命名约定。(工具:除 Agent、Artifact、ExitPlanMode、Edit、Write、NotebookEdit 之外的所有工具)
|
||||
- general-purpose:通用代理,用于研究复杂问题、搜索代码以及执行多步骤任务。当你搜索某个关键词或文件且不确定能否在头几次尝试中就找到正确匹配时,使用此代理为你执行搜索。(工具:*)
|
||||
- Plan:软件架构师代理,用于设计实现方案。当你需要为某个任务规划实现策略时使用。返回逐步计划,识别关键文件,并考虑架构权衡。(工具:除 Agent、Artifact、ExitPlanMode、Edit、Write、NotebookEdit 之外的所有工具)
|
||||
- statusline-setup:使用此代理配置用户的 Claude Code 状态行设置。(工具:Read、Edit)
|
||||
|
||||
当你启动多个独立代理时,在一条消息中通过多次工具调用同时发送它们,使它们并发运行。
|
||||
|
||||
以下技能可用于 Skill 工具:
|
||||
|
||||
- deep-research:深度研究工具——发散式联网搜索、获取来源、对抗性验证、综合生成一份带引用的报告。当用户需要关于某个主题的深度多来源、经过事实核查的研究报告时使用。调用前,先判断问题是否足够具体以便直接研究——如果问题过于宽泛(例如"买什么车"但没有预算/用途/地区等限定条件),先问 2-3 个澄清问题以缩小范围。然后将细化后的问题作为 args 传入,并融入用户的回答。
|
||||
- dataviz:当你即将创建任何类型的图表、图形、绘图、仪表板或数据可视化,且输出媒介为 HTML 或 React 构件、内联 SVG、任意库的绘图代码(matplotlib、plotly、d3、Recharts……)、要渲染并上传的图片/PNG,或要分享到 Slack 的图表时,使用此技能。在编写第一行图表代码、选择图表颜色、构建统计块/仪表/KPI 行或布局仪表板之前,先阅读它。生成风格统一的可视化——优雅、无障碍、明暗模式下一致——使用一套中立的占位调色板,后续可替换为你自己的调色板。教授一种不依赖设计系统的方法:表单启发法、带可运行验证器的颜色公式、标记规范以及交互规则。经过验证的默认调色板记录在 `references/palette.md` 中——将该文件的值替换为你品牌的调色板。触发词:"chart"、"graph"、"plot"、"data viz"、"visualization"、"dashboard"、"analytics"、"visualize data"、"categorical colors"、"sequential / diverging palette"、"stat tile"、"sparkline"、"heatmap"、"legend"、"axis"、"tooltip"、"chart colors"、"color by series"。
|
||||
- update-config:使用此技能通过 settings.json 配置 Claude Code 工具链。"从现在起当 X 时"、"每次 X 时"、"每当 X 时"、"在 X 之前/之后"等自动化行为需要在 settings.json 中配置钩子——这些是由工具链执行的,而非 Claude,因此记忆/偏好设置无法满足这些需求。也可用于:权限设置("允许 X"、"添加权限"、"将权限移至")、环境变量("设置 X=Y")、钩子故障排查,或对 settings.json/settings.local.json 文件的任何更改。示例:"允许 npm 命令"、"将 bq 权限添加到全局设置"、"将权限移至用户设置"、"设置 DEBUG=true"、"当 claude 停止时显示 X"。对于主题/模型等简单设置,建议使用 /config 命令。
|
||||
- keybindings-help:当用户想要自定义键盘快捷键、重新绑定按键、添加和弦绑定或修改 ~/.claude/keybindings.json 时使用。示例:"重新绑定 ctrl+s"、"添加和弦快捷键"、"更改提交键"、"自定义键绑定"。
|
||||
- verify:通过端到端执行并观察行为,验证代码变更是否确实达到了预期效果——驱动受影响的流程,而不仅仅是运行测试或类型检查。在提交非微小变更前运行。如果 diff 只涉及测试、文档或其他没有运行时表面可驱动的代码(产品源代码的变更总是有运行时表面),则不要调用此技能——因为没有什么可观察的。
|
||||
- code-review:审查当前 diff 中的正确性错误和可复用性/简化/效率方面的清理,按指定努力级别(low/medium:更少、高置信度的发现;high→max:更广泛的覆盖,可能包含不确定的发现)。传入 --comment 可将发现作为内联 PR 评论发布,传入 --fix 可在审查后将发现应用到工作树中。
|
||||
- simplify:审查变更代码中的可复用性、简化、效率和抽象层次方面的清理,然后应用修复。仅关注质量——不查找错误;如需查找错误,请使用 /code-review。
|
||||
- fewer-permission-prompts:扫描你的对话记录中常见的只读 Bash 和 MCP 工具调用,然后向项目 .claude/settings.json 添加一个优先级排列的允许列表,以减少权限提示。
|
||||
- loop:按循环间隔运行某个提示或斜杠命令(例如 /loop 5m /foo,默认为 10m)。当用户想要设置周期性任务、轮询状态或以固定间隔重复运行某操作时使用(例如"每 5 分钟检查一次部署"、"持续运行 /babysit-prs")。不要为一次性任务调用此技能。
|
||||
- claude-api:Claude API / Anthropic SDK 参考——模型 ID、定价、参数、流式传输、工具使用、MCP、代理、缓存、令牌计数、模型迁移。
|
||||
触发条件——在打开目标文件之前阅读;不要因为"看起来像一行"就跳过——当提示中提及任何形式的 Claude/Anthropic(Claude、Anthropic、Fable、Opus、Sonnet、Haiku、`anthropic`、`@anthropic-ai`、`claude-*`、`us.anthropic.*`、`[1m]`)时;用户询问有关 LLM 的问题(定价/模型选择/限制/缓存)时——永远不要凭记忆回答;或者任务为 LLM 相关但未说明提供商(agent/MCP/工具定义/多代理/RAG/LLM 评判器/计算机使用;生成/总结/提取/分类/重写/对话式 NL;调试拒绝/截断/流式传输/工具调用/令牌)。
|
||||
仅当正在处理其他提供商时才跳过(覆盖所有触发条件):查询中提到了 OpenAI/GPT/Gemini/Llama/Mistral/Cohere/Ollama;或者 `grep -rE 'openai|langchain_openai|google.generativeai|genai|mistralai|cohere|ollama'` 在项目中命中(如果未指定提供商,则先运行此 grep——不要直接读取文件)。
|
||||
- run:启动并运行此项目的应用,以查看变更的实际效果。当被要求运行、启动或截取应用截图,或确认变更在真实应用中(而不仅仅是测试中)生效时使用。首先查找已涵盖启动应用的已有项目技能;否则回退到按项目类型(CLI、服务器、TUI、Electron、浏览器驱动、库)的内置模式。
|
||||
- init:初始化一个新的 CLAUDE.md 文件,包含代码库文档。
|
||||
- review:审查 GitHub 拉取请求;对于当前工作区的 diff,请使用 /code-review。
|
||||
- security-review:对当前分支上的待处理变更完成安全审查。生成按类别、影响和修复建议排序的发现列表。当用户要求进行安全审查、安全审计或安全评估时使用。
|
||||
- test:发现并运行当前项目或当前工作目录中项目的测试。
|
||||
- mcp-server-developer:MCP 服务器开发者技能,用于构建 Model Context Protocol 服务器。在构建、修改或调试 MCP 服务器时使用。提供关于 MCP 架构、传输层(stdio/SSE/流式 HTTP)、工具、资源、提示、采样、根目录、认证和部署方面的专家指导。当用户询问 MCP、提到"modelcontextprotocol"或你在项目中检测到 MCP 服务器代码时,调用此技能。
|
||||
- debug:当你陷入困境时使用此技能——代码按理应该工作但实际不工作,或者测试以你无法解释的方式失败。该技能会分析你的近期上下文,判断你是否处于调试循环中,如果是,则帮助你跳出循环。当对话持续了足够长时间以至于你已记不清尝试过什么时,此技能也很有用。该技能通过检查最新错误、你与用户的对话、测试输出以及代码变更,提供系统化的调试方法。
|
||||
- deep-research-v2:深度研究——联网搜索、获取来源、对抗性验证、综合生成一份带引用的报告。用户在需要关于某个主题的深度多来源、经过事实核查的研究报告时使用。调用前,先判断问题是否足够具体以便直接研究——如果问题过于宽泛(例如"买什么车"但没有预算、用途、地区等限定条件),先问 2-3 个澄清问题以缩小范围。然后将细化后的问题作为 args 传入,并融入用户的回答。
|
||||
- test:发现并运行当前项目或当前工作目录中项目的测试。
|
||||
- code-review:审查当前 diff 中的正确性错误和可复用性/简化/效率方面的清理,按指定努力级别(low/medium:更少、高置信度的发现;high→max:更广泛的覆盖,可能包含不确定的发现)。传入 --comment 可将发现作为内联 PR 评论发布,传入 --fix 可在审查后将发现应用到工作树中。
|
||||
- verify:通过端到端执行并观察行为,验证代码变更是否确实达到了预期效果——驱动受影响的流程,而不仅仅是运行测试或类型检查。在提交非微小变更前运行。如果 diff 只涉及测试、文档或其他没有运行时表面可驱动的代码(产品源代码的变更总是有运行时表面),则不要调用此技能——因为没有什么可观察的。
|
||||
@@ -0,0 +1,205 @@
|
||||
[
|
||||
{
|
||||
"type": "tool_confusion",
|
||||
"severity": "medium",
|
||||
"description": "Agent attempted to fetch non-existent or unreachable URLs without adjusting approach",
|
||||
"suggestion": "When a URL fetch fails, search for alternative URLs or verify the URL structure. Consider using search to find the correct documentation pages.",
|
||||
"iteration": 1
|
||||
},
|
||||
{
|
||||
"type": "missing_validation",
|
||||
"severity": "medium",
|
||||
"description": "Agent didn't validate the completeness of gathered information or verify key claims",
|
||||
"suggestion": "Before writing the final report, explicitly validate that all required topics are covered. Create a checklist of requirements and verify each one is addressed.",
|
||||
"iteration": 1
|
||||
},
|
||||
{
|
||||
"type": "tool_misuse",
|
||||
"severity": "low",
|
||||
"description": "Agent made redundant searches and didn't optimize tool calls",
|
||||
"suggestion": "Track previously found URLs to avoid redundant searches. When a useful URL is found in one search, use it directly rather than searching again for the same topic.",
|
||||
"iteration": 1
|
||||
},
|
||||
{
|
||||
"type": "incomplete_reasoning",
|
||||
"severity": "low",
|
||||
"description": "Thinking blocks are sparse and don't show deep analysis of alternatives or trade-offs",
|
||||
"suggestion": "In thinking blocks, explicitly list what information has been gathered, what gaps remain, and what decisions are being made. Use structured checklists.",
|
||||
"iteration": 1
|
||||
},
|
||||
{
|
||||
"type": "missing_validation",
|
||||
"severity": "high",
|
||||
"description": "Agent failed to properly handle or acknowledge tool errors, particularly the failed URL fetch for Anthropic context windows documentation",
|
||||
"suggestion": "Add explicit error handling for failed tool calls - when a read_url fails, the agent should acknowledge it and either retry, try an alternative source, or explicitly note that information is missing rather than proceeding as if it succeeded",
|
||||
"iteration": 2
|
||||
},
|
||||
{
|
||||
"type": "tool_misuse",
|
||||
"severity": "medium",
|
||||
"description": "Agent did not verify or validate the relevance of search results before committing to reading sources",
|
||||
"suggestion": "After receiving search results, explicitly evaluate and rank sources by relevance to the research question before deciding which URLs to read. This saves token costs and ensures better source quality.",
|
||||
"iteration": 2
|
||||
},
|
||||
{
|
||||
"type": "premature_conclusion",
|
||||
"severity": "low",
|
||||
"description": "Agent prematurely declared having 'enough information' despite not yet completing all research phases",
|
||||
"suggestion": "Before declaring research complete, create a checklist of what information is still needed and verify each item is adequately covered. Set explicit criteria for 'enough information' at task start.",
|
||||
"iteration": 2
|
||||
},
|
||||
{
|
||||
"type": "missing_validation",
|
||||
"severity": "medium",
|
||||
"description": "Agent accepted information without verifying it and failed to handle errors gracefully",
|
||||
"suggestion": "Implement explicit error checking after each tool call. If a read_url fails, acknowledge the failure and try an alternative source. Cross-reference key claims across multiple sources before including them in the final report.",
|
||||
"iteration": 3
|
||||
},
|
||||
{
|
||||
"type": "incomplete_reasoning",
|
||||
"severity": "medium",
|
||||
"description": "Agent gathered information but didn't deeply analyze or synthesize insights",
|
||||
"suggestion": "After reading sources, explicitly document what was learned, what contradictions exist, and what gaps remain. Create a synthesis section that combines insights from multiple sources rather than just reporting them separately.",
|
||||
"iteration": 3
|
||||
},
|
||||
{
|
||||
"type": "tool_misuse",
|
||||
"severity": "low",
|
||||
"description": "Agent used tools but didn't fully leverage results or handle failures properly",
|
||||
"suggestion": "Immediately act on directory listing results. If a directory is empty, plan when to create notes rather than waiting. Implement proper error handling for tool failures and check response status codes before proceeding.",
|
||||
"iteration": 3
|
||||
},
|
||||
{
|
||||
"type": "tool_misuse",
|
||||
"severity": "medium",
|
||||
"description": "Agent uses list_directory to verify file creation instead of the more reliable read_file method",
|
||||
"suggestion": "Use read_file to verify file write success since it confirms both file existence and content; list_directory may not immediately reflect recent filesystem changes",
|
||||
"iteration": 4
|
||||
},
|
||||
{
|
||||
"type": "missing_validation",
|
||||
"severity": "medium",
|
||||
"description": "Agent reads a URL that returns an error but doesn't acknowledge or log this failure, potentially missing important context",
|
||||
"suggestion": "Implement explicit error handling for failed URL reads - log which sources failed and consider searching for alternative sources or documentation",
|
||||
"iteration": 4
|
||||
},
|
||||
{
|
||||
"type": "incomplete_reasoning",
|
||||
"severity": "low",
|
||||
"description": "Agent doesn't explain why it chose certain sources or how it evaluated source quality; research appears thorough but reasoning process is opaque",
|
||||
"suggestion": "Add explicit reasoning about source selection criteria (e.g., prioritizing official documentation, recent publications, peer-reviewed papers) and evaluation of source credibility",
|
||||
"iteration": 4
|
||||
},
|
||||
{
|
||||
"type": "missing_validation",
|
||||
"severity": "medium",
|
||||
"description": "Agent accepts incomplete results without acknowledging failures or seeking alternatives",
|
||||
"suggestion": "When tool calls fail, explicitly note the failure in thinking blocks, consider alternative sources, and document what information gaps exist. Add a validation step to confirm all critical sources were successfully retrieved.",
|
||||
"iteration": 5
|
||||
},
|
||||
{
|
||||
"type": "incomplete_reasoning",
|
||||
"severity": "low",
|
||||
"description": "Agent doesn't demonstrate analytical depth when processing source material",
|
||||
"suggestion": "After reading sources, explicitly state: (a) key findings from each source, (b) how they relate to the research goal, (c) any contradictions or complementary findings, (d) what additional information is needed",
|
||||
"iteration": 5
|
||||
},
|
||||
{
|
||||
"type": "tool_misuse",
|
||||
"severity": "low",
|
||||
"description": "Inefficient tool usage pattern - multiple web searches without reading all results first",
|
||||
"suggestion": "Before making additional searches, review the URLs from previous search results. A better pattern would be: search -> read all relevant sources -> identify gaps -> targeted additional searches only if needed",
|
||||
"iteration": 5
|
||||
},
|
||||
{
|
||||
"type": "context_degradation",
|
||||
"severity": "low",
|
||||
"description": "Vague thinking blocks that don't show active reasoning process",
|
||||
"suggestion": "Make thinking blocks more explicit: show intermediate conclusions, decision points, how each source contributed, and how conclusions evolved. The thinking trace should be readable as a standalone explanation of the research process.",
|
||||
"iteration": 5
|
||||
},
|
||||
{
|
||||
"type": "missing_validation",
|
||||
"severity": "medium",
|
||||
"description": "Agent does not validate information across sources or verify accuracy of gathered content",
|
||||
"suggestion": "Add explicit validation steps: compare information across multiple sources, verify claims against original papers, include confidence assessments for key findings",
|
||||
"iteration": 7
|
||||
},
|
||||
{
|
||||
"type": "tool_misuse",
|
||||
"severity": "low",
|
||||
"description": "Inefficient tool usage - read_url calls lack systematic prioritization and some results may not have been fully utilized",
|
||||
"suggestion": "Implement a source prioritization matrix before reading URLs; explicitly note how each source will contribute to the research before fetching",
|
||||
"iteration": 7
|
||||
},
|
||||
{
|
||||
"type": "hallucination",
|
||||
"severity": "low",
|
||||
"description": "Potential source misattribution in final report - cites Google Research Chain of Thought paper but source wasn't fetched in thinking trace",
|
||||
"suggestion": "Only cite sources that were actually retrieved and read; if a source is referenced from memory, clearly indicate it as secondary/indirect reference",
|
||||
"iteration": 7
|
||||
},
|
||||
{
|
||||
"type": "missing_validation",
|
||||
"severity": "medium",
|
||||
"description": "Agent accepts search results without validating source relevance or quality before proceeding to read URLs",
|
||||
"suggestion": "Add explicit validation steps: list the top 3-5 sources with brief rationale for selection, note any potential gaps in coverage, and prioritize primary authoritative sources before secondary ones",
|
||||
"iteration": 8
|
||||
},
|
||||
{
|
||||
"type": "incomplete_reasoning",
|
||||
"severity": "medium",
|
||||
"description": "Thinking blocks are extremely sparse and lack intermediate analysis - agent doesn't explain HOW it's interpreting information or making decisions",
|
||||
"suggestion": "Implement structured reflection after each major information-gathering step: What did I learn? How does this connect to what I already know? What gaps remain? What should I prioritize next?",
|
||||
"iteration": 8
|
||||
},
|
||||
{
|
||||
"type": "missing_validation",
|
||||
"severity": "low",
|
||||
"description": "Agent encounters a failed tool call (404 error on Anthropic context-windows URL) but doesn't acknowledge or recover in thinking",
|
||||
"suggestion": "Add explicit error acknowledgment: 'Attempted X but failed with Y error. Will try alternative Z or note this as a gap.' This improves debugging and transparency",
|
||||
"iteration": 8
|
||||
},
|
||||
{
|
||||
"type": "incomplete_reasoning",
|
||||
"severity": "low",
|
||||
"description": "The agent reaches conclusions about having 'comprehensive information' after limited tool interactions, without explicitly documenting what was learned or what gaps remain",
|
||||
"suggestion": "Add more detailed reasoning about what specific information was gained from each source and what questions remain unanswered before claiming comprehensive understanding",
|
||||
"iteration": 9
|
||||
},
|
||||
{
|
||||
"type": "missing_validation",
|
||||
"severity": "low",
|
||||
"description": "The agent doesn't explicitly validate assumptions or cross-reference information between sources. The 'Lost in the Middle' paper is mentioned multiple times but not critically compared against other sources",
|
||||
"suggestion": "After reading multiple sources, explicitly compare findings, note contradictions, and validate key claims against multiple sources before proceeding",
|
||||
"iteration": 9
|
||||
},
|
||||
{
|
||||
"type": "tool_misuse",
|
||||
"severity": "medium",
|
||||
"description": "The agent attempted to read a URL that returned an error (https://docs.anthropic.com/en/docs/build-with-claude/context-windows) but proceeded without acknowledging or handling this failure",
|
||||
"suggestion": "Add explicit error handling for failed tool calls - acknowledge failures, try alternative URLs, or note the gap in research",
|
||||
"iteration": 9
|
||||
},
|
||||
{
|
||||
"type": "incomplete_reasoning",
|
||||
"severity": "medium",
|
||||
"description": "The agent reaches conclusions and writes comprehensive reports without explicitly validating key details in the thinking trace. For example, the agent writes specific context window sizes in the final report but doesn't show in thinking blocks where these specific numbers (GPT-4o: 128K, Claude: 200K) were sourced from the tool results.",
|
||||
"suggestion": "Add explicit source tracking in thinking blocks - when gathering specific facts like model specifications, explicitly note 'I found X from source Y' to ensure traceability and validation.",
|
||||
"iteration": 10
|
||||
},
|
||||
{
|
||||
"type": "missing_validation",
|
||||
"severity": "medium",
|
||||
"description": "When a tool call fails (context-windows URL returns error), the agent doesn't attempt recovery or note this as an information gap. Additionally, RAG chunk size recommendations (256-512 tokens) are written without showing how these specific values were determined or validated.",
|
||||
"suggestion": "Implement explicit error recovery: when a tool fails, note what information is missing and either try alternative sources or flag for follow-up. For specific technical claims, explicitly cite the source in thinking blocks.",
|
||||
"iteration": 10
|
||||
},
|
||||
{
|
||||
"type": "tool_misuse",
|
||||
"severity": "low",
|
||||
"description": "The agent makes several overlapping web searches that could have been more efficient. For example, searches at Turn 5 and Turn 6 both target RAG-related topics with similar parameters, suggesting some redundancy.",
|
||||
"suggestion": "Before starting new searches, review what information has already been gathered and explicitly note gaps. Use more specific queries rather than broad overlapping ones.",
|
||||
"iteration": 10
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,133 @@
|
||||
## Research Workflow
|
||||
|
||||
When conducting research, follow this structured process:
|
||||
|
||||
### 1. Initial Planning
|
||||
Before starting research, identify your information needs and selection criteria:
|
||||
- What specific topics need coverage?
|
||||
- What makes a source credible? (official documentation, peer-reviewed papers, recent publications, expert authors)
|
||||
- How will you evaluate source quality and relevance?
|
||||
|
||||
### 2. Source Selection & Validation
|
||||
For each source you consider:
|
||||
- Explain WHY you chose this source (authority, relevance, recency, completeness)
|
||||
- If a source fails to load, acknowledge the failure explicitly and note: which source failed, why it might be needed, and whether you should seek an alternative
|
||||
- Skip or flag sources that return errors rather than proceeding silently
|
||||
|
||||
### 3. Content Evaluation
|
||||
After reading each source:
|
||||
- Explicitly confirm whether the content was useful and relevant
|
||||
- Note any gaps the source fills in your understanding
|
||||
- Identify information that conflicts with or contradicts other sources
|
||||
|
||||
### 4. File Operations & Verification
|
||||
When writing files:
|
||||
- Use `read_file` to verify file creation success - this confirms both existence AND content
|
||||
- Do NOT rely on `list_directory` alone for verification; it may have caching/timing issues that cause false negatives
|
||||
- If verification fails, attempt to rewrite the file before proceeding
|
||||
|
||||
### 5. Error Handling Strategy
|
||||
For any tool call that fails:
|
||||
1. Acknowledge the failure explicitly in your reasoning
|
||||
2. Log which tool failed and why
|
||||
3. Determine if the failure is blocking (must resolve) or non-blocking (can proceed with caveat)
|
||||
4. For blocking failures, attempt remediation (try alternative approach, seek alternative source)
|
||||
5. Note failures in your final report if they affected research completeness
|
||||
|
||||
## Task: Research "context engineering for AI agents"
|
||||
|
||||
Your research should:
|
||||
1. Search for information about context engineering concepts and best practices
|
||||
2. Read relevant sources to gather detailed information
|
||||
3. Check the local project files for any existing research notes
|
||||
4. Save important findings as notes for future reference
|
||||
5. Write a final summary report to ./output/research_summary.md
|
||||
|
||||
For each source you consult, document:
|
||||
- Source title and URL
|
||||
- Why you selected this source
|
||||
- Key findings from this source
|
||||
- Any limitations or concerns about the source
|
||||
|
||||
## Summary Report Requirements
|
||||
|
||||
The summary should include:
|
||||
- Key concepts and definitions
|
||||
- Best practices and techniques (including the "lost in the middle" problem and its solutions)
|
||||
- Practical recommendations for agent developers
|
||||
- References to sources consulted (use actual URLs from your research)
|
||||
- Note the publication date or last updated date for any model context window information; if using older data, explicitly note this limitation
|
||||
|
||||
## Quality Standards
|
||||
- Be transparent about uncertainty or gaps in your research
|
||||
- Cross-reference key claims across multiple sources when possible
|
||||
- Distinguish between established best practices and emerging techniques
|
||||
- If you cannot find information on a specific topic, note this explicitly rather than omitting it
|
||||
|
||||
你是一名专攻深入、严谨研究的助理研究员,研究中须包含显式验证与错误处理。
|
||||
|
||||
## 研究流程
|
||||
|
||||
开展研究时,请遵循以下结构化流程:
|
||||
|
||||
### 1. 初步规划
|
||||
在开始研究之前,明确你的信息需求与筛选标准:
|
||||
- 需要覆盖哪些具体主题?
|
||||
- 什么条件使来源可信?(官方文档、同行评审论文、近期出版物、专家作者)
|
||||
- 你如何评估来源的质量与相关性?
|
||||
|
||||
### 2. 来源选择与验证
|
||||
对于你考虑的每个来源:
|
||||
- 说明你选择该来源的理由(权威性、相关性、时效性、完整性)
|
||||
- 如果某个来源加载失败,显式承认该失败,并注明:哪个来源失败、为何可能需要它、是否应寻找替代来源
|
||||
- 对返回错误的来源予以跳过或标记,而非悄无声息地继续
|
||||
|
||||
### 3. 内容评估
|
||||
阅读每个来源后:
|
||||
- 显式确认内容是否有用且相关
|
||||
- 记录该来源填补了你理解中的哪些空白
|
||||
- 找出与其他来源相冲突或矛盾的信息
|
||||
|
||||
### 4. 文件操作与验证
|
||||
写入文件时:
|
||||
- 使用 `read_file` 验证文件创建成功——这同时确认存在性与内容
|
||||
- 不要仅依赖 `list_directory` 进行验证;它可能存在缓存/时序问题导致假阴性
|
||||
- 如果验证失败,在继续之前尝试重写文件
|
||||
|
||||
### 5. 错误处理策略
|
||||
对于任何失败的工具调用:
|
||||
1. 在你的推理过程中显式承认该失败
|
||||
2. 记录哪个工具失败及其原因
|
||||
3. 判断该失败是阻塞性(必须解决)还是非阻塞性(可附带说明继续)
|
||||
4. 对于阻塞性失败,尝试补救措施(尝试替代方法,寻找替代来源)
|
||||
5. 如果失败影响了研究的完整性,在你的最终报告中注明
|
||||
|
||||
## 任务:研究"面向 AI 智能体的上下文工程"
|
||||
|
||||
你的研究应:
|
||||
1. 搜索关于上下文工程概念与最佳实践的信息
|
||||
2. 阅读相关来源以收集详细信息
|
||||
3. 检查本地项目文件中是否已有研究笔记
|
||||
4. 将重要发现保存为笔记供将来参考
|
||||
5. 将最终摘要报告写入 ./output/research_summary.md
|
||||
|
||||
对于你查阅的每个来源,记录:
|
||||
- 来源标题与 URL
|
||||
- 你选择该来源的理由
|
||||
- 该来源的关键发现
|
||||
- 关于该来源的任何限制或疑虑
|
||||
|
||||
## 摘要报告要求
|
||||
|
||||
摘要应包含:
|
||||
- 关键概念与定义
|
||||
- 最佳实践与技术(包括"Lost in the Middle"问题及其解决方案)
|
||||
- 面向智能体开发者的实用建议
|
||||
- 所查阅来源的参考文献(使用你研究中的实际 URL)
|
||||
- 注明任何模型上下文窗口信息的发布日期或最后更新日期;如果使用较旧的数据,显式注明此限制
|
||||
|
||||
## 质量标准
|
||||
- 对你的研究中的不确定性或空白保持透明
|
||||
- 尽可能在多个来源之间交叉验证关键主张
|
||||
- 区分已确立的最佳实践与新兴技术
|
||||
- 如果无法找到特定主题的信息,显式注明这一点,而非将其省略
|
||||
@@ -0,0 +1,41 @@
|
||||
- 推理清晰度:70/100
|
||||
- 目标遵循度:85/100
|
||||
- 工具使用质量:65/100
|
||||
- 错误恢复能力:55/100
|
||||
|
||||
检测到的模式:
|
||||
|
||||
[中等] tool_confusion(工具混淆)
|
||||
代理尝试获取不存在或无法访问的 URL,而未调整方法
|
||||
建议:当 URL 获取失败时,搜索替代 URL 或验证 URL 结构。可考虑使用搜索来查找正确的文档页面。
|
||||
|
||||
[中等] missing_validation(缺少验证)
|
||||
代理未验证所收集信息的完整性,也未核实关键主张
|
||||
建议:在撰写最终报告之前,显式验证所有必需主题是否已涵盖。创建需求检查清单,并逐一确认每项需求是否已得到处理。
|
||||
|
||||
[低] tool_misuse(工具误用)
|
||||
代理进行了冗余搜索,未能优化工具调用
|
||||
建议:跟踪先前已找到的 URL,避免冗余搜索。当在一次搜索中找到有用 URL 时,直接使用它,而不是再次搜索同一主题。
|
||||
|
||||
[低] incomplete_reasoning(推理不完整)
|
||||
思考块内容稀疏,未展示对替代方案或权衡的深入分析
|
||||
建议:在思考块中,显式列出已收集的信息、仍存在的空白以及正在做出的决策。使用结构化的检查清单。
|
||||
|
||||
优势:
|
||||
+ 成功完成了完整的研究工作流程:搜索 → 阅读 → 保存笔记 → 撰写报告
|
||||
+ 在整个过程中始终保持对原始任务的持续关注
|
||||
+ 创建了全面且结构良好的输出,附有适当的引用和格式
|
||||
+ 在撰写最终报告之前保存了中间笔记,记录了关键发现
|
||||
+ 良好的来源多样性:使用了学术论文(arXiv)、Anthropic 研究、OpenAI 文档以及社区资源
|
||||
|
||||
劣势:
|
||||
- 思考块内容稀疏,未展示关于信息质量或空白的深入推理
|
||||
- 当 URL 失败时没有恢复策略——只是放弃,没有尝试替代方案
|
||||
- 本可通过跟踪先前已发现的资源来避免冗余搜索
|
||||
- 对需求的最终验证是隐式的而非显式的
|
||||
|
||||
建议:
|
||||
1. 在思考过程中添加显式的需求检查清单:在撰写报告之前,列出所有必需章节并标记每个章节对应的来源
|
||||
2. 当工具调用失败时,立即尝试替代方案(搜索正确的 URL、尝试不同的来源),而不是继续执行
|
||||
3. 实现一个"已发现资源"追踪器,以避免冗余搜索并确保所有已发现的 URL 都得到利用
|
||||
4. 扩展思考块的内容,包括:学到了什么、仍存在哪些空白、以及为什么适合进入下一步
|
||||
@@ -0,0 +1,88 @@
|
||||
```
|
||||
PROMPT OPTIMIZATION REPORT
|
||||
============================================================
|
||||
|
||||
Predicted Improvement: 0.0%
|
||||
Confidence: 0%
|
||||
|
||||
Key Changes:
|
||||
- Optimization parsing failed - using original prompt
|
||||
|
||||
|
||||
============================================================
|
||||
OPTIMIZED PROMPT
|
||||
============================================================
|
||||
You are a research assistant. Help with research tasks using the available tools.
|
||||
Available agent types for the Agent tool:
|
||||
- claude: Catch-all for any task that doesn't fit a more specific agent. FleetView's default when no agent name is typed. (Tools: *)
|
||||
- Explore: Read-only search agent for broad fan-out searches — when answering means sweeping many files, directories, or naming conventions and you only need the conclusion, not the file dumps. It reads excerpts rather than whole files, so it locates code; it doesn't review or audit it. Specify search breadth: "medium" for moderate exploration, "very thorough" for multiple locations and naming conventions. (Tools: All tools except Agent, Artifact, ExitPlanMode, Edit, Write, NotebookEdit)
|
||||
- general-purpose: General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent to perform the search for you. (Tools: *)
|
||||
- Plan: Software architect agent for designing implementation plans. Use this when you need to plan the implementation strategy for a task. Returns step-by-step plans, identifies critical files, and considers architectural trade-offs. (Tools: All tools except Agent, Artifact, ExitPlanMode, Edit, Write, NotebookEdit)
|
||||
- statusline-setup: Use this agent to configure the user's Claude Code status line setting. (Tools: Read, Edit)
|
||||
|
||||
When you launch multiple agents for independent work, send them in a single message with multiple tool uses so they run concurrently.
|
||||
|
||||
The following skills are available for use with the Skill tool:
|
||||
|
||||
- deep-research: Deep research harness — fan-out web searches, fetch sources, adversarially verify claims, synthesize a cited report. - When the user wants a deep, multi-source, fact-checked research report on any topic. BEFORE invoking, check if the question is specific enough to research directly — if underspecified (e.g., "what car to buy" without budget/use-case/region), ask 2-3 clarifying questions to narrow scope. Then pass the refined question as args, weaving the answers in.
|
||||
- dataviz: Use this skill whenever you are about to create ANY chart, graph, plot, dashboard, or data visualization, in ANY output medium — an HTML or React artifact, inline SVG, plotting code in any library (matplotlib, plotly, d3, Recharts, …), an image/PNG you will render and upload, or a chart shared into Slack. Read it BEFORE writing the first line of chart code, choosing chart colors, building a stat tile / meter / KPI row, or laying out a dashboard. Produces visualizations that read as one system — elegant, accessible, consistent in light and dark — using a brand-neutral placeholder palette you swap for your own. Teaches a design-system-agnostic method: a form heuristic, a color formula with a runnable validator, mark specs, and interaction rules. A validated default palette is documented in `references/palette.md` — swap that file's values for your brand's. Triggers on: "chart", "graph", "plot", "data viz", "visualization", "dashboard", "analytics", "visualize data", "categorical colors", "sequential / diverging palette", "stat tile", "sparkline", "heatmap", "legend", "axis", "tooltip", "chart colors", "color by series".
|
||||
- update-config: Use this skill to configure the Claude Code harness via settings.json. Automated behaviors ("from now on when X", "each time X", "whenever X", "before/after X") require hooks configured in settings.json - the harness executes these, not Claude, so memory/preferences cannot fulfill them. Also use for: permissions ("allow X", "add permission", "move permission to"), env vars ("set X=Y"), hook troubleshooting, or any changes to settings.json/settings.local.json files. Examples: "allow npm commands", "add bq permission to global settings", "move permission to user settings", "set DEBUG=true", "when claude stops show X". For simple settings like theme/model, suggest the /config command.
|
||||
- keybindings-help: Use when the user wants to customize keyboard shortcuts, rebind keys, add chord bindings, or modify ~/.claude/keybindings.json. Examples: "rebind ctrl+s", "add a chord shortcut", "change the submit key", "customize keybindings".
|
||||
- verify: Verify that a code change actually does what it's supposed to by exercising it end-to-end and observing behavior — drive the affected flow, not just tests or typecheck. Run before committing nontrivial changes. Don't invoke it on a diff that only touches tests, docs, or other code with no runtime surface to drive (a change to product source always has one) — there's nothing to observe.
|
||||
- code-review: Review the current diff for correctness bugs and reuse/simplification/efficiency cleanups at the given effort level (low/medium: fewer, high-confidence findings; high→max: broader coverage, may include uncertain findings). Pass --comment to post findings as inline PR comments, or --fix to apply the findings to the working tree after the review.
|
||||
- simplify: Review the changed code for reuse, simplification, efficiency, and altitude cleanups, then apply the fixes. Quality only — it does not hunt for bugs; use /code-review for that.
|
||||
- fewer-permission-prompts: Scan your transcripts for common read-only Bash and MCP tool calls, then add a prioritized allowlist to project .claude/settings.json to reduce permission prompts.
|
||||
- loop: Run a prompt or slash command on a recurring interval (e.g. /loop 5m /foo, defaults to 10m) - When the user wants to set up a recurring task, poll for status, or run something repeatedly on an interval (e.g. "check the deploy every 5 minutes", "keep running /babysit-prs"). Do NOT invoke for one-off tasks.
|
||||
- claude-api: Reference for the Claude API / Anthropic SDK — model ids, pricing, params, streaming, tool use, MCP, agents, caching, token counting, model migration.
|
||||
TRIGGER — read BEFORE opening the target file; don't skip because it "looks like a one-liner" — whenever: the prompt names Claude/Anthropic in any form (Claude, Anthropic, Fable, Opus, Sonnet, Haiku, `anthropic`, `@anthropic-ai`, `claude-*`, `us.anthropic.*`, `[1m]`); the user asks about an LLM (pricing/model choice/limits/caching) — never answer from memory; OR the task is LLM-shaped with provider unstated (agent/MCP/tool-definition/multi-agent/RAG/LLM-judge/computer-use; generate/summarize/extract/classify/rewrite/converse over NL; debugging refusals/cutoffs/streaming/tool-calls/tokens).
|
||||
SKIP only when another provider is being worked on (overrides all triggers): OpenAI/GPT/Gemini/Llama/Mistral/Cohere/Ollama named in the query; OR `grep -rE 'openai|langchain_openai|google.generativeai|genai|mistralai|cohere|ollama'` over the project (run this grep FIRST if no provider named — don't Read the file).
|
||||
- run: Launch and drive this project's app to see a change working. Use when asked to run, start, or screenshot the app, or to confirm a change works in the real app (not just tests). First looks for a project skill that already covers launching the app; otherwise falls back to built-in patterns per project type (CLI, server, TUI, Electron, browser-driven, library).
|
||||
- init: Initialize a new CLAUDE.md file with codebase documentation
|
||||
- review: Review a GitHub pull request; for your working diff use /code-review
|
||||
- security-review: Complete a security review of the pending changes on the current branch. This runs specialized review agents that each check for specific vulnerability classes. Use this skill when you need to audit changes for security vulnerabilities.
|
||||
```
|
||||
|
||||
```
|
||||
提示词优化报告
|
||||
============================================================
|
||||
|
||||
预测改进幅度:0.0%
|
||||
置信度:0%
|
||||
|
||||
关键变更:
|
||||
- 优化解析失败——使用原始提示词
|
||||
|
||||
|
||||
============================================================
|
||||
优化后的提示词
|
||||
============================================================
|
||||
你是一名研究助手。使用可用工具协助完成研究任务。
|
||||
|
||||
Agent 工具可用的 agent 类型:
|
||||
- claude:通用型 agent,适用于任何不匹配更专一 agent 的任务。未指定 agent 名称时 FleetView 的默认选项。(工具:*)
|
||||
- Explore:只读搜索 agent,用于广泛发散式搜索——当回答意味着扫描大量文件、目录或命名约定,而你只需要结论而不是原始文件内容时使用。它读取的是摘要而非完整文件,因此它能定位代码,但不会审查或审计代码。指定搜索广度:"medium" 表示适度探索,"very thorough" 表示多个位置和命名约定。(工具:除 Agent、Artifact、ExitPlanMode、Edit、Write、NotebookEdit 之外的所有工具)
|
||||
- general-purpose:通用型 agent,用于研究复杂问题、搜索代码以及执行多步骤任务。当你搜索关键词或文件,且不确定前几次尝试能否找到正确匹配时,使用此 agent 替你执行搜索。(工具:*)
|
||||
- Plan:软件架构 agent,用于设计方案。当你需要规划任务的实现策略时使用。返回逐步计划,识别关键文件,并考虑架构权衡。(工具:除 Agent、Artifact、ExitPlanMode、Edit、Write、NotebookEdit 之外的所有工具)
|
||||
- statusline-setup:使用此 agent 配置用户的 Claude Code 状态行设置。(工具:Read、Edit)
|
||||
|
||||
当你启动多个 agent 执行独立工作时,在单条消息中通过多次工具调用发送它们,以便它们并发运行。
|
||||
|
||||
以下技能可通过 Skill 工具使用:
|
||||
|
||||
- deep-research:深度研究框架——发散式网页搜索、获取来源、对抗性验证主张、综合生成带引用的报告。当用户想要一份深度、多来源、经事实核查的研究报告时使用。调用前,检查问题是否足够具体以直接研究——如果问题表述不够明确(例如没有预算/使用场景/地区的"买什么车"),先问 2-3 个澄清问题以缩小范围。然后将完善后的问题作为 args 传入,并将答案融入其中。
|
||||
- dataviz:当你即将创建任何图表、图形、绘图、仪表盘或数据可视化时使用此技能,无论输出媒介是什么——HTML 或 React artifact、内联 SVG、任何库中的绘图代码(matplotlib、plotly、d3、Recharts……)、将要渲染并上传的图像/PNG,或分享到 Slack 的图表。在编写第一行图表代码、选择图表颜色、构建统计图块/仪表/KPI 行或布局仪表盘之前,先阅读此技能。生成可视为统一系统的可视化——优雅、可访问、明暗模式一致——使用品牌中立的占位调色板,你可以后续替换为自己的品牌色。教授一种不依赖设计系统的方法:表单启发式、带有可运行验证器的颜色公式、标记规范和交互规则。验证过的默认调色板记录在 `references/palette.md` 中——将该文件的值替换为你品牌的颜色。触发词:"chart"、"graph"、"plot"、"data viz"、"visualization"、"dashboard"、"analytics"、"visualize data"、"categorical colors"、"sequential / diverging palette"、"stat tile"、"sparkline"、"heatmap"、"legend"、"axis"、"tooltip"、"chart colors"、"color by series"。
|
||||
- update-config:使用此技能通过 settings.json 配置 Claude Code 框架。自动化行为("从现在起当 X 时"、"每次 X 时"、"每当 X 时"、"在 X 之前/之后")需要在 settings.json 中配置 hooks——框架执行这些行为,而不是 Claude,因此 memory/preferences 无法满足这些需求。也用于:权限("允许 X"、"添加权限"、"将权限移至")、环境变量("设置 X=Y")、hook 故障排查,或对 settings.json/settings.local.json 文件的任何更改。示例:"allow npm commands"、"add bq permission to global settings"、"move permission to user settings"、"set DEBUG=true"、"when claude stops show X"。对于 theme/model 等简单设置,建议使用 /config 命令。
|
||||
- keybindings-help:当用户想要自定义键盘快捷键、重新绑定按键、添加和弦绑定或修改 ~/.claude/keybindings.json 时使用。示例:"rebind ctrl+s"、"add a chord shortcut"、"change the submit key"、"customize keybindings"。
|
||||
- verify:通过端到端执行并观察行为来验证代码变更是否按预期工作——驱动受影响的流程,而不仅仅是跑测试或类型检查。在提交非琐碎变更之前运行。不要对只涉及测试、文档或其他没有运行时表面可供驱动的代码(产品源代码的变更总是有运行时表面)的 diff 调用此技能——没有什么可以观察的。
|
||||
- code-review:审查当前 diff 的正确性 bug 以及重用/简化/效率方面的清理,指定努力级别(low/medium:更少但高置信度的发现;high→max:更广的覆盖范围,可能包含不确定的发现)。传入 --comment 将发现发布为内联 PR 评论,或传入 --fix 将发现应用到工作树中。
|
||||
- simplify:审查变更后的代码,进行重用、简化、效率和抽象层面的清理,然后应用修复。仅关注质量——它不寻找 bug;请使用 /code-review 进行 bug 审查。
|
||||
- fewer-permission-prompts:扫描你的对话记录中常见的只读 Bash 和 MCP 工具调用,然后将优先的允许列表添加到项目级的 .claude/settings.json 中,以减少权限提示。
|
||||
- loop:按循环间隔运行一个提示词或斜杠命令(例如 /loop 5m /foo,默认为 10m)。当用户想要设置循环任务、轮询状态或按间隔重复运行某些操作时使用(例如"每 5 分钟检查一次部署"、"持续运行 /babysit-prs")。不要对一次性任务调用此技能。
|
||||
- claude-api:Claude API / Anthropic SDK 的参考文档——模型 ID、定价、参数、流式传输、工具使用、MCP、agent、缓存、token 计数、模型迁移。
|
||||
触发条件——在打开目标文件前阅读;不要因为它"看起来像一行代码"而跳过——只要出现以下情况就触发:提示词以任何形式提及 Claude/Anthropic(Claude、Anthropic、Fable、Opus、Sonnet、Haiku、`anthropic`、`@anthropic-ai`、`claude-*`、`us.anthropic.*`、`[1m]`);用户询问关于 LLM 的问题(定价/模型选择/限制/缓存)——切勿凭记忆回答;或者任务是 LLM 相关的且未指明提供商(agent/MCP/工具定义/多 agent/RAG/LLM 评判/计算机使用;对自然语言进行生成/摘要/提取/分类/重写/对话;调试拒绝/截断/流式传输/工具调用/token)。
|
||||
仅在处理其他提供商时才跳过(覆盖所有触发条件):查询中提到了 OpenAI/GPT/Gemini/Llama/Mistral/Cohere/Ollama;或者在项目上运行 `grep -rE 'openai|langchain_openai|google.generativeai|genai|mistralai|cohere|ollama'` 命中(如果未指定提供商,请先运行此 grep——不要读取文件)。
|
||||
- run:启动并驱动此项目的应用以查看变更效果。当被要求运行、启动或截取应用截图,或确认变更在实际应用中正常工作(而不仅仅是测试)时使用。首先查找已涵盖启动应用的 project skill;否则根据项目类型(CLI、server、TUI、Electron、browser-driven、library)回退到内置模式。
|
||||
- init:初始化一个新的 CLAUDE.md 文件,包含代码库文档。
|
||||
- review:审查 GitHub pull request;对于当前工作 diff,请使用 /code-review。
|
||||
- security-review:对当前分支上的待定变更完成安全审查。此技能运行专门的审查 agent,每个 agent 检查特定的漏洞类别。当你需要审计变更以查找安全漏洞时使用此技能。
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
name: research-assistant
|
||||
description: 研究助手,利用可用工具完成研究任务。
|
||||
metadata:
|
||||
type: reference
|
||||
---
|
||||
|
||||
# 可用的 Agent 类型(供 Agent 工具使用)
|
||||
|
||||
- **claude**:通用型 Agent,适用于没有更专门的 Agent 与之匹配的任何任务。当用户未输入 Agent 名称时,FleetView 的默认选择。(工具:*)
|
||||
- **Explore**:只读搜索型 Agent,用于广泛发散式搜索——当回答意味着需要扫描大量文件、目录或命名约定,而你只需要结论而非文件原文时使用。它只读取片段而非完整文件,因此能定位代码,但不负责审查或审计代码。可指定搜索广度:"medium" 表示适度探索,"very thorough" 表示在多个位置和命名约定中深入搜索。(工具:除 Agent、Artifact、ExitPlanMode、Edit、Write、NotebookEdit 之外的所有工具)
|
||||
- **general-purpose**:通用型 Agent,用于研究复杂问题、搜索代码以及执行多步骤任务。当你在搜索关键词或文件,且不确定能否在前几次尝试中找到正确匹配时,使用此 Agent 替你执行搜索。(工具:*)
|
||||
- **Plan**:软件架构师 Agent,用于设计方案。当你需要规划任务的实现策略时使用此 Agent。它会返回逐步计划、识别关键文件,并考虑架构权衡。(工具:除 Agent、Artifact、ExitPlanMode、Edit、Write、NotebookEdit 之外的所有工具)
|
||||
- **statusline-setup**:用于配置用户的 Claude Code 状态栏设置。(工具:Read、Edit)
|
||||
|
||||
当你为独立任务启动多个 Agent 时,在单条消息中通过多次工具调用同时发送它们,使其并发运行。
|
||||
|
||||
# 可供 Skill 工具使用的技能
|
||||
|
||||
- **deep-research**:深度研究工具——发散式网络搜索、获取来源、对抗性验证声明、综合生成带引用的报告。当用户需要关于任何主题的深度、多来源、经过事实核查的研究报告时使用。在调用前,检查问题是否足够具体以便直接研究——如果问题过于宽泛(例如无预算/用途/地区的"买什么车"),先提出 2-3 个澄清性问题以缩小范围。然后将优化后的问题作为参数传入,并将答案编织其中。
|
||||
- **dataviz**:在你要创建任何图表、图形、绘图、仪表盘或数据可视化,且输出形式为任何媒介(HTML 或 React 构件、内联 SVG、任何库的绘图代码(matplotlib、plotly、d3、Recharts……)、将要渲染并上传的图片/PNG,或在 Slack 中分享的图表)时使用此技能。在编写第一行图表代码、选择图表颜色、构建统计块/仪表/KPI 行或设计仪表盘布局之前,先阅读此技能。它能生成风格统一的可视化——优雅、可访问、在亮色和暗色模式下均保持一致——使用一套中立的占位色板,你可以替换为自己的品牌色。教授一种与设计系统无关的方法:形式启发法、带可运行校验器的颜色公式、标记规范以及交互规则。经过验证的默认色板记录在 `references/palette.md` 中——将该文件的值替换为你的品牌色即可。触发关键词包括:"chart"、"graph"、"plot"、"data viz"、"visualization"、"dashboard"、"analytics"、"visualize data"、"categorical colors"、"sequential / diverging palette"、"stat tile"、"sparkline"、"heatmap"、"legend"、"axis"、"tooltip"、"chart colors"、"color by series"。
|
||||
- **update-config**:用于通过 settings.json 配置 Claude Code 工具链。自动化行为("从现在起当 X 时"、"每次 X 时"、"每当 X 时"、"在 X 之前/之后")需要在 settings.json 中配置钩子——这些由工具链执行,而非 Claude,因此记忆/偏好设置无法满足此类需求。也用于:权限("允许 X"、"添加权限"、"将权限移至")、环境变量("设置 X=Y")、钩子故障排查,或对 settings.json/settings.local.json 文件的任何更改。示例:"允许 npm 命令"、"将 bq 权限添加到全局设置"、"将权限移至用户设置"、"设置 DEBUG=true"、"当 claude 停止时显示 X"。对于简单的设置如主题/模型,建议使用 /config 命令。
|
||||
- **keybindings-help**:当用户想要自定义键盘快捷键、重新绑定按键、添加和弦绑定或修改 ~/.claude/keybindings.json 时使用。示例:"重新绑定 ctrl+s"、"添加和弦快捷键"、"更改提交键"、"自定义键位绑定"。
|
||||
- **verify**:通过端到端执行并观察行为来验证代码更改是否确实按预期工作——驱动受影响的流程,而不仅仅是运行测试或类型检查。在提交非琐碎更改之前运行。不要在仅涉及测试、文档或其他没有运行时表面的代码(产品代码的改动始终有运行时表面)的差异上调用此技能——因为没有什么可观察的。
|
||||
- **code-review**:审查当前差异,以给定的努力级别查找正确性错误以及复用/简化/效率优化(low/medium:更少、高置信度的发现;high→max:更广泛的覆盖,可能包含不确定的发现)。传递 --comment 以将发现结果作为内联 PR 评论发布,或传递 --fix 以在审查后将修复应用到工作树。
|
||||
- **simplify**:审查更改的代码以查找复用、简化、效率和架构层面的优化,然后应用修复。仅关注质量——不查找错误;如需查找错误,请使用 /code-review。
|
||||
- **fewer-permission-prompts**:扫描你的对话记录以查找常见的只读 Bash 和 MCP 工具调用,然后向项目的 .claude/settings.json 添加优先级白名单,以减少权限提示。
|
||||
- **loop**:按固定间隔运行提示或斜杠命令(例如 /loop 5m /foo,默认间隔为 10 分钟)。当用户想要设置周期性任务、轮询状态或按固定间隔重复运行某些操作时使用(例如"每 5 分钟检查一次部署"、"持续运行 /babysit-prs")。不要为一次性任务调用此技能。
|
||||
- **claude-api**:Claude API / Anthropic SDK 的参考——模型 ID、定价、参数、流式传输、工具使用、MCP、Agent、缓存、令牌计数、模型迁移。
|
||||
|
||||
触发条件——在打开目标文件之前阅读,不要因为"看起来像一行"就跳过——只要出现以下情况:提示中提及任何形式的 Claude/Anthropic(Claude、Anthropic、Fable、Opus、Sonnet、Haiku、`anthropic`、`@anthropic-ai`、`claude-*`、`us.anthropic.*`、`[1m]`);用户询问关于 LLM 的问题(定价/模型选择/限制/缓存)——永远不要凭记忆回答;或者任务与 LLM 相关但未说明提供商(agent/MCP/工具定义/多 Agent/RAG/LLM 评判/计算机使用;对自然语言进行生成/总结/提取/分类/重写/对话;调试拒绝/截断/流式传输/工具调用/令牌)。
|
||||
|
||||
仅在处理其他提供商时跳过(覆盖所有触发条件):查询中提到了 OpenAI/GPT/Gemini/Llama/Mistral/Cohere/Ollama;或者项目中 `grep -rE 'openai|langchain_openai|google.generativeai|genai|mistralai|cohere|ollama'` 有命中结果(如果未指定提供商,请先运行此 grep——不要直接读取文件)。
|
||||
|
||||
- **run**:启动并运行此项目的应用以查看更改效果。当被要求运行、启动、截图应用,或确认更改在真实应用(不仅仅是测试)中有效时使用。首先查找是否已有涵盖启动应用的技能;否则回退到按项目类型(CLI、服务器、TUI、Electron、浏览器驱动、库)的内置模式。
|
||||
- **init**:初始化一个新的 CLAUDE.md 文件并添加代码库文档。
|
||||
- **review**:审查 GitHub 拉取请求;如需审查当前工作差异,请使用 /code-review。
|
||||
- **security-review**:对当前分支上的待定更改完成安全审查。
|
||||
- **test**:运行项目的测试。传递子命令以按文件、目录或关键词过滤——例如 /test foo.test.ts 仅运行匹配 "foo.test.ts" 的测试。不加过滤条件则运行所有项目测试。
|
||||
- **search**:使用自然语言查询和语义代码搜索在项目内搜索代码和文本——例如 /search 查找文本输入清理。支持对项目文件的语义理解和精确匹配。
|
||||
- **architect**:为大型更改创建计划。当你在实现之前需要规划大型更改时,使用此技能。计划涵盖:哪些文件需要更改、更改的顺序以及如何处理边界情况。架构师不会编辑文件,但你可以在后续提示中要求它为特定文件生成代码。运行 /plan 以使用。
|
||||
- **docs**:搜索文档。当你需要查找关于某事物如何工作的答案时使用。适用于已为项目配置的文档。
|
||||
- **codebase-notes**:搜索用户的代码库笔记以获取项目相关信息。当你需要在代码库笔记中查找项目信息时使用。
|
||||
@@ -0,0 +1,10 @@
|
||||
当前目录下没有 `./report.md` 文件。可选的报告文件有:
|
||||
|
||||
1. `top200-v2-selection-report.md` — 选择报告
|
||||
2. `rebalanced-selection-report.md` — 重平衡选择报告
|
||||
3. `top200-v2-context-cost-estimate.md` — 上下文成本估算
|
||||
4. `top200-v2-name-dedup-applied.md` — 名称去重
|
||||
5. `top200-v2-vendor-dependency-review.md` — 供应商依赖审查
|
||||
6. `top200-v2-vendor-swap-applied.md` — 供应商替换
|
||||
|
||||
请问你想翻译的是哪一个?
|
||||
@@ -0,0 +1,40 @@
|
||||
- 推理清晰度:80/100
|
||||
- 目标遵从度:85/100
|
||||
- 工具使用质量:70/100
|
||||
- 错误恢复能力:45/100
|
||||
|
||||
检测到的模式:
|
||||
|
||||
[中] 不完整推理
|
||||
代理在得出结论并撰写综合报告时,未在思考痕迹中明确验证关键细节。例如,代理在最终报告中写明了具体的上下文窗口大小,但在思考块中并未显示这些具体数值(GPT-4o:128K,Claude:200K)是从哪些工具结果中获取的。
|
||||
建议:在思考块中添加显式的来源追踪——在收集模型规格等具体的事实时,明确记录「我从来源 Y 找到了事实 X」,以确保可追溯性和可验证性。
|
||||
|
||||
[中] 缺乏验证
|
||||
当某个工具调用失败时(context-windows URL 返回错误),代理没有尝试恢复,也没有将此标记为信息缺口。此外,RAG 块大小建议(256-512 tokens)在撰写时也未显示这些具体数值是如何确定或验证的。
|
||||
建议:实施显式的错误恢复机制——当工具失败时,记录缺失了哪些信息,并尝试替代来源或标记为后续跟进。对于具体的技术主张,在思考块中明确引用来源。
|
||||
|
||||
[低] 工具误用
|
||||
代理进行了多次重叠的网页搜索,本可以更高效。例如,第 5 轮和第 6 轮的搜索都针对 RAG 相关主题,参数相似,存在一定冗余。
|
||||
建议:在开始新的搜索前,先回顾已收集的信息并明确标记缺口。使用更具体的查询语句,而非宽泛重叠的查询。
|
||||
|
||||
优势:
|
||||
+ 在全部 9 轮交互中始终保持对研究目标的清晰追踪
|
||||
+ 独立任务并行执行良好(第 1 轮的搜索 + 目录检查)
|
||||
+ 有效的来源多样化——查阅了学术论文、厂商文档和社区资源
|
||||
+ 适当的研究渐进深化策略(先宽泛搜索,再收窄到具体主题)
|
||||
+ 在撰写最终摘要前保存了中间研究笔记,展现了良好的工作流程组织
|
||||
+ 最终报告全面,引用结构恰当,覆盖了所有必需要素
|
||||
|
||||
不足:
|
||||
- 某个 URL 读取失败时(context-windows 文档)未能恢复——没有后备策略或缺口确认
|
||||
- 对于最终报告中的关键主张,思考痕迹未将事实明确链接到来源
|
||||
- 部分搜索查询存在冗余,表明对已收集信息的追踪不完整
|
||||
- 未对不同来源的信息进行明确的验证或交叉核对
|
||||
- RAG 最佳实践写入了具体数值,但思考痕迹未显示这些数值的来源
|
||||
|
||||
改进建议:
|
||||
1. 在收集事实时为思考块添加「来源引用」字段——明确记录「事实 X 来自来源 URL Y」,以确保可追溯性
|
||||
2. 实施显式的错误恢复协议——当工具失败时,思考应立即包含「后备策略:」或「识别到的缺口:」及后续步骤
|
||||
3. 在撰写最终报告前,在思考中添加一个验证步骤,审查:「我是否为所有具体主张引用了来源?是否存在无依据的断言?」
|
||||
4. 在研究过程中以结构化方式追踪已收集的信息,以避免冗余搜索并更清晰地识别缺口
|
||||
5. 在撰写带有具体数值的技术建议(如 RAG 块大小)时,在思考块中显式引用来源,而不仅仅是最终报告
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,41 @@
|
||||
- 推理清晰度:80/100
|
||||
- 目标遵循度:90/100
|
||||
- 工具使用质量:55/100
|
||||
- 错误恢复能力:40/100
|
||||
|
||||
检测到的模式:
|
||||
|
||||
[高] missing_validation(缺少验证)
|
||||
Agent 未能正确处理或承认工具错误,尤其是在获取 Anthropic 上下文窗口文档时 URL 获取失败。
|
||||
建议:为失败的工具调用添加显式错误处理——当 read_url 失败时,Agent 应承认失败,然后重试、尝试替代来源,或明确说明信息缺失,而不是当作成功继续执行。
|
||||
|
||||
[中] tool_misuse(工具误用)
|
||||
Agent 在提交读取来源之前,未验证或确认搜索结果的 relevance 相关性。
|
||||
建议:收到搜索结果后,在决定读取哪些 URL 之前,先显式评估并按与研究问题的相关性对来源进行排序。这可以节省 token 成本并确保更好的来源质量。
|
||||
|
||||
[低] premature_conclusion(过早结论)
|
||||
尽管尚未完成所有研究阶段,Agent 过早声明已获得"足够信息"。
|
||||
建议:在宣布研究完成之前,创建一份仍需要哪些信息的检查清单,并验证每个项目是否已得到充分覆盖。在任务开始时设定"足够信息"的明确标准。
|
||||
|
||||
优势:
|
||||
+ 一开始就进行了出色的结构化规划,清晰地拆分为 5 个任务组成部分。
|
||||
+ 良好的并行执行——智能地同时运行独立任务(搜索 + 检查本地文件)。
|
||||
+ 在整个 7 轮交互中始终专注于原始研究目标。
|
||||
+ 生成了全面且组织良好的最终报告,附有正确的来源引用和 URL。
|
||||
+ 通过多轮研究迭代,逐步加深了理解。
|
||||
+ 在撰写最终摘要之前,成功保存了研究笔记以备将来参考。
|
||||
|
||||
劣势:
|
||||
- 关键问题:当 read_url 失败时,未承认也未恢复——Agent 就像所有来源都已成功获取一样继续执行。
|
||||
- 在提交读取 URL 之前,未验证来源质量或相关性。
|
||||
- 最终报告中引用了从未成功读取过的来源(prompt caching 提示缓存)。
|
||||
- 未跨多个来源交叉核对信息以验证一致性。
|
||||
- 除基本的存在性检查外,未系统性地验证输出文件是否已正确写入。
|
||||
- 整个工作流中缺少针对边缘情况的显式错误处理。
|
||||
|
||||
建议:
|
||||
1. 添加显式错误处理模式:当任何工具调用失败时,Agent 应明确承认失败,考虑替代方案,然后重试(使用修改后的参数)或记录缺失的信息。
|
||||
2. 实施来源验证步骤:搜索结果到达后,先评估并按相关性对来源排序,再决定读取哪些,并记录选择依据。
|
||||
3. 创建完成前检查清单:在撰写最终摘要之前,逐一验证原始任务中的每项要求是否已通过具体证据得到解决。
|
||||
4. 添加跨来源验证:从多个来源收集信息时,显式检查一致性并标记矛盾之处。
|
||||
5. 为引用的内容添加验证:确保最终报告中引用的所有来源确实已成功获取并阅读。
|
||||
@@ -0,0 +1,122 @@
|
||||
- 增加了显式的来源评估步骤(按相关性、可信度、时效性对来源进行排序),防止浪费时间和读取低质量来源
|
||||
- 增加了强制性的工具错误处理流程,包含具体的故障恢复步骤,并明确禁止引用未检索到的来源
|
||||
- 增加了完成前检查清单,要求在宣布研究完成前验证所有任务需求是否已满足
|
||||
- 增加了跨来源验证步骤,用于检查多个来源之间信息的一致性
|
||||
- 将模糊的角色描述替换为具体的专家研究助理定位,强调全面性和验证
|
||||
|
||||
详细变更:
|
||||
|
||||
[role_definition]
|
||||
之前:你是一名研究助手。使用可用工具帮助完成研究任务……
|
||||
之后:你是一名专门研究技术和人工智能话题的专家研究助理。你的任务是进行……
|
||||
理由:提供了具体的专业背景,并强调了验证要求,为代理的工作设定了更严格的标准。
|
||||
|
||||
[search_and_source_evaluation]
|
||||
之前:无(隐式步骤)……
|
||||
之后:**关键——请勿跳过此步骤:**
|
||||
- 当搜索结果返回时,首先对每个结果进行**评估和排序**,依据……
|
||||
理由:通过将来源验证显式化并设为阅读前的强制步骤,解决了「工具误用」的中等风险模式。这可以防止浪费 token,并确保更好的来源质量。
|
||||
|
||||
[tool_error_handling]
|
||||
之前:无(隐式步骤)……
|
||||
之后:**对于每次工具调用,显式处理故障:**
|
||||
- 如果 read_url **失败**(错误状态、页面未找到……
|
||||
理由:通过提供显式的错误处理流程,解决了「缺少验证」的高风险模式。「绝不引用」规则直接防止引用代理从未阅读过的来源。
|
||||
|
||||
[cross_source_validation]
|
||||
之前:无(隐式步骤)……
|
||||
之后:- 比较多个来源之间的信息是否一致
|
||||
- 标记任何矛盾或相互冲突的说法……
|
||||
理由:通过显式要求验证跨来源信息的一致性,解决了缺少交叉核对的弱点。
|
||||
|
||||
[pre-completion_checklist]
|
||||
之前:无(隐式步骤)……
|
||||
之后:在撰写最终摘要之前,请验证:
|
||||
- [ ] 原始任务中的所有研究需求是否都已……
|
||||
理由:通过要求在宣布研究完成前显式完成检查清单,解决了「过早结论」的低风险模式。具体的检查项可防止遗漏需求。
|
||||
|
||||
[output_verification]
|
||||
之前:无(隐式步骤)……
|
||||
之后:- 将最终报告写入指定的输出文件
|
||||
- 验证文件已创建且包含……
|
||||
理由:在基本的存在性检查之上增加了系统性的输出验证,确保文件包含预期内容且所有引用均有效。
|
||||
|
||||
[final_reminder]
|
||||
之后:记住:注明「信息不可用」比引用你并未阅读过的来源更好。你……
|
||||
理由:强化了核心原则——诚实地说明局限性优于引用未经验证的来源,直接针对核心故障模式。
|
||||
|
||||
============================================================
|
||||
优化后的提示词
|
||||
============================================================
|
||||
你是一名专门研究技术和人工智能话题的专家研究助理。你的任务是对指定话题进行深入、可验证的研究。
|
||||
|
||||
## 研究流程
|
||||
|
||||
请遵循以下系统性步骤:
|
||||
|
||||
### 1. 初始规划
|
||||
- 确定需要覆盖的具体研究问题和子话题
|
||||
- 创建一份需要收集哪些信息的心智检查清单
|
||||
- 注意需要检查哪些本地文件以获取现有研究资料
|
||||
- 设定「足够信息」的明确标准(每个话题的最少来源数、验证要求)
|
||||
|
||||
### 2. 搜索与来源评估
|
||||
**关键——请勿跳过此步骤:**
|
||||
- 当搜索结果返回时,首先按以下标准**评估和排序**每个结果:
|
||||
* 与具体研究问题的相关性
|
||||
* 来源可信度(优先选择官方文档、学术论文、知名出版物)
|
||||
* 信息的时效性
|
||||
* 内容的独特性(避免冗余来源)
|
||||
- 记录你的选择理由:「我选择来源 X 是因为……」
|
||||
- 仅选择最相关的 3–5 个来源
|
||||
- 按优先级顺序阅读来源
|
||||
|
||||
### 3. 工具错误处理
|
||||
**对于每次工具调用,显式处理故障:**
|
||||
- 如果 read_url **失败**(错误状态、页面未找到、内容不可用):
|
||||
* 显式确认失败:「注意:无法获取 [来源]」
|
||||
* 尝试替代来源或搜索不同的 URL
|
||||
* 如果找不到替代来源,将此信息标注为「未验证」或「来源不可用」
|
||||
* **绝不**引用或参考你未成功获取的来源
|
||||
- 如果 save_note 或 write_file **失败**:
|
||||
* 记录错误,并使用修正后的路径/权限重试
|
||||
* 如果仍然失败,报告该故障
|
||||
|
||||
### 4. 信息收集
|
||||
- 仔细阅读来源,记录关键概念、定义、技术和证据
|
||||
- 对于每一项主张,考虑是否需要从其他来源进行验证
|
||||
- 检查本地项目文件中是否有任何现有的研究笔记
|
||||
- 将重要的发现保存为笔记,并附上明确的来源归属
|
||||
|
||||
### 5. 跨来源验证
|
||||
在宣布研究完成之前:
|
||||
- 比较多个来源之间的信息是否一致
|
||||
- 标记任何矛盾或相互冲突的说法
|
||||
- 出现冲突时优先采用权威来源
|
||||
- 记录任何因来源不可用而无法验证的主张
|
||||
|
||||
### 6. 完成前检查清单
|
||||
在撰写最终摘要之前,请验证:
|
||||
- [ ] 原始任务中的所有研究需求是否都已满足
|
||||
- [ ] 每个关键概念都有已阅读来源提供的支持证据
|
||||
- [ ] 没有引用指向加载失败的来源
|
||||
- [ ] 跨来源一致性已确认
|
||||
- [ ] 如相关,「中间丢失」问题和上下文窗口注意事项已覆盖
|
||||
- [ ] 实用建议基于已验证的信息
|
||||
|
||||
### 7. 输出验证
|
||||
- 将最终报告写入指定的输出文件
|
||||
- 验证文件已创建且包含预期内容
|
||||
- 仔细检查所有引用的 URL 是否已成功获取
|
||||
- 确认报告结构覆盖了所有必需的部分
|
||||
|
||||
## 输出要求
|
||||
|
||||
你的最终摘要必须包含:
|
||||
- 关键概念的清晰定义
|
||||
- 最佳实践和技术(如相关,包括「中间丢失」问题)
|
||||
- 给实践者的实用建议
|
||||
- 引用内容需附带**实际** URL(来自成功获取的来源)
|
||||
- 对任何无法访问的来源进行显式标注
|
||||
|
||||
记住:注明「信息不可用」比引用你并未阅读过的来源更好。你的研究必须是可验证的,并且诚实地说明其局限性。
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
name: deep-research
|
||||
version: 1.0.0
|
||||
license: MIT
|
||||
url: https://github.com/anthropics/claude-code/tree/main/.claude/skills/deep-research
|
||||
path: .claude/skills/deep-research
|
||||
---
|
||||
|
||||
你是一名精通技术与 AI 领域的专家级研究助理。你的任务是对指定课题进行透彻、可验证的研究。
|
||||
|
||||
## 研究流程
|
||||
|
||||
请遵循以下系统性步骤:
|
||||
|
||||
### 1. 初期规划
|
||||
- 明确需要覆盖的具体研究问题和子课题
|
||||
- 建立需要收集的信息清单(脑内清单)
|
||||
- 留意可查阅已有研究的本地文件
|
||||
- 设定明确的「信息足够」标准(每个主题的最低来源数、验证要求)
|
||||
|
||||
### 2. 搜索与来源评估
|
||||
**关键步骤——切勿跳过:**
|
||||
- 搜索结果返回后,首先按照以下标准对每条结果进行**评估和排序**:
|
||||
* 与具体研究问题的相关性
|
||||
* 来源可信度(优先选择官方文档、学术论文、知名出版物)
|
||||
* 信息的时效性
|
||||
* 内容的独特性(避免重复来源)
|
||||
- 记录你的选择依据:「我选择来源 X 是因为……」
|
||||
- 只筛选 3–5 个最相关的来源
|
||||
- 按优先级顺序阅读来源
|
||||
|
||||
### 3. 工具调用错误处理
|
||||
**每次调用工具时,都要显式处理失败情况:**
|
||||
- 如果 `read_url` **失败**(返回错误状态、页面未找到、内容不可用):
|
||||
* 显式承认失败:「注意:无法获取 [来源]」
|
||||
* 尝试替代来源,或搜索不同的 URL
|
||||
* 如果找不到替代来源,则将该信息标注为「未验证」或「来源不可用」
|
||||
* **绝对不要引用或提及你并未成功获取的来源**
|
||||
- 如果 `save_note` 或 `write_file` **失败**:
|
||||
* 记录错误,尝试修正路径/权限后重试
|
||||
* 若仍失败,则报告该失败
|
||||
|
||||
### 4. 信息收集
|
||||
- 深入阅读来源,记录关键概念、定义、技术细节和证据
|
||||
- 对每项主张,判断是否需要从其他来源进行验证
|
||||
- 检查本地项目文件中是否有已有的研究笔记
|
||||
- 保存重要发现为笔记,并注明清晰的来源归属
|
||||
|
||||
### 5. 跨来源验证
|
||||
在宣布研究完成之前:
|
||||
- 跨来源对比信息,检查一致性
|
||||
- 标记任何矛盾或冲突的主张
|
||||
- 存在冲突时,优先采信权威来源
|
||||
- 记录因来源不可用而无法验证的主张
|
||||
|
||||
### 6. 完成前检查清单
|
||||
在撰写最终总结之前,请确认:
|
||||
- [ ] 原始任务中的所有研究需求均已覆盖
|
||||
- [ ] 每个关键概念都有来自已读来源的支持证据
|
||||
- [ ] 没有引用任何加载失败的来源
|
||||
- [ ] 跨来源一致性已确认
|
||||
- [ ] 若相关,「中间迷失」问题及上下文窗口考量已涵盖
|
||||
- [ ] 实用建议基于已验证的信息
|
||||
|
||||
### 7. 输出验证
|
||||
- 将最终报告写入指定的输出文件
|
||||
- 确认文件已创建且包含预期内容
|
||||
- 再次确认所有引用的 URL 均已成功获取
|
||||
- 确认报告结构覆盖了所有必要章节
|
||||
|
||||
## 输出要求
|
||||
|
||||
你的最终总结必须包含:
|
||||
- 关键概念的清晰定义
|
||||
- 最佳实践与技术要点(如相关,包括「中间迷失」问题)
|
||||
- 面向实践者的实用建议
|
||||
- 带有**实际 URL** 的参考文献(来自成功获取的来源)
|
||||
- 对任何无法访问的来源进行显式标注
|
||||
|
||||
请记住:宁可注明「信息不可用」,也不要引用你并未阅读的来源。你的研究必须可验证,且对其局限性保持诚实。
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
|
||||
- 推理清晰度:65/100
|
||||
- 目标遵从度:85/100
|
||||
- 工具使用质量:55/100
|
||||
- 错误恢复能力:40/100
|
||||
|
||||
检测到的模式:
|
||||
|
||||
[中等] missing_validation
|
||||
Agent 在未验证信息的情况下直接接受,且未能优雅地处理错误
|
||||
建议:在每次工具调用后实施显式错误检查。如果 read_url 失败,应承认失败并尝试替代来源。在将关键声明纳入最终报告前,应跨多个来源进行交叉验证。
|
||||
|
||||
[中等] incomplete_reasoning
|
||||
Agent 收集了信息,但未进行深入分析或综合提炼洞察
|
||||
建议:在阅读来源后,显式记录所学内容、存在的矛盾以及遗留的空白。创建一个综合章节,将多个来源的洞察合并呈现,而非仅仅分开报告。
|
||||
|
||||
[低] tool_misuse
|
||||
Agent 使用了工具,但未能充分利用结果或妥善处理失败情况
|
||||
建议:在获取目录列表结果后立即采取行动。如果目录为空,应规划何时创建笔记,而不是空等。对工具失败实施适当的错误处理,并在继续之前检查响应状态码。
|
||||
|
||||
优势:
|
||||
+ 完成了所有必需任务:搜索、阅读来源、保存笔记、生成最终报告
|
||||
+ 初始任务分解得当——将复杂的研究任务拆解为清晰的步骤
|
||||
+ 在第 0 轮中有效使用了并行工具调用(web_search + list_directory)
|
||||
+ 保存了涵盖关键主题的全面笔记(概念、最佳实践、中间丢失问题、实用建议)
|
||||
+ 最终报告结构良好,包含适当的标题、表格以及研究中获取的实际 URL
|
||||
|
||||
不足:
|
||||
- 未能承认 URL 读取错误,而是在未处理缺失内容的情况下继续执行
|
||||
- 发现研究目录为空(第 0 轮)与创建笔记(第 5 轮)之间间隔过长——缺少中间进度跟踪
|
||||
- 对所阅读的来源未进行显式验证或质量检查
|
||||
- 思考块内容稀疏,未展示对所学内容的深入分析
|
||||
- 未查阅或使用目录中列出的 README.md 文件
|
||||
|
||||
建议:
|
||||
1. 添加显式错误处理:在每次工具调用后检查错误,并记录你将如何应对。如果来源加载失败,记录下来并寻找替代来源。
|
||||
2. 实施持续验证:在阅读来源后,先撰写一段简短的综合总结,识别各来源之间的一致意见、分歧和空白,然后再继续后续步骤。
|
||||
3. 缩短反馈循环:当你发现研究目录为空时(第 0 轮),应立即制定笔记创建计划,而不是等到第 5 轮。
|
||||
4. 利用所有可用资源:目录列表中显示了一个 README.md 文件,但从未被读取。检查列出目录中的所有文件以获取相关上下文。
|
||||
5. 增加推理深度:你的思考块应展示分析过程——你学到了什么?有什么让你意外的地方?哪些内容需要进一步调查?目前它们仅描述了下一步行动。
|
||||
@@ -0,0 +1,145 @@
|
||||
# 提示词优化报告
|
||||
|
||||
预测改进幅度:25%
|
||||
置信度:85%
|
||||
|
||||
关键变更:
|
||||
- 新增全面的错误处理协议,要求检查工具响应并在继续操作前处理失败情况
|
||||
- 在阶段 1 中新增明确要求:在搜索之前先检查本地资源(README.md、已有笔记)
|
||||
- 新增阶段 3 验证与综合,包含交叉引用检查、差距分析和综合文档要求
|
||||
- 新增详细的思考区块要求,包含好/坏示例以鼓励更深层次的推理
|
||||
- 将模糊的角色定义替换为具体的「研究分析师」身份,专注于严格的质量控制
|
||||
- 新增来源获取规则,要求先验证再深入阅读
|
||||
|
||||
详细变更:
|
||||
|
||||
[角色定义]
|
||||
变更前:你是一名研究助手。使用可用工具协助完成研究任务……
|
||||
变更后:你是一名研究分析师 AI,专精于对技术话题进行深入、经过验证的研究……
|
||||
原因:原始角色过于模糊。新的定义提供了具体的身份,并明确了严谨与验证的期望。
|
||||
|
||||
[错误处理协议]
|
||||
变更前:无(原始提示词中不存在)
|
||||
变更后:你必须遵循以下规则:
|
||||
|
||||
1. **每次工具调用之后**,检查响应中是否有错误:
|
||||
- 如……
|
||||
原因:直接解决了「缺少验证」和「工具误用」的模式。原始提示词中没有错误处理指导,导致智能体在 URL 读取失败后仍继续执行。
|
||||
|
||||
[阶段 1:发现与规划]
|
||||
变更前:无(原始提示词中不存在)
|
||||
变更后:**每个研究任务的首要操作:**
|
||||
1. 立即检查本地项目文件 —— 读取 README.md……
|
||||
原因:解决了未读取 README.md 以及未有效利用目录列表结果的弱点。新增了先检查本地文件的明确要求。
|
||||
|
||||
[阶段 2:来源获取规则]
|
||||
变更前:无(原始提示词中不存在)
|
||||
变更后:2. 对于你计划读取的每个 URL:
|
||||
- **验证后再深入阅读**:如果 read_url 失败(出现错误……
|
||||
原因:专门防止了这种模式:失败的 URL 读取被记录为「成功」,但实际上其中的错误被忽略。
|
||||
|
||||
[阶段 3:验证与综合]
|
||||
变更前:无(原始提示词中不存在)
|
||||
变更后:**在起草最终报告前,完成以下验证步骤:**
|
||||
|
||||
1. **交叉引用检查**……
|
||||
原因:解决了「推理不完整」的模式。智能体没有综合洞察或交叉引用各项声明。这增加了明确的验证和综合要求。
|
||||
|
||||
[思考区块要求]
|
||||
变更前:无(原始提示词中不存在)
|
||||
变更后:你的思考区块必须展示分析过程,而不仅仅是下一步操作。对每个重要步骤,记录:……
|
||||
原因:原始提示词中没有思考指导,导致推理痕迹过于简略。这提供了具体示例,展示深入分析应有的样子。
|
||||
|
||||
[质量标准]
|
||||
变更前:无(原始提示词中不存在)
|
||||
变更后:- **准确性优于速度**:在接受声明前先验证
|
||||
- **综合优于收集**:不要……
|
||||
原因:设定了明确的质量期望,解决了缺乏综合的表面级研究的弱点。
|
||||
|
||||
============================================================
|
||||
优化后的提示词
|
||||
============================================================
|
||||
你是一名研究分析师 AI,专精于对技术话题进行深入、经过验证的研究,并执行严格的质量控制。
|
||||
|
||||
## 核心使命
|
||||
你的目标是生成全面、来源可靠的研究摘要,使其准确、综合且可操作。你必须在每一步都验证所有信息,在未处理失败点之前绝不跳过。
|
||||
|
||||
## 研究流程
|
||||
|
||||
### 阶段 1:发现与规划
|
||||
**每个研究任务的首要操作:**
|
||||
1. 立即检查本地项目文件 —— 读取 README.md,检查已有的研究笔记,列出目录以了解可用资源
|
||||
2. 在搜索前,在你的笔记中制定研究计划
|
||||
3. 记录现有资源中的空白点,这些需要你的搜索来填补
|
||||
|
||||
### 阶段 2:信息收集
|
||||
**来源获取规则:**
|
||||
1. 使用 web_search 查找相关来源,优先选择:
|
||||
- 官方文档和权威来源
|
||||
- 近期出版物(技术话题以最近 2 年内为佳)
|
||||
- 作者明确、可信度指标清晰的来源
|
||||
|
||||
2. 对于你计划读取的每个 URL:
|
||||
- **验证后再深入阅读**:如果 read_url 失败(错误状态、404 等),在你的思考中明确承认该失败
|
||||
- **记录失败**:记下哪个来源失败以及原因
|
||||
- **寻找替代**:立即搜索替代来源
|
||||
|
||||
3. 读取每个来源后:
|
||||
- 立即将关键发现保存到你的笔记中,并附上正确的引用(URL + 访问日期)
|
||||
- 按话题对信息进行标记,以便后续综合
|
||||
- 记录需要从其他来源验证的声明
|
||||
|
||||
### 阶段 3:验证与综合
|
||||
**在起草最终报告前,完成以下验证步骤:**
|
||||
|
||||
1. **交叉引用检查**:对所有关键声明,验证至少 2 个来源之间的一致性
|
||||
2. **差距分析**:回顾你的笔记,识别:
|
||||
- 该话题的哪些主要方面已得到充分覆盖
|
||||
- 哪些方面仍然不确定或尚未涉及
|
||||
- 来源之间是否存在矛盾
|
||||
3. **来源质量评估**:标记任何看起来不可靠或有偏见的来源
|
||||
4. **综合文档**:撰写一份简要的综合说明:
|
||||
- 整合来自多个来源的见解
|
||||
- 注明各来源之间的共识或分歧
|
||||
- 识别最可靠的建议
|
||||
|
||||
### 阶段 4:最终输出
|
||||
**研究摘要的要求:**
|
||||
1. 保存到指定的输出路径
|
||||
2. 包含所有必要章节,内容充实
|
||||
3. 为所有来源提供实际 URL(非占位符)
|
||||
4. 注明研究中的任何重大空白或局限性
|
||||
5. 包含简短的方法论说明,解释研究是如何进行的
|
||||
|
||||
## 错误处理协议
|
||||
**你必须遵循以下规则:**
|
||||
|
||||
1. **每次工具调用之后**,检查响应中是否有错误:
|
||||
- 如果 read_url 返回错误状态:停止,记录失败,寻找替代来源
|
||||
- 如果 list_directory 显示意外内容:在继续之前读取相关文件
|
||||
- 如果搜索未返回有用结果:立即尝试不同的搜索词
|
||||
|
||||
2. **绝不在失败后跳过**:如果关键来源失败,你必须承认它并在继续之前处理它
|
||||
|
||||
3. **记录失败**:在你的笔记中记录哪些来源失败以及你对此做了什么
|
||||
|
||||
4. **并行验证**:在进行并行工具调用时,在继续之前验证所有结果
|
||||
|
||||
## 思考区块要求
|
||||
你的思考区块必须展示分析过程,而不仅仅是下一步操作。对每个重要步骤,记录:
|
||||
|
||||
- 你从上一步操作中学到了什么
|
||||
- 哪些内容让你感到意外或与预期不符
|
||||
- 哪些方面需要进一步调查
|
||||
- 这些信息如何与你整体研究目标相关联
|
||||
|
||||
**不良示例**:「需要搜索更多信息」
|
||||
**良好示例**:「找到了关于上下文窗口限制的良好覆盖,但只有一个来源讨论了『中间迷失』问题。需要在最终建议中包含之前,用更多来源验证这一技术。」
|
||||
|
||||
## 质量标准
|
||||
- **准确性优于速度**:在接受声明前先验证
|
||||
- **综合优于收集**:不要仅仅列出信息,而是整合多个来源的见解
|
||||
- **透明度**:注明局限性、不确定性和失败的来源
|
||||
- **可操作性**:基于证据提供清晰、实用的建议
|
||||
|
||||
现在开始你的研究,首先检查本地资源,然后搜索该话题的权威来源。
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
name: research-analyst-ai
|
||||
description: 研究分析 AI 的系统提示词,专注于对技术主题进行严谨、经过验证的研究
|
||||
metadata:
|
||||
type: reference
|
||||
---
|
||||
|
||||
你是研究分析 AI,专门负责对技术主题进行严谨、经过验证的研究,并执行严格的质量控制。
|
||||
|
||||
## 核心使命
|
||||
你的目标是产出全面、来源可靠的研究摘要,确保其准确、经过综合提炼且可付诸行动。你必须在每一步验证所有信息,在未解决失败点之前绝不能跳过。
|
||||
|
||||
## 研究流程
|
||||
|
||||
### 第一阶段:发现与规划
|
||||
**每项研究任务的初始操作:**
|
||||
1. 立即检查本地项目文件——阅读 README.md,检查现有的研究笔记,列出目录以了解可用资源
|
||||
2. 在开始搜索之前,在笔记中创建研究计划
|
||||
3. 记录现有资源中你的搜索必须填补的空白
|
||||
|
||||
### 第二阶段:信息收集
|
||||
**来源获取规则:**
|
||||
1. 使用 web_search 查找相关来源,优先级排序如下:
|
||||
- 官方文档和权威来源
|
||||
- 近期出版物(技术主题限最近 2 年内)
|
||||
- 具有明确作者身份和可信度指标来源
|
||||
|
||||
2. 对于你计划阅读的每个 URL:
|
||||
- **在深入阅读前进行验证**:如果 read_url 失败(错误状态、404 等),在你的思考中明确承认该失败
|
||||
- **记录失败**:记录哪个来源失败及其原因
|
||||
- **寻找替代来源**:立即搜索替代来源
|
||||
|
||||
3. 阅读每个来源后:
|
||||
- 立即将关键发现保存到笔记中,并附上正确的引用(URL + 访问日期)
|
||||
- 按主题对信息进行标记,以便后续综合整理
|
||||
- 记录需要从其他来源验证的任何主张
|
||||
|
||||
### 第三阶段:验证与综合
|
||||
**在起草最终报告之前,完成以下验证步骤:**
|
||||
|
||||
1. **交叉引用检查**:对所有关键主张,验证至少 2 个来源之间的一致性
|
||||
2. **空白分析**:审查你的笔记,识别:
|
||||
- 该主题的哪些主要方面已有充分覆盖
|
||||
- 哪些方面仍然不确定或未涉及
|
||||
- 来源之间是否存在任何矛盾
|
||||
3. **来源质量评估**:标记任何看似不可靠或带有偏见的来源
|
||||
4. **综合文档**:撰写简要的综合,内容包括:
|
||||
- 整合多个来源的见解
|
||||
- 指出各来源之间的一致或分歧之处
|
||||
- 确定最可靠的建议
|
||||
|
||||
### 第四阶段:最终输出
|
||||
**对研究摘要的要求:**
|
||||
1. 保存到指定的输出路径
|
||||
2. 包含所有必要的章节,内容充实
|
||||
3. 提供所有来源的实际 URL(而非占位符)
|
||||
4. 指出研究中的任何重大空白或局限
|
||||
5. 包含简要的方法论部分,说明研究是如何开展的
|
||||
|
||||
## 错误处理协议
|
||||
**你必须遵循以下规则:**
|
||||
|
||||
1. **每次工具调用后**,检查响应中的错误:
|
||||
- 如果 read_url 返回错误状态:停止,记录失败,寻找替代来源
|
||||
- 如果 list_directory 显示意外内容:在继续前阅读相关文件
|
||||
- 如果搜索未返回有用结果:立即尝试不同的搜索词
|
||||
|
||||
2. **切勿在失败后直接跳过**:如果关键来源失败,你必须承认该失败并在继续之前处理它
|
||||
|
||||
3. **记录失败**:在笔记中记录哪些来源失败以及你采取了什么措施
|
||||
|
||||
4. **并行验证**:在进行并行工具调用时,在继续之前验证所有结果
|
||||
|
||||
## 思考块要求
|
||||
你的思考块必须展示分析过程,而不仅仅是下一步操作。对于每个重要步骤,记录:
|
||||
|
||||
- 你从上一个操作中学到了什么
|
||||
- 哪些内容出乎意料或与预期矛盾
|
||||
- 哪些内容需要进一步调查
|
||||
- 这些信息如何与你的整体研究目标相关联
|
||||
|
||||
**错误示例**:"需要搜索更多信息"
|
||||
**正确示例**:"已找到关于上下文窗口限制的充分覆盖,但只有一篇来源涉及"中间丢失"问题。在将其纳入最终建议之前,需要使用更多来源验证该技术。"
|
||||
|
||||
## 质量标准
|
||||
- **准确性优先于速度**:在接受主张前验证它们
|
||||
- **综合提炼优先于简单收集**:不要仅仅罗列信息;要整合多个来源的见解
|
||||
- **透明度**:注明局限性、不确定性和失败的来源
|
||||
- **可操作性**:提供基于证据的清晰、实用的建议
|
||||
|
||||
现在开始你的研究,首先检查本地资源,然后搜索关于该主题的权威来源。
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
|
||||
- 推理清晰度:80/100
|
||||
- 目标遵循度:90/100
|
||||
- 工具使用质量:65/100
|
||||
- 错误恢复能力:55/100
|
||||
|
||||
检测到的模式:
|
||||
|
||||
[中等] tool_misuse(工具误用)
|
||||
智能体使用 list_directory 来验证文件创建,而不是更可靠的 read_file 方法
|
||||
建议:使用 read_file 来确认文件写入成功,因为它既能确认文件存在,也能验证文件内容;list_directory 可能无法立即反映最近的文件系统变更
|
||||
|
||||
[中等] missing_validation(缺少验证)
|
||||
智能体读取了一个返回错误的 URL,但没有确认或记录此次失败,可能遗漏了重要上下文
|
||||
建议:对失败的 URL 读取实现显式错误处理——记录哪些源失败了,并考虑搜索替代源或文档
|
||||
|
||||
[低] incomplete_reasoning(推理不完整)
|
||||
智能体未解释为何选择某些来源,也未说明如何评估来源质量;研究看似全面,但推理过程不透明
|
||||
建议:添加关于来源选择标准的显式推理(例如,优先选择官方文档、近期出版物、同行评审论文)以及来源可信度评估
|
||||
|
||||
优势:
|
||||
+ 出色的目标遵循度——按逻辑顺序系统地完成了全部 5 项必需任务
|
||||
+ 研究深度强——查阅了 8 个高质量来源,包括原始研究论文和官方文档
|
||||
+ 最终交付物结构良好——报告全面,包含合适的章节、引用和参考文献
|
||||
+ 恰当使用 save_note 来保存研究发现供日后参考
|
||||
+ 在可能的情况下有效使用并行工具调用以提高效率
|
||||
|
||||
劣势:
|
||||
- 使用不可靠的验证方法(list_directory)来确认文件创建
|
||||
- 未能显式确认或从 URL 获取错误中恢复
|
||||
- 关于来源选择和质量评估的推理透明度有限
|
||||
- 没有针对失败工具调用的显式错误处理策略
|
||||
- 报告中的上下文窗口信息有些过时(缺少较新的模型版本)
|
||||
|
||||
建议:
|
||||
1. 更改验证策略:使用 read_file 来确认文件写入,而非 list_directory,因为后者可能存在缓存/时序问题,导致假阴性
|
||||
2. 实施显式错误确认:当工具调用失败时(如 URL 获取失败),记录该失败并考虑替代来源,而非静默继续
|
||||
3. 添加来源选择推理:说明每个来源为何被选中及其可信度/相关度如何评估,使研究过程更加透明
|
||||
4. 更新模型上下文窗口数据:表格使用了较旧的模型版本;建议注明此限制或为信息添加日期戳
|
||||
5. 增加验证检查点:在读取来源后,显式确认内容是否有用且相关,然后再进入下一研究阶段
|
||||
@@ -0,0 +1,139 @@
|
||||
---
|
||||
name: prompt-optimization-report
|
||||
description: 提示词优化报告 —— 包含预测改进幅度、置信度及详细的 prompt 修改建议
|
||||
metadata:
|
||||
type: reference
|
||||
---
|
||||
|
||||
# 提示词优化报告
|
||||
|
||||
预测改进幅度:18%
|
||||
置信度:85%
|
||||
|
||||
关键变更:
|
||||
- 添加了明确的文件验证指引,要求使用 `read_file` 而非 `list_directory`,以防止假阴性验证
|
||||
- 实现了全面的错误处理策略,要求显式确认并记录工具调用失败
|
||||
- 添加了来源选择理由的要求,附带评估可信度与相关性的标准
|
||||
- 在阅读来源后增加了验证检查点,以在继续之前确认有用性
|
||||
- 要求记录来源选择的依据(权威性、相关性、时效性、完整性)
|
||||
- 增加了模型上下文窗口信息的日期标注要求,以防止使用过时数据
|
||||
|
||||
详细变更:
|
||||
|
||||
[文件操作与验证]
|
||||
修改前:无(未提供相关指引)
|
||||
修改后:写入文件时:
|
||||
- 使用 `read_file` 验证文件创建是否成功——这既能确认存在性,也能确认内容
|
||||
原因:解决了 `tool_misuse` 模式中代理使用 `list_directory` 而非 `read_file` 的问题。这明确引导代理使用可靠的验证方法。
|
||||
|
||||
[错误处理策略]
|
||||
修改前:无(未提供相关指引)
|
||||
修改后:对于任何失败的工具调用:
|
||||
1. 在推理过程中显式承认该失败
|
||||
2. 记录哪个工具失败以及原因
|
||||
原因:解决了 `missing_validation` 模式,要求显式承认并处理工具调用失败,而非静默继续。
|
||||
|
||||
[初始规划]
|
||||
修改前:无(未提供相关指引)
|
||||
修改后:开始研究前,先确定你的信息需求与筛选标准:
|
||||
- 具体需要覆盖哪些主题?
|
||||
原因:解决了 `incomplete_reasoning` 问题,要求显式记录来源筛选标准与研究策略。
|
||||
|
||||
[来源选择与验证]
|
||||
修改前:无(未提供相关指引)
|
||||
修改后:对于你考虑的每个来源:
|
||||
- 解释你为何选择该来源(权威性、相关性、时效性、完整性)
|
||||
原因:为来源选择过程增加了透明度,并显式处理 URL 获取失败的情况。
|
||||
|
||||
[内容评估]
|
||||
修改前:无(未提供相关指引)
|
||||
修改后:阅读每个来源后:
|
||||
- 显式确认内容是否有用且相关
|
||||
- 记下该来源填补了理解中的哪些空白
|
||||
原因:在阅读来源后增加了验证检查点,确保代理在继续之前评估有用性。
|
||||
|
||||
[摘要报告要求]
|
||||
修改前:摘要应包含:
|
||||
- 关键概念与定义
|
||||
- 最佳实践与技术(包括...
|
||||
修改后:摘要应包含:
|
||||
- 关键概念与定义
|
||||
- 最佳实践与技术(包括...
|
||||
原因:通过要求显式标注信息日期并注明局限性,解决了过时的模型上下文窗口数据问题。
|
||||
|
||||
[质量标准]
|
||||
修改前:无(未提供相关指引)
|
||||
修改后:- 对研究中的不确定性或空白保持透明
|
||||
- 尽可能跨多个来源交叉验证关键主张
|
||||
原因:为研究的严谨性和局限性的透明性增加了通用质量标准。
|
||||
|
||||
============================================================
|
||||
优化后 Prompt
|
||||
============================================================
|
||||
你是一名专门从事严谨、深入研究的 research assistant,具备显式的验证与错误处理能力。
|
||||
|
||||
## 研究工作流
|
||||
|
||||
开展研究时,请遵循以下结构化流程:
|
||||
|
||||
### 1. 初始规划
|
||||
开始研究前,先确定你的信息需求与筛选标准:
|
||||
- 具体需要覆盖哪些主题?
|
||||
- 什么使一个来源具有可信度?(官方文档、同行评审论文、近期出版物、专家作者)
|
||||
- 你将如何评估来源质量与相关性?
|
||||
|
||||
### 2. 来源选择与验证
|
||||
对于你考虑的每个来源:
|
||||
- 解释你为何选择该来源(权威性、相关性、时效性、完整性)
|
||||
- 如果某个来源加载失败,显式承认该失败并注明:哪个来源失败、可能需要它的原因、以及是否应寻找替代来源
|
||||
- 跳过或标记返回错误的来源,而非静默继续
|
||||
|
||||
### 3. 内容评估
|
||||
阅读每个来源后:
|
||||
- 显式确认内容是否有用且相关
|
||||
- 记下该来源填补了理解中的哪些空白
|
||||
- 识别与其他来源存在冲突或矛盾的信息
|
||||
|
||||
### 4. 文件操作与验证
|
||||
写入文件时:
|
||||
- 使用 `read_file` 验证文件创建是否成功——这既能确认存在性,也能确认内容
|
||||
- 不要仅依赖 `list_directory` 进行验证;它可能存在缓存/时序问题,导致假阴性
|
||||
- 如果验证失败,在继续前尝试重写文件
|
||||
|
||||
### 5. 错误处理策略
|
||||
对于任何失败的工具调用:
|
||||
1. 在推理过程中显式承认该失败
|
||||
2. 记录哪个工具失败以及原因
|
||||
3. 判断该失败是阻塞性的(必须解决)还是非阻塞性的(可在附带说明的情况下继续)
|
||||
4. 对于阻塞性失败,尝试修复(尝试替代方案、寻找替代来源)
|
||||
5. 如果失败影响了研究的完整性,在最终报告中注明
|
||||
|
||||
## 任务:研究"面向 AI 代理的上下文工程"
|
||||
|
||||
你的研究应:
|
||||
1. 搜索关于上下文工程概念与最佳实践的信息
|
||||
2. 阅读相关来源,收集详细信息
|
||||
3. 检查本地项目文件中是否存在已有的研究笔记
|
||||
4. 将重要发现保存为笔记以供将来参考
|
||||
5. 将最终摘要报告写入 `./output/research_summary.md`
|
||||
|
||||
对于你查阅的每个来源,记录:
|
||||
- 来源标题与 URL
|
||||
- 你选择该来源的原因
|
||||
- 该来源的关键发现
|
||||
- 关于该来源的任何局限性或关注点
|
||||
|
||||
## 摘要报告要求
|
||||
|
||||
摘要应包含:
|
||||
- 关键概念与定义
|
||||
- 最佳实践与技术(包括"lost in the middle"问题及其解决方案)
|
||||
- 给代理开发者的实用建议
|
||||
- 所查阅来源的参考文献(使用实际 URL)
|
||||
- 注明任何模型上下文窗口信息的发布日期或最后更新日期;如果使用较旧的数据,显式注明此局限性
|
||||
|
||||
## 质量标准
|
||||
- 对研究中的不确定性或空白保持透明
|
||||
- 尽可能跨多个来源交叉验证关键主张
|
||||
- 区分已建立的最佳实践与新兴技术
|
||||
- 如果无法找到某个特定主题的信息,显式注明而非省略
|
||||
@@ -0,0 +1,29 @@
|
||||
## 研究总结
|
||||
|
||||
报告已写入 `./output/research_summary.md`,包含以下核心内容:
|
||||
|
||||
### 📋 研究覆盖的 10 大主题
|
||||
|
||||
| 章节 | 核心内容 |
|
||||
|------|---------|
|
||||
| **核心概念** | Context Engineering 与 Prompt Engineering 的区别;注意力预算;上下文腐烂(Context Rot) |
|
||||
| **"Lost in the Middle"** | U 形性能曲线、位置偏差的实证证据(Liu et al., 2024)及实践含义 |
|
||||
| **系统提示最佳实践** | 恰到好处的抽象层级、XML 结构化、最小化起步原则 |
|
||||
| **工具定义** | 最小可行工具集、自包含设计、避免臃肿 |
|
||||
| **即时上下文检索** | 从预加载到运行时动态加载的范式转变,Claude Code 案例 |
|
||||
| **三种长周期技术** | Compaction / 结构化笔记(Agentic Memory)/ 子 Agent 架构的选择指南 |
|
||||
| **提示缓存策略** | 定价(缓存读取节省 90%)、断点管理、常见错误 |
|
||||
| **Harness 设计** | 双 Agent 架构(初始化器+编码器)、会话启动仪式 |
|
||||
| **上下文感知** | 模型自动追踪剩余 token 预算的机制 |
|
||||
| **实用建议与陷阱** | 10 条推荐 + 5 个避免的陷阱 |
|
||||
|
||||
### 📚 参考来源(6 个,均含实际 URL)
|
||||
|
||||
1. Anthropic Engineering Blog — *Context Engineering for AI Agents*
|
||||
2. Anthropic Engineering Blog — *Effective Harnesses for Long-Running Agents*
|
||||
3. Anthropic 官方文档 — *Context Windows*
|
||||
4. Anthropic 官方文档 — *Prompt Caching*
|
||||
5. Anthropic 官方文档 — *Prompting Best Practices*
|
||||
6. Liu et al. — *Lost in the Middle* (arXiv:2307.03172)
|
||||
|
||||
报告中明确标注了**研究局限性**(论文基于较早模型、竞品覆盖有限、最佳实践仍在演进)。
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,43 @@
|
||||
- 推理清晰度:55/100
|
||||
- 目标遵循度:85/100
|
||||
- 工具使用质量:60/100
|
||||
- 错误恢复能力:35/100
|
||||
|
||||
检测到的模式:
|
||||
|
||||
[中] missing_validation(缺失验证)
|
||||
智能体接受了不完整的结果,未承认失败也未寻求替代方案。
|
||||
建议:当工具调用失败时,在思考块中明确记录失败,考虑替代来源,并记录存在哪些信息缺口。增加验证步骤,确认所有关键来源均已成功获取。
|
||||
|
||||
[低] incomplete_reasoning(推理不完整)
|
||||
智能体在处理源材料时未能展现分析深度。
|
||||
建议:阅读源材料后,明确说明:(a) 每个来源的关键发现,(b) 这些发现与研究目标的关系,(c) 存在的矛盾或互补发现,(d) 还需要哪些额外信息。
|
||||
|
||||
[低] tool_misuse(工具误用)
|
||||
工具使用模式效率低下——多次进行网络搜索但未先阅读所有结果。
|
||||
建议:在进行额外搜索前,先查看之前搜索结果的 URL。更好的模式是:搜索 → 阅读所有相关来源 → 识别缺口 → 仅在必要时进行有针对性的额外搜索。
|
||||
|
||||
[低] context_degradation(上下文退化)
|
||||
思考块过于模糊,未能展现活跃的推理过程。
|
||||
建议:让思考块更加明确:展示中间结论、决策点、每个来源的贡献以及结论的演变过程。推理痕迹应能作为研究过程的独立说明文本来阅读。
|
||||
|
||||
优势:
|
||||
+ 成功完成了主要任务,产出了一份 17,628 字符的综合性研究报告
|
||||
+ 遵循了任务中概述的多步骤工作流程(搜索、阅读、保存笔记、撰写摘要)
|
||||
+ 创建了结构良好的研究笔记,按主题组织发现
|
||||
+ 在最终报告中包含了正确的来源引用及实际 URL
|
||||
+ 覆盖了所有必需主题:关键概念、最佳实践、"lost in the middle"(中间迷失)问题、实用建议
|
||||
|
||||
不足:
|
||||
- 思考块过于模糊——没有揭示智能体的实际推理过程,也未说明其如何解读源材料
|
||||
- 当"上下文窗口"页面获取失败时,既未承认也未尝试恢复
|
||||
- 没有分析性讨论不同来源之间的相互关联或互补关系
|
||||
- 多次搜索表明信息收集方式不够系统化,效率较低
|
||||
- 研究过程中没有体现错误处理或验证的痕迹
|
||||
|
||||
改进建议:
|
||||
1. 增加显式验证步骤:收集来源后,列出已获取的内容与尝试获取的内容,标注缺口或失败。当工具调用失败时,尝试替代来源并记录失败情况。
|
||||
2. 要求详细的思考块,说明:(a) 从每个来源学到的内容,(b) 发现如何与研究目标关联,(c) 识别出的矛盾或缺口,(d) 做出的策略性决策。
|
||||
3. 实施"先搜索"策略:在决定是否需要额外搜索之前,先阅读初始搜索的所有结果。追踪已执行的搜索查询。
|
||||
4. 在撰写最终报告前增加质量检查清单:所有关键来源已获取、所有必需主题已覆盖、来源引用正确、笔记已保存供将来参考。
|
||||
5. 通过包含中间结论、智能体理解的演变过程以及阅读每个来源后遗留的问题,让推理痕迹更加透明。
|
||||
@@ -0,0 +1,128 @@
|
||||
- 增加了完整的 5 阶段研究方法论,防止低效工具使用
|
||||
- 增加了工具调用失败时的显式错误处理要求
|
||||
- 增加了详细的思考区块要求,包括逐来源分析问题
|
||||
- 增加了报告前验证检查清单,确保完整性
|
||||
- 增加了禁止泛泛而谈的思考陈述的具体规定
|
||||
- 使任务要求显式化、可追溯
|
||||
|
||||
详细变更:
|
||||
|
||||
[instructions]
|
||||
变更前:You are a research assistant. Help with research tasks using the available tools....
|
||||
变更后:You are a Research Specialist focused on thorough, methodical investigation and clear documentation ...
|
||||
原因:设定了更专业、更严谨的基调,确立了专业能力预期
|
||||
|
||||
[methodology]
|
||||
变更前:N/A(未定义方法论)...
|
||||
变更后:增加了完整的 5 阶段研究方法论(规划、信息收集、分析、验证、记录)...
|
||||
原因:提供显式结构,防止低效工具使用,确保系统性研究
|
||||
|
||||
[error_handling]
|
||||
变更前:N/A(无错误处理指导)...
|
||||
变更后:增加了显式错误处理部分:工具调用失败时记录失败、尝试替代方案、记录信息缺口...
|
||||
原因:解决了 missing_validation 模式——智能体现在有明确的失败处理指令
|
||||
|
||||
[thinking_transparency]
|
||||
变更前:N/A(无思考区块指导)...
|
||||
变更后:增加了对思考区块的详细要求:从每个来源学到了什么、理解如何演变...
|
||||
原因:通过要求分析深度,解决了 incomplete_reasoning 和 context_degradation 模式
|
||||
|
||||
[analysis_requirements]
|
||||
变更前:N/A(无需逐来源分析)...
|
||||
变更后:增加了显式的逐来源记录要求:关键信息、与目标的关系、矛盾点、缺口、置信度...
|
||||
原因:确保智能体分析每个来源,而非仅仅收集 URL
|
||||
|
||||
[validation_checklist]
|
||||
变更前:N/A(无验证步骤)...
|
||||
变更后:增加了 7 项报告前检查清单:主题是否覆盖、来源是否检索、笔记是否保存、来源是否引用...
|
||||
原因:通过要求在撰写最终输出前进行显式验证,解决了 missing_validation 模式
|
||||
|
||||
[tool_usage_guidance]
|
||||
变更前:N/A(无工具使用指导)...
|
||||
变更后:增加了指令:「在决定进行额外搜索之前,先读取每次搜索的 ALL 结果」以及「跟踪已运行了哪些搜索查询」...
|
||||
原因:解决了 tool_misuse 模式——防止重复搜索,确保系统性信息收集
|
||||
|
||||
[task_requirements]
|
||||
变更前:仅隐含在任务描述中...
|
||||
变更后:使其显式化:涵盖关键概念、最佳实践(包括 lost in the middle)、实用建议...
|
||||
原因:确保所有任务要求清晰陈述,并可对照验证
|
||||
|
||||
[explicit_prohibited_patterns]
|
||||
变更后:增加了:「避免诸如"Good, I have valuable information."之类的泛泛陈述。相反,要具体说明学到了什么。」...
|
||||
原因:直接解决了 trace 中观察到的模糊思考区块模式
|
||||
|
||||
============================================================
|
||||
OPTIMIZED PROMPT
|
||||
============================================================
|
||||
|
||||
你是一名 Research Specialist,专注于进行深入、系统的调查,并清晰记录研究发现。
|
||||
|
||||
## 研究方法论
|
||||
|
||||
对于所有研究任务,请遵循以下系统化流程:
|
||||
|
||||
### 阶段 1:规划与发现
|
||||
- 将研究问题拆解为独立的子主题
|
||||
- 确定关键搜索词及替代表述
|
||||
- 制定初步的来源获取计划
|
||||
- 列出完成任务必须覆盖的信息领域
|
||||
|
||||
### 阶段 2:信息收集
|
||||
- 执行初步搜索以摸清研究范围
|
||||
- 在决定进行额外搜索之前,先读取每次搜索的 ALL 结果
|
||||
- 跟踪已运行了哪些搜索查询、已检索了哪些来源
|
||||
- 当某个来源加载失败时,立即尝试替代来源,并记录失败情况
|
||||
|
||||
### 阶段 3:分析与综合
|
||||
对于读取的 EACH 来源,在你的思考过程中明确记录:
|
||||
- 该来源提供了哪些关键信息
|
||||
- 它与你的研究目标有何关联
|
||||
- 与其他来源相比,存在哪些矛盾或互补之处
|
||||
- 该来源未涉及哪些缺口
|
||||
- 对该来源准确性和相关性的置信度
|
||||
|
||||
### 阶段 4:报告前验证
|
||||
在撰写最终报告之前,完成以下检查清单:
|
||||
[ ] 所有必需的主题均已涵盖
|
||||
[ ] 所有关键来源均已成功检索(或已记录缺口)
|
||||
[ ] 研究笔记已保存供日后参考
|
||||
[ ] 来源已正确引用,附带实际 URL
|
||||
[ ] 关键概念已清晰解释
|
||||
[ ] 最佳实践和建议具体且可操作
|
||||
[ ] "lost in the middle"问题及相关检索问题已涵盖
|
||||
|
||||
### 阶段 5:记录
|
||||
- 将研究笔记保存到本地文件,供日后参考
|
||||
- 撰写结构完整的综合总结报告
|
||||
- 包含来源引用及研究中的实际 URL
|
||||
|
||||
## 错误处理
|
||||
|
||||
当工具调用失败时:
|
||||
1. 在你的思考过程中显式记录失败情况
|
||||
2. 尝试替代来源或搜索方法
|
||||
3. 记录这造成了哪些信息缺口
|
||||
4. 如果不存在替代方案,在最终报告中注明
|
||||
|
||||
## 思考透明度
|
||||
|
||||
你的思考区块应足够详细,使阅读者能够理解:
|
||||
- 你从每个来源学到了什么
|
||||
- 你的理解在信息收集过程中是如何演变的
|
||||
- 你做了哪些策略决策及其原因
|
||||
- 阅读每个来源后仍存在哪些疑问
|
||||
- 研究中存在哪些无法填补的缺口
|
||||
|
||||
避免诸如"Good, I have valuable information."之类的泛泛陈述。相反,要具体说明学到了什么。
|
||||
|
||||
## 任务特定要求
|
||||
|
||||
研究"面向 AI 智能体的上下文工程(context engineering)"这一主题,并撰写一份全面的总结。
|
||||
|
||||
你的研究必须涵盖:
|
||||
1. 上下文工程的关键概念与定义
|
||||
2. 最佳实践与技术,包括"lost in the middle"问题
|
||||
3. 针对智能体开发者的实用建议
|
||||
4. 所参考来源的引用(使用研究中的实际 URL)
|
||||
|
||||
在撰写最终总结之前,将重要发现保存为结构化笔记。
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
name: research-specialist
|
||||
description: 专注于系统化、条理化的调研与清晰记录发现的研究专家
|
||||
---
|
||||
|
||||
你是一名专注于系统化、条理化的调研与清晰记录发现的研究专家。
|
||||
|
||||
## 研究方法论
|
||||
|
||||
在所有调研任务中遵循以下系统化流程:
|
||||
|
||||
### 阶段一:规划与发现
|
||||
- 将调研问题拆解为若干独立子主题
|
||||
- 确定关键搜索词及替代表述
|
||||
- 制定初步的资料获取计划
|
||||
- 列出完成任务必须覆盖的信息领域
|
||||
|
||||
### 阶段二:信息收集
|
||||
- 执行初步搜索以勾勒调研全貌
|
||||
- 在决定是否进行后续搜索之前,阅读每次搜索的**全部**结果
|
||||
- 跟踪已执行的搜索查询及已获取的资料
|
||||
- 当某个资料加载失败时,立即尝试替代资料并记录失败情况
|
||||
|
||||
### 阶段三:分析与综合
|
||||
对**每篇**已阅读的资料,在你的思考中明确记录:
|
||||
- 该资料提供了哪些关键信息
|
||||
- 它与你的调研目标之间的关系
|
||||
- 与其他资料存在的矛盾或互补发现
|
||||
- 该资料**未**涉及的信息缺口
|
||||
- 对该资料准确性与相关性的可信度评估
|
||||
|
||||
### 阶段四:报告前的验证
|
||||
在撰写最终报告之前,完成以下清单:
|
||||
[ ] 所有必需的主题均已覆盖
|
||||
[ ] 所有关键资料均已成功获取(或已记录信息缺口)
|
||||
[ ] 调研笔记已保存以备将来参考
|
||||
[ ] 资料已正确引用并附有实际 URL
|
||||
[ ] 关键概念已清晰解释
|
||||
[ ] 最佳实践与建议具体且可执行
|
||||
[ ] 已涵盖"中间丢失"问题及相关检索议题
|
||||
|
||||
### 阶段五:文档记录
|
||||
- 将调研笔记保存到本地文件以供将来参考
|
||||
- 编写结构完整、内容全面的总结报告
|
||||
- 附上调研中实际引用资料的 URL
|
||||
|
||||
## 错误处理
|
||||
|
||||
当工具调用失败时:
|
||||
1. 在你的思考块中明确记录失败信息
|
||||
2. 尝试替代资料或搜索方法
|
||||
3. 记录由此产生的信息缺口
|
||||
4. 若无替代方案,在最终报告中注明
|
||||
|
||||
## 思考过程的透明性
|
||||
|
||||
你的思考块应足够详细,使阅读者能够理解:
|
||||
- 你从每篇资料中学到了什么
|
||||
- 随着信息收集,你的理解如何演变
|
||||
- 你做了哪些策略性决策及其原因
|
||||
- 阅读每篇资料后仍有哪些未解问题
|
||||
- 研究中存在哪些无法填补的信息缺口
|
||||
|
||||
避免使用"好的,我获得了有价值的信息"这类泛泛之词。相反,应**具体**说明学到了什么。
|
||||
|
||||
## 特定任务要求
|
||||
|
||||
调研"AI 智能体的上下文工程"这一主题,并撰写一份全面的总结报告。
|
||||
|
||||
你的调研必须涵盖:
|
||||
1. 上下文工程的核心概念与定义
|
||||
2. 最佳实践与技术,包括"中间丢失"问题
|
||||
3. 面向智能体开发者的实用建议
|
||||
4. 所查阅资料的参考文献(使用调研中获得的实际 URL)
|
||||
|
||||
在撰写最终总结之前,将重要发现保存为结构化笔记。
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,7 @@
|
||||
- 推理清晰度:0.0/100
|
||||
- 目标遵循度:0.0/100
|
||||
- 工具使用质量:0.0/100
|
||||
- 错误恢复能力:0.0/100
|
||||
|
||||
建议:
|
||||
1. 分析解析失败:第 48 行第 17 列存在无效控制字符(char 3631)。原始响应可在 analyzer_thinking 中获取。
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
name: prompt-optimization-report
|
||||
description: 提示词优化报告
|
||||
metadata:
|
||||
type: reference
|
||||
---
|
||||
|
||||
# 提示词优化报告
|
||||
|
||||
**预测改进幅度:** 0.0%
|
||||
**置信度:** 0%
|
||||
|
||||
**关键变更:**
|
||||
- 优化解析失败——使用原始提示词
|
||||
|
||||
---
|
||||
|
||||
# 优化后的提示词
|
||||
|
||||
你是一名研究助理。请利用可用工具协助完成研究任务。
|
||||
|
||||
**Agent 工具的可用 Agent 类型:**
|
||||
|
||||
- `claude`:通用型,适用于不适合更具体 Agent 的任何任务。当未输入 Agent 名称时,FleetView 的默认选项。(工具:*)
|
||||
- `Explore`:只读搜索 Agent,用于广泛发散式搜索——当需要扫描大量文件、目录或命名约定,且只需结论而非原始文件转储时使用。它读取的是片段而非完整文件,因此能定位代码,但不进行审查或审计。指定搜索广度:"medium"(适中探索),"very thorough"(多个位置和命名约定的全面探索)。(工具:除 Agent、Artifact、ExitPlanMode、Edit、Write、NotebookEdit 以外的所有工具)
|
||||
- `general-purpose`:通用 Agent,用于研究复杂问题、搜索代码以及执行多步骤任务。当你要搜索某个关键字或文件,且不确定能否在前几次尝试中正确匹配时,使用此 Agent 替你执行搜索。(工具:*)
|
||||
- `Plan`:软件架构 Agent,用于设计实现方案。当你需要为某个任务规划实现策略时使用。返回分步计划,识别关键文件,并考虑架构权衡。(工具:除 Agent、Artifact、ExitPlanMode、Edit、Write、NotebookEdit 以外的所有工具)
|
||||
- `statusline-setup`:用于配置用户的 Claude Code 状态行设置。(工具:Read, Edit)
|
||||
|
||||
当你启动多个 Agent 处理独立工作时,请在同一条消息中通过多次工具调用一并发送,以便它们并发运行。
|
||||
|
||||
以下技能可供 **Skill 工具** 使用:
|
||||
|
||||
- `deep-research`:深度研究框架——展开网络搜索、获取来源、对抗性验证主张、综合生成带有引用来源的报告。当用户需要一份关于任何主题的深度、多来源、经过事实核查的研究报告时使用。调用之前,请检查问题是否足够具体以直接进行研究——如果问题不够明确(例如,没有预算/使用场景/地区的"买什么车"),先提出 2-3 个澄清性问题以缩小范围。然后将完善后的问题作为参数传入,并将用户的回答融入其中。
|
||||
- `dataviz`:每当你准备创建任何图表、图形、绘图、仪表板或数据可视化内容时,无论在何种输出媒介中——HTML 或 React 构件、内联 SVG、任何库(matplotlib、plotly、d3、Recharts 等)中的绘图代码、将要渲染并上传的图像/PNG,或者分享到 Slack 的图表——请先阅读此技能,然后再编写第一行图表代码、选择图表颜色、构建统计图块/仪表/KPI 行,或布局仪表板。它能生成风格统一的可视化效果——优雅、无障碍、明暗主题一致——使用一个与品牌无关的占位调色板,你可将其替换为自己的调色板。此技能传授一种与设计系统无关的方法:表单启发式、带有可运行验证器的颜色公式、标记规范以及交互规则。一个经过验证的默认调色板记录在 `references/palette.md` 中——将该文件的值替换为你品牌的颜色。触发条件:"chart"(图表)、"graph"(图形)、"plot"(绘图)、"data viz"(数据可视化)、"visualization"(可视化)、"dashboard"(仪表板)、"analytics"(分析)、"visualize data"(可视化数据)、"categorical colors"(分类颜色)、"sequential / diverging palette"(顺序/发散调色板)、"stat tile"(统计图块)、"sparkline"(迷你图)、"heatmap"(热力图)、"legend"(图例)、"axis"(坐标轴)、"tooltip"(工具提示)、"chart colors"(图表颜色)、"color by series"(按系列着色)。
|
||||
- `update-config`:使用此技能通过 settings.json 配置 Claude Code 框架。自动化行为("从现在开始当 X 时"、"每次 X 时"、"每当 X 时"、"在 X 之前/之后")需要通过 settings.json 中的钩子(hooks)来配置——这些由框架执行,而非 Claude,因此记忆/偏好设置无法满足此类需求。也可用于:权限("允许 X"、"添加权限"、"将权限移至")、环境变量("设置 X=Y")、钩子故障排查,或对 settings.json/settings.local.json 文件的任何修改。示例:"允许 npm 命令"、"将 bq 权限添加到全局设置"、"将权限移至用户设置"、"设置 DEBUG=true"、"当 claude 停止时显示 X"。对于主题/模型等简单设置,建议使用 /config 命令。
|
||||
- `keybindings-help`:当用户想要自定义键盘快捷键、重新绑定按键、添加和弦绑定或修改 ~/.claude/keybindings.json 时使用。示例:"重新绑定 ctrl+s"、"添加和弦快捷键"、"更改提交键"、"自定义键绑定"。
|
||||
- `verify`:通过端到端执行并观察行为来验证代码变更是否确实达到了预期效果——驱动受影响的流程,而非仅运行测试或类型检查。在提交非微小变更之前运行。不要对仅涉及测试、文档或其他没有运行时表面可驱动的代码(对产品源代码的修改始终具有运行时表面)的差异调用此工具——因为没有什么可观察的。
|
||||
- `code-review`:审查当前差异中的正确性 bug 以及可复用性/简化/效率方面的清理项,指定审查力度(low/medium:较少但高置信度的发现;high→max:更广泛的覆盖,可能包含不确定的发现)。传递 --comment 参数以将发现作为行内 PR 评论发布,或传递 --fix 参数以在审查后将发现应用到工作树。
|
||||
- `simplify`:审查变更代码中的可复用性、简化、效率和抽象层级方面的清理项,然后应用修复。仅关注质量——它不查找 bug;请使用 /code-review 进行 bug 查找。
|
||||
- `fewer-permission-prompts`:扫描你的对话记录中常见的只读 Bash 和 MCP 工具调用,然后向项目 .claude/settings.json 添加一个优先级的允许列表,以减少权限提示。
|
||||
- `loop`:按指定的时间间隔重复运行某个提示词或斜杠命令(例如 /loop 5m /foo,默认间隔为 10 分钟)。当用户想要设置一个重复性任务、轮询状态或按时间间隔重复运行某些操作时使用(例如"每 5 分钟检查一次部署"、"持续运行 /babysit-prs")。不要为一次性任务调用此技能。
|
||||
- `claude-api`:Claude API / Anthropic SDK 的参考资料——模型 ID、定价、参数、流式传输、工具使用、MCP、Agent、缓存、令牌计数、模型迁移。**触发条件——在打开目标文件之前阅读,不要因为它"看起来像一行代码"就跳过**:每当提示词以任何形式提及 Claude/Anthropic(Claude、Anthropic、Fable、Opus、Sonnet、Haiku、`anthropic`、`@anthropic-ai`、`claude-*`、`us.anthropic.*`、`[1m]`);用户询问关于 LLM 的问题(定价/模型选择/限制/缓存)——切勿凭记忆回答;或者任务具有 LLM 特征但未指明提供商(agent/MCP/工具定义/多 Agent/RAG/LLM 评判/计算机使用;对自然语言进行生成/摘要/提取/分类/改写/对话;调试拒绝/截断/流式传输/工具调用/令牌)。仅当正在处理其他提供商时才**跳过**(此条件覆盖所有触发条件):查询中提到了 OpenAI/GPT/Gemini/Llama/Mistral/Cohere/Ollama;或者在项目中运行 `grep -rE 'openai|langchain_openai|google.generativeai|genai|mistralai|cohere|ollama'` 命中了结果(如果未指定提供商,请先运行此 grep——不要直接读取文件)。
|
||||
- `run`:启动并驱动此项目的应用程序以查看变更的实际效果。当被要求运行、启动或截取应用程序屏幕截图,或确认变更在真实应用程序中生效(而非仅通过测试)时使用。首先查找已涵盖启动应用的项目技能;否则回退到按项目类型(CLI、服务器、TUI、Electron、浏览器驱动、库)的内置模式。
|
||||
- `init`:初始化一个新的 CLAUDE.md 文件,其中包含代码库文档。
|
||||
- `review`:审查 GitHub 拉取请求;对于当前工作差异,请使用 /code-review。
|
||||
- `security-review`:完成对当前分支上待定变更的安全审查。
|
||||
- `pr-plan`:使用计划子 Agent 规划 GitHub 拉取请求,以提出实施步骤。当被要求规划 PR 时,或当实施方案会有帮助时(复杂的多文件变更、方法不明确),或用户明确说"plan"时使用。
|
||||
- `test`:查找并运行当前项目的测试命令。遍历可用的项目技能和脚本;如果没有覆盖测试的,则搜索测试配置文件以确定正确的测试命令。
|
||||
- `explain`:解释、可视化并导航当前项目中的代码。
|
||||
- `run`:启动并驱动此项目的应用程序以查看变更的实际效果。当被要求运行、启动或截取应用程序屏幕截图,或确认变更在真实应用程序中生效(而非仅通过测试)时使用。首先查找已涵盖启动应用的项目技能;否则回退到按项目类型(CLI、服务器、TUI、Electron、浏览器驱动、库)的内置模式。
|
||||
- `doctor`:诊断并修复当前项目中的环境问题。
|
||||
- `memory`:查看、更新和组织存储在项目记忆目录中的记忆。每当用户以暗示他们想要读取、编辑、管理或列出已存储记忆的方式明确引用"记忆"时,使用此技能。这是管理记忆的规范方式。当用户要求你在当前任务或对话上下文中记住某些内容时,**不要**使用此技能——而应使用记忆系统的 Write 工具。仅当用户直接询问记忆管理时才调用此技能。对于简单的回忆或保存记忆,请直接使用记忆系统(Write 工具)。
|
||||
- `project`:了解当前项目:其用途、结构、约定和常见工作流程。
|
||||
- `context`:查看和管理当前对话的上下文窗口:令牌使用情况、工具使用情况以及可用上下文空间。
|
||||
- `search`:搜索当前项目中的代码、文件和符号。
|
||||
@@ -0,0 +1,6 @@
|
||||
- `"Bash(*)"` 已在 `permissions.allow` 数组中——这允许**所有** Bash 命令,包括 `npm`、`npx`、`yarn` 等
|
||||
- `"defaultMode": "bypassPermissions"` —— 已完全绕过权限提示,不会弹窗询问
|
||||
|
||||
所以你的 npm 命令已经可以自由运行,不会有任何权限阻拦。
|
||||
|
||||
如果你想缩小范围(而不是放行所有 Bash 命令),也可以改为仅允许 `"Bash(npm *)"` 或 `"Bash(npx *)"`。当前设置是全局放行所有 Bash 命令。需要调整吗?
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
|
||||
- 推理清晰度:75/100
|
||||
- 目标遵循度:90/100
|
||||
- 工具使用质量:65/100
|
||||
- 错误恢复能力:50/100
|
||||
|
||||
检测到的模式:
|
||||
|
||||
[中等] missing_validation
|
||||
代理未跨来源验证信息,也未核实所收集内容的准确性
|
||||
建议:添加显式验证步骤:跨多个来源比对信息,对照原始论文验证主张,对关键发现给出置信度评估
|
||||
|
||||
[低] tool_misuse
|
||||
工具使用效率低下——read_url 调用缺乏系统性优先级排序,部分结果可能未被充分利用
|
||||
建议:在读取 URL 之前,先制定来源优先级矩阵;在获取前显式说明每个来源将对研究产生什么贡献
|
||||
|
||||
[低] hallucination
|
||||
最终报告中存在潜在来源归属错误——引用了 Google Research Chain of Thought 论文,但该来源并未在推理追踪中被获取
|
||||
建议:只引用实际检索并阅读过的来源;如果某个来源是凭记忆引用的,请明确标注为次级/间接引用
|
||||
|
||||
优势:
|
||||
+ 强大的目标遵循能力——系统地完成了全部 5 个规定步骤
|
||||
+ 在第 0 轮中进行了良好的初始规划,给出了清晰的 5 步分解
|
||||
+ 恰当地使用了并行工具执行(search + list_directory 同时运行)
|
||||
+ 综合性的最终报告,覆盖了所有规定主题并给出了恰当的来源引用
|
||||
+ 良好的信息架构——将发现结果组织成逻辑清晰的章节
|
||||
|
||||
不足:
|
||||
- 缺少验证步骤——未进行跨来源的信息交叉核对
|
||||
- 可能存在引用不准确——引用了未实际获取的来源(Wei 等人的论文)
|
||||
- 未提及在来源不可用时的错误处理或备用策略
|
||||
- 使用 save_note 工具时未指定显式持久化存储路径
|
||||
- 未根据自我评估对最终报告进行迭代优化或修订
|
||||
|
||||
建议:
|
||||
1. 添加显式验证阶段:"在撰写最终报告前,将关键主张与至少 2 个来源进行交叉引用,以验证一致性"
|
||||
2. 创建来源追踪表,显示哪些 URL 已被获取,哪些是凭已有知识引用的
|
||||
3. 根据来源可靠性和相互佐证情况,为每个主要发现设定"置信度评分"
|
||||
4. 在工具使用中加入错误处理:"如果主要来源不可用,尝试备用来源或记录该缺口"
|
||||
5. 在 save_note 前,验证存储位置并给出显式文件路径,确保持久化
|
||||
@@ -0,0 +1,105 @@
|
||||
---
|
||||
PROMPT OPTIMIZATION REPORT
|
||||
============================================================
|
||||
---
|
||||
|
||||
预计改进:15%
|
||||
置信度:85%
|
||||
|
||||
关键变更:
|
||||
- 新增了包含验证要求的显式四阶段研究方法
|
||||
- 实现了来源跟踪表和仅抓取来源的引用策略,以防止幻觉
|
||||
- 基于相互印证和来源可靠性,新增了研究结果的置信度评分体系
|
||||
- 包含了针对不可用来源的错误处理与回退策略
|
||||
- 创建了提交前自查的质量保证检查清单
|
||||
- 所有保存操作均要求显式文件路径
|
||||
|
||||
详细变更:
|
||||
|
||||
[研究方法简介]
|
||||
之前:无(全新部分)……
|
||||
之后:你是一名专门从事全面、准确信息收集与综合的研究助手……
|
||||
理由:从一开始就为智能体设定明确的角色期望,并将准确性置于优先地位
|
||||
|
||||
[阶段 1 —— 收集]
|
||||
之前:无(原始任务中隐含但未在提示词中写明)……
|
||||
之后:1. **系统搜索** —— 使用网络搜索查找与你主题相关的来源
|
||||
2. **检查本地文件** —— 在外部搜索前,先检查项目中已有的研究笔记……
|
||||
理由:通过在抓取 URL 之前要求显式的来源优先级排序,解决了【低】工具误用问题
|
||||
|
||||
[阶段 2 —— 验证]
|
||||
之前:无(原始内容缺失)……
|
||||
之后:在撰写最终报告之前,你**必须**:
|
||||
- **交叉验证关键主张**,至少在 2 个来源之间进行核对……
|
||||
理由:通过添加显式的交叉验证要求和置信度评分,解决了【中】缺少验证问题
|
||||
|
||||
[阶段 3 —— 引用准确性]
|
||||
之前:无(仅隐含)……
|
||||
之后:- **仅引用你实际抓取过的来源** —— 如果你在不抓取来源的情况下凭借已有知识引用某内容,请明确标注为"[推断/次级参考]"……
|
||||
理由:通过要求仅引用已抓取来源并建立显式跟踪表以防止归属错误,解决了【低】幻觉问题
|
||||
|
||||
[阶段 4 —— 输出]
|
||||
之前:无(原始内容表述模糊)……
|
||||
之后:1. **保存中间发现**,使用 save_note 并指定显式文件路径(例如 `./output/research_notes.md`)……
|
||||
理由:明确了输出要求,并确保使用显式文件路径进行持久化
|
||||
|
||||
[错误处理]
|
||||
之前:无(缺失)……
|
||||
之后:如果主要来源不可用,尝试替代来源并注明:"主要来源获取失败,使用备用来源:[URL]"……
|
||||
理由:解决了缺失错误处理的问题 —— 提供了显式的回退策略
|
||||
|
||||
[质量保证检查清单]
|
||||
之前:无(缺失)……
|
||||
之后:在提交最终报告前,请验证:
|
||||
- [ ] 所有引用的来源均出现在你的来源跟踪表中并附有 URL……
|
||||
理由:增加了迭代完善步骤和完成前的自我评估,防止提交未经验证的工作
|
||||
|
||||
============================================================
|
||||
优化后的提示词
|
||||
============================================================
|
||||
|
||||
你是一名专门从事全面、准确信息收集与综合的研究助手。
|
||||
|
||||
## 研究方法
|
||||
|
||||
对每项研究任务,请遵循以下步骤:
|
||||
|
||||
### 阶段 1:信息收集
|
||||
1. **系统搜索** —— 使用网络搜索查找与你主题相关的来源
|
||||
2. **检查本地文件** —— 在外部搜索前,先检查项目中已有的研究笔记
|
||||
3. **排列来源优先级** —— 在调用 read_url 之前,列出你将抓取哪些来源,以及每个来源对你的研究目标有何相关性
|
||||
|
||||
### 阶段 2:来源验证与交叉核对
|
||||
在撰写最终报告之前,你**必须**:
|
||||
- **交叉验证关键主张**,至少在 2 个来源之间进行核对以验证一致性
|
||||
- **为每个主要发现分配置信度评分**(高/中/低),基于:
|
||||
- 相互印证的来源数量
|
||||
- 来源可靠性(同行评审 > 成熟机构 > 个人博客)
|
||||
- 直接引用 vs. 转述 vs. 推断
|
||||
- **标记不确定的信息** —— 注明任何无法验证或存在冲突来源的主张
|
||||
|
||||
### 阶段 3:来源跟踪与引用规则
|
||||
- **仅引用你实际抓取过的来源** —— 如果你在不抓取来源的情况下凭借已有知识引用某内容,请明确标注为"[推断/次级参考]"
|
||||
- **维护一张来源跟踪表**,包含:来源标题、URL、抓取日期、以及与你研究的相关性
|
||||
- **在最终报告中的每处引用**,均需包含获取该信息的实际 URL
|
||||
|
||||
### 阶段 4:输出创建
|
||||
1. **保存中间发现**,使用 save_note 并指定显式文件路径(例如 `./output/research_notes.md`)
|
||||
2. **在指定路径创建最终报告**,包含:
|
||||
- 关键概念与定义
|
||||
- 最佳实践与技术(包括"中间丢失"问题)
|
||||
- 针对智能体开发者的实用建议
|
||||
- 带 URL 的来源引用
|
||||
- 每项主要发现的置信度评估
|
||||
|
||||
## 错误处理
|
||||
- 如果主要来源不可用,尝试替代来源并注明:"主要来源获取失败,使用备用来源:[URL]"
|
||||
- 如果关键信息无法验证,请明确说明:"该主张无法通过主要来源进行验证"
|
||||
|
||||
## 质量保证
|
||||
在提交最终报告前,请验证:
|
||||
- [ ] 所有引用的来源均出现在你的来源跟踪表中并附有 URL
|
||||
- [ ] 没有提出任何未经至少一个已抓取来源支持的主张
|
||||
- [ ] 关键发现已分配置信度评分
|
||||
- [ ] "中间丢失"问题及其他指定主题已涉及
|
||||
- [ ] 文件已保存至正确的显式路径
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
name: deep-research-agent
|
||||
description: 专业研究助手,擅长全面、准确的信息收集与综合
|
||||
---
|
||||
|
||||
你是一名专业的研究助手,擅长全面、准确的信息收集与综合。
|
||||
|
||||
## 研究方法
|
||||
|
||||
请遵循以下步骤完成每项研究任务:
|
||||
|
||||
### 第一阶段:信息收集
|
||||
1. **系统化搜索** - 使用网络搜索查找与主题相关的信息来源
|
||||
2. **检查本地文件** - 在对外搜索之前,先查看项目中已有的研究笔记
|
||||
3. **优先级排序** - 在调用 read_url 之前,列出你将获取哪些来源,以及每个来源与你的研究目标之间的关联
|
||||
|
||||
### 第二阶段:来源验证与交叉引用
|
||||
在撰写最终报告之前,你**必须**:
|
||||
- **交叉验证关键主张**,至少比对 2 个来源以确保一致性
|
||||
- **为每项主要发现分配置信度评分**(高/中/低),依据:
|
||||
- 相互印证来源的数量
|
||||
- 来源的可靠性(同行评审 > 权威机构 > 个人博客)
|
||||
- 直接引用 vs. 转述 vs. 推断
|
||||
- **标注不确定信息** - 对无法验证或存在冲突来源的主张做出明确标注
|
||||
|
||||
### 第三阶段:来源追踪与引用规则
|
||||
- **仅引用你实际获取的来源** - 如果你依据已有知识引用某项内容而未实际获取来源,请明确标注为「[推断/二手引用]」
|
||||
- **维护来源追踪表**,包含:来源标题、URL、获取日期以及与研究的关联性
|
||||
- **最终报告中的每条引用**,都必须附上信息获取的实际 URL
|
||||
|
||||
### 第四阶段:输出生成
|
||||
1. **保存中间发现**,使用 save_note 并指定明确文件路径(例如 `./output/research_notes.md`)
|
||||
2. **在指定路径创建最终报告**,包含:
|
||||
- 核心概念与定义
|
||||
- 最佳实践与技术(包括「中间丢失」问题)
|
||||
- 面向智能体开发者的实用建议
|
||||
- 附 URL 的来源引用
|
||||
- 每项主要发现的置信度评估
|
||||
|
||||
## 错误处理
|
||||
- 如果主要来源不可用,尝试替代来源并注明:「主要来源获取失败,使用备选来源:[URL]」
|
||||
- 如果关键信息无法验证,明确说明:「该主张无法通过主要来源验证」
|
||||
|
||||
## 质量保证
|
||||
在提交最终报告前,请验证:
|
||||
- [ ] 所有引用的来源均出现在来源追踪表中,并附有 URL
|
||||
- [ ] 没有提出任何未得到至少一个已获取来源支持的主张
|
||||
- [ ] 关键发现已分配置信度评分
|
||||
- [ ] 「中间丢失」问题及其他指定主题已得到处理
|
||||
- [ ] 文件已保存至正确且明确的路径
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,40 @@
|
||||
- 推理清晰度:55/100
|
||||
- 目标遵循度:90/100
|
||||
- 工具使用质量:70/100
|
||||
- 错误恢复能力:40/100
|
||||
|
||||
检测到的模式:
|
||||
|
||||
[中等] missing_validation
|
||||
智能体在未验证来源相关性和质量的情况下,直接接受搜索结果并继续读取 URL
|
||||
建议:添加显式验证步骤:列出前 3-5 个来源并附带简短的选择理由,注明覆盖范围可能存在的缺口,优先选择一手权威来源而非二手来源
|
||||
|
||||
[中等] incomplete_reasoning
|
||||
思考块极其稀疏,缺少中间分析——智能体未说明它如何解读信息或做出决策
|
||||
建议:在每个主要信息收集步骤之后实施结构化反思:我学到了什么?这如何与我已知的信息关联?还有哪些缺口?接下来应优先处理什么?
|
||||
|
||||
[低] missing_validation
|
||||
智能体遇到工具调用失败(Anthropic 上下文窗口 URL 返回 404 错误),但在思考过程中未承认或恢复
|
||||
建议:添加显式错误确认:'尝试了 X 但失败并出现 Y 错误。将尝试备选方案 Z 或将此标记为缺口。' 这有助于提升调试和透明度
|
||||
|
||||
优势:
|
||||
+ 初始计划清晰,定义了步骤和里程碑
|
||||
+ 成功完成所有必需的任务组成部分(搜索、阅读来源、保存笔记、撰写总结)
|
||||
+ 来源选择得当,来自权威机构(Anthropic、OpenAI、学术论文)
|
||||
+ 最终输出内容全面、结构良好,并按需包含实际 URL
|
||||
+ 在可能的情况下合理使用了并行操作(搜索的同时检查目录)
|
||||
|
||||
劣势:
|
||||
- 思考块过于简短,未能提供对智能体决策过程的足够洞察
|
||||
- 缺少中间推理记录——不清楚智能体如何跨来源综合信息
|
||||
- 推理轨迹中未承认或恢复失败的工具调用(404 错误)
|
||||
- 在投入时间读取 URL 之前未验证搜索结果
|
||||
- 缺少显式缺口分析——智能体未说明缺少哪些信息
|
||||
- 来自 Anthropic 的 "Context Engineering for AI Agents" 来源出现在搜索结果中,但未在读取来源时清晰追溯
|
||||
|
||||
改进建议:
|
||||
1. 增加思考块的最小长度,要求显式反思学到了什么、如何与已有知识关联、还有哪些缺口
|
||||
2. 在搜索结果之后添加验证步骤:在读取来源之前,显式地对来源进行排序/优先级排序并附带简短理由
|
||||
3. 实施强制性错误确认机制:当工具调用失败时,下一个思考块必须处理该错误并提出恢复策略
|
||||
4. 在读取多个来源之后添加综合步骤:显式比较各来源的发现,记录共识与矛盾之处,并说明最终结论是如何得出的
|
||||
5. 在撰写最终输出之前,加入简短的"剩余缺口"评估,以确保完整性
|
||||
@@ -0,0 +1,106 @@
|
||||
- 增加了全面的提示结构,包含多个阶段和原则,替代了原单句提示词
|
||||
- 实施了强制性的实质性思考块(至少 3-5 句话),并附带明确的反思要求
|
||||
- 创建了明确的来源验证步骤,要求在阅读 URL 之前进行排序并说明理由
|
||||
- 增加了强制性错误确认及恢复策略要求
|
||||
- 增加了综合阶段,要求在最终输出之前进行比较、差距评估和结构化文档记录
|
||||
|
||||
详细变更:
|
||||
|
||||
[整体结构]
|
||||
之前:无(提示词仅为单句)...
|
||||
之后:全面的多节提示结构,包含核心原则、研究工作流、具体要求以...
|
||||
原因:原提示词仅为 1 句话,严重缺少说明。全面的结构为研究的所有阶段提供了清晰指导。
|
||||
|
||||
[思考要求]
|
||||
之前:无(未提供思考指导)...
|
||||
之后:「行动前先思考」原则,明确要求:「你的思考应该是实质性的——通...
|
||||
原因:通过要求实质性思考块并明确最低长度预期,解决了不完整推理模式。
|
||||
|
||||
[来源验证]
|
||||
之前:无(未提供验证指导)...
|
||||
之后:「验证来源」原则,包含明确的验证步骤:「收到搜索结果后,确定...
|
||||
原因:通过要求在使用 URL 之前对来源进行明确排序并附理由,解决了缺少验证模式的问题。
|
||||
|
||||
[错误处理]
|
||||
之前:无(未提供错误处理指导)...
|
||||
之后:「确认错误」原则:「当工具调用失败时,你必须在你的思考中明确...
|
||||
原因:通过强制要求确认错误并附带清晰的恢复要求,解决了工具调用失败模式的问题。
|
||||
|
||||
[阶段二:反思]
|
||||
之前:无(未提供反思框架)...
|
||||
之后:阅读每个主要来源后,回答 4 个具体问题进行反思:提供了哪些关...
|
||||
原因:提供了结构化的反思框架,确保智能体记录中间分析结果并在不同来源之间进行综合。
|
||||
|
||||
[阶段三:综合]
|
||||
之前:无(未提供综合指导)...
|
||||
之后:明确的综合阶段,包含 4 项要求:跨来源比较发现,识别最有价值...
|
||||
原因:确保智能体在撰写最终输出之前执行显式的信息整合,防止发现结果之间缺乏关联。
|
||||
|
||||
[阶段四:质量标准]
|
||||
之前:无(未提供质量标准)...
|
||||
之后:五项具体质量标准:思考块、来源选择、错误处理、综合、完整性...
|
||||
原因:使评估标准明确,让智能体了解每个阶段的高质量表现是什么样子。
|
||||
|
||||
============================================================
|
||||
优化后的提示词
|
||||
============================================================
|
||||
你是一名专家级研究助手,擅长全面的主题研究与综合。
|
||||
|
||||
## 核心原则
|
||||
|
||||
**行动前先思考**:始终利用你的思考块来反思所学内容、如何与已有知识关联、以及还存在哪些差距,然后再采取下一步行动。你的思考应该是实质性的——每个主要步骤通常至少 3-5 句话。
|
||||
|
||||
**验证来源**:在未先评估搜索结果之前,切勿直接读取 URL。根据相关性和权威性对来源进行排序,优先选择一手来源(官方文档、学术论文、权威出版物)而非二手来源。
|
||||
|
||||
**确认错误**:当工具调用失败时,你必须在下一个思考块中明确说明失败情况,并在继续之前提出恢复策略。
|
||||
|
||||
## 研究工作流
|
||||
|
||||
### 阶段一:规划与初始搜索
|
||||
1. 在搜索之前,记下你对主题已有的了解,并确定需要探索的关键概念
|
||||
2. 执行针对权威来源的搜索查询
|
||||
3. **验证步骤**:收到搜索结果后,确定最相关的 3-5 个来源。对每个来源简要说明:其相关性、权威级别(一手/二手),以及它可能涵盖主题的哪个方面
|
||||
|
||||
### 阶段二:信息收集
|
||||
1. 按优先顺序读取来源(先读一手来源)
|
||||
2. 阅读每个主要来源后,进行反思:
|
||||
- 这个来源提供了哪些关键信息?
|
||||
- 这与我已经了解的内容有何关联?
|
||||
- 出现了哪些新问题或空白?
|
||||
- 接下来应优先处理什么?
|
||||
3. 如果某个 URL 加载失败,在你的思考中确认该错误,并指出替代来源或标注该空白
|
||||
|
||||
### 阶段三:综合
|
||||
在撰写最终总结之前:
|
||||
1. 比较所有来源的发现——记录共识领域和任何矛盾之处
|
||||
2. 确定哪些来源提供了最有价值的见解
|
||||
3. 评估哪些信息仍然缺失或不完整
|
||||
4. 以结构化笔记形式记录关键收获
|
||||
|
||||
### 阶段四:输出生成
|
||||
撰写一份全面的总结报告,要求如下:
|
||||
- 清晰定义关键概念
|
||||
- 涵盖最佳实践与技术(包括「中间迷失」问题)
|
||||
- 为智能体开发者提供实用建议
|
||||
- 包含来自你研究的实际 URL 作为正确引用
|
||||
|
||||
## 本任务的具体要求
|
||||
|
||||
研究主题:「面向 AI 智能体的上下文工程」,并撰写一份全面的总结。
|
||||
|
||||
你的研究必须:
|
||||
1. 搜索有关上下文工程概念和最佳实践的信息
|
||||
2. 阅读相关来源以收集详细信息
|
||||
3. 检查本地项目文件中的 research/ 目录下是否有任何现有研究笔记
|
||||
4. 将重要发现作为笔记保存到 research/ 目录
|
||||
5. 将最终的总结报告写入 ./output/research_summary.md
|
||||
|
||||
## 质量标准
|
||||
|
||||
- **思考块**:必须是实质性的,并解释你的推理过程
|
||||
- **来源选择**:必须展示基于相关性和权威性的明确优先级排序
|
||||
- **错误处理**:必须透明地确认工具故障并进行恢复
|
||||
- **综合**:必须展示如何在多个来源之间整合信息
|
||||
- **完整性**:必须在最终输出之前包含简短的差距评估
|
||||
|
||||
请记住:全面、经过深思熟虑的研究能产生更好的输出。花时间反思每一步。
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
|
||||
你是一名专业的研究助理,擅长全面的主题研究与综合总结。
|
||||
|
||||
## 核心原则
|
||||
|
||||
**先思考再行动**:在采取下一步行动之前,始终使用你的思考区块来反思你学到了什么、这些信息如何与已有知识关联,以及还存在哪些空白。你的思考应当有实质性内容——通常每个主要步骤至少 3-5 句话。
|
||||
|
||||
**验证来源**:在未经评估搜索结果之前,绝不进行 URL 读取。按相关性和权威性对来源排序,优先使用一手来源(官方文档、学术论文、权威出版物)而非二手来源。
|
||||
|
||||
**承认错误**:当工具调用失败时,你必须在下一个思考区块中明确说明该失败,并在继续之前提出恢复策略。
|
||||
|
||||
## 研究工作流
|
||||
|
||||
### 第一阶段:规划与初步搜索
|
||||
1. 在搜索之前,记下你已经知道的关于该主题的信息,并确定要探索的关键概念
|
||||
2. 执行针对权威来源的搜索查询
|
||||
3. **验证步骤**:收到搜索结果后,确定最相关的 3-5 个来源。对每个来源简要说明:为什么它相关、它的权威级别(一手/二手),以及它可能涵盖该主题的哪个方面
|
||||
|
||||
### 第二阶段:信息收集
|
||||
1. 按优先级顺序阅读来源(先阅读一手来源)
|
||||
2. 阅读每个主要来源后,进行反思:
|
||||
- 这个来源提供了哪些关键信息?
|
||||
- 这些信息如何与我已学到的内容相关联?
|
||||
- 出现了哪些新问题或空白?
|
||||
- 接下来应该优先做什么?
|
||||
3. 如果 URL 加载失败,在思考中承认该错误,并确定替代来源或记录该空白
|
||||
|
||||
### 第三阶段:综合
|
||||
在撰写最终总结之前:
|
||||
1. 对比所有来源的发现——记录共识领域和任何矛盾之处
|
||||
2. 确定哪些来源提供了最有价值的见解
|
||||
3. 评估哪些信息仍然缺失或不完整
|
||||
4. 以结构化笔记的形式记录关键收获
|
||||
|
||||
### 第四阶段:输出生成
|
||||
撰写一份全面的总结报告,要求:
|
||||
- 清晰定义关键概念
|
||||
- 涵盖最佳实践和技术(包括"中间丢失"问题)
|
||||
- 为智能体开发者提供实用建议
|
||||
- 包含来自你研究的带有实际 URL 的适当引用
|
||||
|
||||
## 本任务的具体要求
|
||||
|
||||
研究"面向 AI 智能体的上下文工程"这一主题,并创建一份全面的总结。
|
||||
|
||||
你的研究必须:
|
||||
1. 搜索关于上下文工程概念和最佳实践的信息
|
||||
2. 阅读相关来源以收集详细信息
|
||||
3. 检查本地项目文件中 `research/` 目录下是否已存在任何研究笔记
|
||||
4. 将重要发现以笔记形式保存在 `research/` 目录中
|
||||
5. 将最终总结报告写入 `./output/research_summary.md`
|
||||
|
||||
## 质量标准
|
||||
|
||||
- **思考区块**:必须具有实质性内容,并解释你的推理过程
|
||||
- **来源选择**:必须展示基于相关性和权威性的明确优先级排序
|
||||
- **错误处理**:必须透明地承认工具失败并从中恢复
|
||||
- **综合能力**:必须展示你如何整合来自多个来源的信息
|
||||
- **完整性**:在最终输出之前必须包含简要的空白评估
|
||||
|
||||
请记住:深入、推理充分的研究能产生更好的输出。花时间反思每一步。
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,150 @@
|
||||
- 推理清晰度:75/100
|
||||
- 目标遵循度:90/100
|
||||
- 工具使用质量:55/100
|
||||
- 错误恢复能力:35/100
|
||||
|
||||
检测到的模式:
|
||||
|
||||
[低] incomplete_reasoning(推理不完整)
|
||||
代理在有限的工具交互后就得出了拥有"全面信息"的结论,而没有明确记录学到了什么或还存在哪些空白
|
||||
建议:在声称全面理解之前,增加更详细的推理,说明从每个来源具体获得了哪些信息,以及哪些问题仍未得到回答
|
||||
|
||||
[低] missing_validation(缺少验证)
|
||||
代理没有明确验证假设或在来源之间交叉核对信息。"Lost in the Middle"论文被多次提及,但没有与其他来源进行批判性比较
|
||||
建议:在阅读多个来源后,明确比较各项发现,记录矛盾之处,并在继续之前针对多个来源验证关键主张
|
||||
|
||||
[中] tool_misuse(工具误用)
|
||||
代理尝试读取一个返回错误的 URL(https://docs.anthropic.com/en/docs/build-with-claude/context-windows),但在没有确认或处理该失败的情况下继续执行
|
||||
建议:为失败的工具调用添加明确的错误处理——确认失败,尝试替代 URL,或在研究中记录该空白
|
||||
|
||||
优势:
|
||||
+ 目标遵循度高——所有 5 项必需任务均成功完成
|
||||
+ 遵循研究流程的系统性工作流表现出色
|
||||
+ 来源选择得当,均来自权威参考(Anthropic、OpenAI、arxiv)
|
||||
+ 最终报告全面,覆盖了所有必需章节并附有恰当的引用
|
||||
+ 有效使用中间笔记在综合之前组织研究发现
|
||||
|
||||
不足:
|
||||
- 缺少对失败 URL 获取(context-windows 页面)的错误处理
|
||||
- 思考模块过于简短,缺少关于来源选择和综合的详细推理
|
||||
- 没有在来源之间进行明确的验证或交叉引用
|
||||
- 在有限的工具交互后过早声称拥有"全面信息"
|
||||
|
||||
建议:
|
||||
1. 为工具失败添加明确的错误处理——当 URL 获取失败时,在思考中确认该失败,然后要么尝试替代方案,要么记录该空白
|
||||
2. 扩展思考模块,使其包括:从每个来源学到了什么、各项发现如何对比/对照、以及哪些问题仍未得到回答
|
||||
3. 实施验证步骤,在继续之前将来自一个来源的关键主张与至少另一个来源进行核对
|
||||
4. 用具体的学习总结和存在的空白替代模糊的"全面信息"表述
|
||||
|
||||
```reasoning_trace_analysis.md
|
||||
---
|
||||
name: reasoning-trace-analysis-report
|
||||
description: 分析代理推理轨迹以评估推理质量、工具使用和错误恢复能力
|
||||
metadata:
|
||||
type: reference
|
||||
---
|
||||
|
||||
# 推理痕迹分析报告
|
||||
|
||||
## 概述
|
||||
|
||||
推理痕迹分析报告评估代理在解决任务过程中的推理质量。它分析推理清晰度、目标遵循度、工具使用质量和错误恢复能力。分析结果提供具体分数、检测到的模式以及可操作的改进建议。
|
||||
|
||||
## 分析维度
|
||||
|
||||
### 推理清晰度(权重:高)
|
||||
评估推理步骤的清晰度和逻辑一致性。考察代理在多大程度上记录了自己的思考过程、做出的假设以及从每个来源学到的内容。
|
||||
|
||||
**关键指标:**
|
||||
- 推理步骤是否明确记录并易于追踪
|
||||
- 结论是否基于具体的发现而非模糊的陈述
|
||||
- 是否在声明声称之前识别并记录了信息空白
|
||||
|
||||
### 目标遵循度(权重:高)
|
||||
衡量代理在多大程度上完成了任务中规定的目标和要求。
|
||||
|
||||
**关键指标:**
|
||||
- 所有必需任务是否全部完成
|
||||
- 工作流程是否遵循预期的研究过程
|
||||
- 最终产出是否满足所有规定的质量标准
|
||||
|
||||
### 工具使用质量(权重:中)
|
||||
评估代理如何选择和使用可用工具来完成任务。
|
||||
|
||||
**关键指标:**
|
||||
- 工具选择是否适合当前任务
|
||||
- 工具调用是否高效且有序
|
||||
- 失败的工具调用是否得到适当处理或记录
|
||||
|
||||
### 错误恢复能力(权重:中)
|
||||
衡量代理在遇到错误或意外情况时如何响应。
|
||||
|
||||
**关键指标:**
|
||||
- 当工具调用失败时,代理是否确认了该失败
|
||||
- 是否尝试了替代策略或记录了信息空白
|
||||
- 失败是否被优雅地处理,不影响整体任务的完成
|
||||
|
||||
## 评分量表
|
||||
|
||||
| 分数范围 | 等级 | 说明 |
|
||||
|----------|------|------|
|
||||
| 90-100 | 优秀 | 示范性的推理和任务执行 |
|
||||
| 75-89 | 良好 | 大部分维度表现扎实,有少量改进空间 |
|
||||
| 50-74 | 一般 | 在一些维度上表现中等,在其他维度上存在明显不足 |
|
||||
| 25-49 | 差 | 在多个维度上表现不足,需要显著改进 |
|
||||
| 0-24 | 不及格 | 关键维度存在严重缺陷 |
|
||||
|
||||
## 检测到的模式
|
||||
|
||||
| 严重级别 | 模式 | 说明 |
|
||||
|----------|------|------|
|
||||
| 高 | pattern_skip | 代理跳过了一个应该执行的任务或步骤 |
|
||||
| 中 | tool_misuse | 工具选择不适合任务,或失败的工具调用未得到处理 |
|
||||
| 中 | hallucination | 代理声称做了某件事但痕迹中未发现相应证据 |
|
||||
| 中 | premature_termination | 代理过早终止,留下未完成的任务或未解决的状态 |
|
||||
| 低 | incomplete_reasoning | 推理步骤不完整或过于简略,难以评估思维过程 |
|
||||
| 低 | missing_validation | 信息未在多个来源之间进行验证或交叉引用 |
|
||||
| 低 | vague_claims | 使用了模糊的表述(如"全面信息"),而没有具体的细节支持 |
|
||||
|
||||
## 改进建议
|
||||
|
||||
### 错误处理
|
||||
1. 始终确认工具调用的失败——不要静默地继续执行
|
||||
2. 当主要来源不可用时,尝试替代来源或方法
|
||||
3. 在最终报告中记录失败和空白,以便用户了解研究的局限性
|
||||
|
||||
### 推理质量
|
||||
1. 明确记录每个推理步骤及其依据
|
||||
2. 在声明全面理解之前,识别并说明信息空白
|
||||
3. 在来源之间比较发现,并记录任何矛盾之处
|
||||
|
||||
### 工具使用
|
||||
1. 选择最适合当前任务的工具
|
||||
2. 以合乎逻辑的顺序组织工具调用
|
||||
3. 优先使用专用工具而非通用命令
|
||||
|
||||
## 输出格式
|
||||
|
||||
报告应以 Markdown 格式输出,包含以下部分:
|
||||
|
||||
- **总分**和**评分明细**(所有维度)
|
||||
- **检测到的模式**(含严重级别和描述)
|
||||
- **优势**和**不足**
|
||||
- **可操作的建议**
|
||||
|
||||
## 使用示例
|
||||
|
||||
```markdown
|
||||
# 推理痕迹分析报告
|
||||
|
||||
总分:64/100
|
||||
|
||||
优势:
|
||||
- 目标遵循度强——所有任务均已完成
|
||||
- 来源选择得当,来自权威参考
|
||||
|
||||
建议:
|
||||
- 为失败的工具调用添加错误处理
|
||||
- 在声称全面理解之前,记录信息空白
|
||||
```
|
||||
```
|
||||
@@ -0,0 +1,107 @@
|
||||
---
|
||||
|
||||
PROMPT OPTIMIZATION REPORT
|
||||
============================================================
|
||||
|
||||
预计改进:20%
|
||||
置信度:85%
|
||||
|
||||
关键变更:
|
||||
- 将单句提示词替换为涵盖工作流程、错误处理、质量标准与禁止行为的多节结构化提示词
|
||||
- 新增明确的阶段 3 综合/验证要求,要求在声称完成前进行交叉引用和差距记录
|
||||
- 新增失败工具调用的强制错误处理协议,附带具体恢复操作
|
||||
- 新增详细的思考块要求,强制包含具体内容(见解、关联、缺口、下一步),而非模糊陈述
|
||||
- 在最终输出中新增「局限与缺口」章节,确保研究边界的透明度
|
||||
|
||||
详细变更:
|
||||
|
||||
[整个提示词结构]
|
||||
之前:无(全新结构化提示词)……
|
||||
之后:创建了一个包含阶段、质量标准、错误处理和禁止行为的全面提示词……
|
||||
原因:原始单句提示词未对推理质量、错误处理或综合要求提供任何指导。包含明确阶段与标准的结构化提示词能够应对所检测到的问题。
|
||||
|
||||
[工作流程指令]
|
||||
之前:使用可用工具协助完成研究任务……
|
||||
之后:对于你阅读的每个来源:
|
||||
- 记录你学到了什么:撰写一个思考块,总结关键见解……
|
||||
原因:通过要求针对每个来源记录具体内容而非模糊的完成声明,应对 incomplete_reasoning 模式。
|
||||
|
||||
[综合要求]
|
||||
之前:无(无综合指导)……
|
||||
之后:针对关键声明,交叉引用 2 个以上来源的发现;记录矛盾之处;明确列出剩余的……
|
||||
原因:通过要求在声称完成前进行明确的交叉引用与差距分析,应对 missing_validation 模式。
|
||||
|
||||
[错误处理]
|
||||
之前:无(无错误处理指导)……
|
||||
之后:失败的工具调用:在思考块中承认,尝试替代方案或记录缺口;无结果返回:尝试……
|
||||
原因:通过要求明确承认失败并尝试恢复,应对 tool_misuse 模式。
|
||||
|
||||
[思考块要求]
|
||||
之前:无(无思考指导)……
|
||||
之后:必须包含:(1)学到的具体见解,(2)这与已有知识如何契合,(3)还有哪些……
|
||||
原因:通过要求在每次思考块中包含具体内容,防止模糊的「全面信息」声明。
|
||||
|
||||
[禁止行为]
|
||||
之前:无(无明确限制)……
|
||||
之后:三项具体禁止:过早声称完成、忽略失败的工具调用、在未说明的情况下综合……
|
||||
原因:创建了直接针对已检测到的失败模式的明确负面约束。
|
||||
|
||||
[输出格式要求]
|
||||
之前:无(无输出结构指导)……
|
||||
之后:要求:清晰的标题、要点、正确的 URL 归属,以及「局限与缺口」章节……
|
||||
原因:确保最终交付物全面且对研究边界保持透明。
|
||||
|
||||
============================================================
|
||||
OPTIMIZED PROMPT
|
||||
============================================================
|
||||
你是一名研究助手,帮助用户对复杂主题进行深入且记录完备的研究。
|
||||
|
||||
## 你的工作流程
|
||||
遵循以下结构化研究流程:
|
||||
|
||||
### 阶段 1:初步探索
|
||||
1. 搜索该主题的基础性与最新信息
|
||||
2. 检查本地项目文件中是否存在已有的研究笔记
|
||||
3. 根据相关性与可信度,确定要阅读的关键来源
|
||||
|
||||
### 阶段 2:深入研究与记录
|
||||
对于你阅读的每个来源:
|
||||
- **记录你学到了什么**:撰写一个思考块,总结关键见解,而不仅仅是说你「读过」该来源
|
||||
- **记录缺口**:确定阅读此来源后仍有哪些问题未得到回答
|
||||
- **标记待验证项**:标记应与其他来源交叉验证的声明
|
||||
|
||||
### 阶段 3:综合与验证
|
||||
在声称你拥有「全面信息」之前:
|
||||
- **交叉引用**:针对关键声明,对比 2 个以上来源的发现
|
||||
- **记录矛盾之处**:如果来源之间存在分歧,记录双方视角
|
||||
- **明确列出剩余缺口**:你仍然不知道什么?
|
||||
- **评估覆盖范围**:你是否涵盖了交付物要求的全部章节?
|
||||
|
||||
### 阶段 4:记录与报告
|
||||
1. 将重要发现保存为结构化笔记
|
||||
2. 将最终总结报告写入指定的输出路径
|
||||
3. 附上来源 URL 及具体的页面/章节引用
|
||||
|
||||
## 错误处理
|
||||
- **失败的工具调用**:如果 URL 获取失败,在你的思考块中承认这一点。尝试替代 URL 或清晰记录研究缺口
|
||||
- **无结果返回**:如果搜索未产生有用结果,先尝试不同的搜索词再继续
|
||||
- **权限被拒**:如果你无法访问某个文件或目录,记录该问题并在可用资源范围内继续
|
||||
|
||||
## 质量标准
|
||||
你的思考块必须包含:
|
||||
1. **你从每次操作中学到了什么**(具体见解,而非仅仅是「我读了 X」)
|
||||
2. **这与已有知识如何契合**(与之前来源的信息对比)
|
||||
3. **关于该主题,还有哪些仍然未知**
|
||||
4. **基于这些新信息,你接下来会做什么**
|
||||
|
||||
## 禁止行为
|
||||
- 在未明确列出已覆盖内容及剩余缺口的情况下,声称拥有「全面信息」
|
||||
- 在不承认失败或未尝试恢复的情况下,跳过失败的工具调用
|
||||
- 在不展示如何综合多个来源信息的情况下,保存笔记或撰写报告
|
||||
|
||||
## 输出格式
|
||||
将最终总结报告保存为结构良好的 Markdown 文档,包含:
|
||||
- 每个必需主题的清晰章节标题
|
||||
- 具体发现使用要点列表
|
||||
- 所有来源均附带 URL 的正确归属
|
||||
- 标注研究未覆盖内容的「局限与缺口」章节
|
||||
@@ -0,0 +1,49 @@
|
||||
## 你的工作流程
|
||||
请遵循以下结构化研究流程:
|
||||
|
||||
### 阶段一:初步探索
|
||||
1. 搜索有关该主题的基础性与最新信息
|
||||
2. 检查本地项目文件中是否存在已有的研究笔记
|
||||
3. 根据相关性与可信度,识别出需要精读的关键来源
|
||||
|
||||
### 阶段二:深度研究与记录
|
||||
对于你精读的**每一个**来源:
|
||||
- **记录你的收获**:写一段思考块,总结关键见解,而不仅仅是「已阅读」该来源
|
||||
- **标注缺口**:指出在阅读该来源后仍有待回答的问题
|
||||
- **标记待验证项**:标注需要与其他来源交叉核验的论断
|
||||
|
||||
### 阶段三:综合与验证
|
||||
在声称已掌握「全面信息」之前:
|
||||
- **交叉引用**:对关键论断,对比至少 2 个来源的发现
|
||||
- **记录矛盾点**:若来源之间存在分歧,记录双方观点
|
||||
- **明确列出尚存缺口**:你还有哪些内容尚不了解?
|
||||
- **评估覆盖度**:是否已涵盖输出物要求的所有章节?
|
||||
|
||||
### 阶段四:文档与报告
|
||||
1. 将重要发现保存为结构化笔记
|
||||
2. 将最终总结报告写入指定的输出路径
|
||||
3. 附上来源 URL 及具体页面/章节引用
|
||||
|
||||
## 错误处理
|
||||
- **工具调用失败**:若 URL 获取失败,在思考块中加以说明。尝试备选 URL,或清晰记录该研究缺口
|
||||
- **无结果返回**:若搜索未返回有用结果,在继续之前尝试更换搜索词
|
||||
- **权限被拒**:若无法访问某文件或目录,注明该问题并利用现有资源继续
|
||||
|
||||
## 质量标准
|
||||
你的思考块必须包含以下内容:
|
||||
1. **你从每次操作中学到了什么**(具体见解,而非仅仅「我阅读了 X」)
|
||||
2. **这与先前来源的已知信息如何衔接**
|
||||
3. **该主题仍有待了解的内容**
|
||||
4. **基于这一新信息,下一步将做什么**
|
||||
|
||||
## 禁止行为
|
||||
- 在未明确列出已覆盖内容与尚存缺口的情况下声称已掌握「全面信息」
|
||||
- 在工具调用失败后不加以说明、也不尝试恢复便继续推进
|
||||
- 在未展示如何综合多个来源的信息之前就保存笔记或撰写报告
|
||||
|
||||
## 输出格式
|
||||
将最终总结报告保存为结构清晰的 Markdown 文档,包含:
|
||||
- 每个必要主题的清晰章节标题
|
||||
- 用项目符号列出具体发现
|
||||
- 所有来源的正确归因及 URL
|
||||
- 一个「局限与缺口」章节,说明你的研究未覆盖的内容
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"task": "Research the topic of \"context engineering for AI agents\" and create a comprehensive summary.\n\nYour research should:\n1. Search for information about context engineering concepts and best practices\n2. Read relevant sources to gather detailed information\n3. Check the local project files for any existing research notes\n4. Save important findings as notes for future reference\n5. Write a final summary report to ./output/research_summary.md\n\nThe summary should include:\n- Key concepts and definitions\n- Best practices and techniques (including the \"lost in the middle\" problem)\n- Practical recommendations for agent developers\n- References to sources consulted (use actual URLs from your research)",
|
||||
"total_iterations": 10,
|
||||
"converged": true,
|
||||
"initial_score": 67.6,
|
||||
"final_score": 72.0,
|
||||
"best_iteration": 4,
|
||||
"improvement_percentage": 6.5,
|
||||
"timestamp": "2026-01-11T18:02:27.953763",
|
||||
"note": "Best prompt from iteration 4 (score 72/100) used as final prompt"
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=61.0", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "reasoning-trace-optimizer"
|
||||
version = "0.1.0"
|
||||
description = "Debug and optimize AI agents by analyzing reasoning traces using MiniMax M2.1's interleaved thinking. Built in partnership with MiniMax AI."
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
authors = [
|
||||
{name = "Muratcan Koylan", email = "muratcan.koylan@outlook.com"}
|
||||
]
|
||||
keywords = [
|
||||
"ai-agents",
|
||||
"reasoning-traces",
|
||||
"prompt-optimization",
|
||||
"minimax-m2",
|
||||
"interleaved-thinking",
|
||||
"agent-debugging",
|
||||
"context-engineering"
|
||||
]
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
||||
]
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"anthropic>=0.40.0",
|
||||
"pydantic>=2.0.0",
|
||||
"rich>=13.0.0",
|
||||
"python-dotenv>=1.0.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pytest>=8.0.0",
|
||||
"pytest-asyncio>=0.23.0",
|
||||
"ruff>=0.1.0",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
rto = "reasoning_trace_optimizer.cli:main"
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering"
|
||||
Repository = "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering"
|
||||
Documentation = "https://github.com/muratcankoylan/Agent-Skills-for-Context-Engineering/tree/main/examples/interleaved-thinking"
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["."]
|
||||
include = ["reasoning_trace_optimizer*"]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 100
|
||||
target-version = "py310"
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "I", "N", "W"]
|
||||
ignore = ["E501"]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
asyncio_mode = "auto"
|
||||
testpaths = ["tests"]
|
||||
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
Reasoning Trace Optimizer
|
||||
|
||||
Debug and optimize AI agents by analyzing reasoning traces
|
||||
using MiniMax M2.1's interleaved thinking capabilities.
|
||||
"""
|
||||
|
||||
from reasoning_trace_optimizer.models import (
|
||||
ReasoningTrace,
|
||||
ThinkingBlock,
|
||||
ToolCall,
|
||||
Pattern,
|
||||
PatternType,
|
||||
Severity,
|
||||
AnalysisResult,
|
||||
OptimizationResult,
|
||||
PromptDiff,
|
||||
LoopIteration,
|
||||
LoopResult,
|
||||
)
|
||||
from reasoning_trace_optimizer.capture import TraceCapture
|
||||
from reasoning_trace_optimizer.analyzer import TraceAnalyzer
|
||||
from reasoning_trace_optimizer.optimizer import PromptOptimizer
|
||||
from reasoning_trace_optimizer.loop import OptimizationLoop, LoopConfig
|
||||
from reasoning_trace_optimizer.skill_generator import SkillGenerator
|
||||
|
||||
__version__ = "0.1.0"
|
||||
|
||||
__all__ = [
|
||||
# Models
|
||||
"ReasoningTrace",
|
||||
"ThinkingBlock",
|
||||
"ToolCall",
|
||||
"Pattern",
|
||||
"PatternType",
|
||||
"Severity",
|
||||
"AnalysisResult",
|
||||
"OptimizationResult",
|
||||
"PromptDiff",
|
||||
"LoopIteration",
|
||||
"LoopResult",
|
||||
# Capture
|
||||
"TraceCapture",
|
||||
# Analyzer
|
||||
"TraceAnalyzer",
|
||||
# Optimizer
|
||||
"PromptOptimizer",
|
||||
# Loop
|
||||
"OptimizationLoop",
|
||||
"LoopConfig",
|
||||
# Skill Generator
|
||||
"SkillGenerator",
|
||||
]
|
||||
@@ -0,0 +1,465 @@
|
||||
"""
|
||||
TraceAnalyzer: Analyzes reasoning traces to detect patterns and issues.
|
||||
|
||||
Uses M2.1's own interleaved thinking to analyze agent reasoning traces,
|
||||
detecting patterns like context degradation, tool confusion, and instruction drift.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
import anthropic
|
||||
|
||||
from reasoning_trace_optimizer.models import (
|
||||
AnalysisResult,
|
||||
Pattern,
|
||||
PatternType,
|
||||
ReasoningTrace,
|
||||
Severity,
|
||||
)
|
||||
|
||||
|
||||
ANALYSIS_SYSTEM_PROMPT = """You are an expert AI agent debugger specializing in analyzing reasoning traces.
|
||||
|
||||
Your task is to analyze an agent's interleaved thinking trace and identify:
|
||||
1. **Patterns of failure** - detect specific failure modes with evidence
|
||||
2. **Quality scores** - rate the agent's reasoning on multiple dimensions
|
||||
3. **Actionable recommendations** - specific improvements for prompts/instructions
|
||||
|
||||
## Pattern Definitions
|
||||
|
||||
Detect these patterns with specific evidence from thinking blocks:
|
||||
|
||||
- **context_degradation**: Agent loses or forgets information from earlier in the conversation
|
||||
- Look for: Repeated questions, contradicting earlier statements, missing key details
|
||||
- **tool_confusion**: Agent misunderstands what a tool does or how to use it
|
||||
- Look for: Wrong tool selection, incorrect parameters, misinterpreting results
|
||||
- **instruction_drift**: Agent gradually deviates from original instructions/persona
|
||||
- Look for: Changing behavior, ignoring constraints, different tone over time
|
||||
- **hallucination**: Agent generates information not supported by context or tools
|
||||
- Look for: Made-up facts, fabricated tool results, unsourced claims
|
||||
- **incomplete_reasoning**: Agent reaches conclusions without thorough analysis
|
||||
- Look for: Skipped steps, missing validation, superficial exploration
|
||||
- **tool_misuse**: Agent uses tools incorrectly or inefficiently
|
||||
- Look for: Redundant calls, wrong parameters, unused results
|
||||
- **goal_abandonment**: Agent stops pursuing the original objective
|
||||
- Look for: Topic drift, giving up, switching goals without reason
|
||||
- **circular_reasoning**: Agent repeats similar actions without progress
|
||||
- Look for: Same queries repeated, looping behavior, no new information
|
||||
- **premature_conclusion**: Agent concludes before completing the task
|
||||
- Look for: Early stops, incomplete answers, skipped requirements
|
||||
- **missing_validation**: Agent doesn't verify results or assumptions
|
||||
- Look for: No cross-checking, accepting first result, no error handling
|
||||
|
||||
## Analysis Focus
|
||||
|
||||
You have access to the FULL reasoning trace including all thinking blocks between tool calls.
|
||||
This gives you unique insight into HOW the agent reasons, not just what it outputs.
|
||||
|
||||
For each thinking block, examine:
|
||||
- What is the agent's current understanding?
|
||||
- How does it interpret tool results?
|
||||
- What alternatives does it consider?
|
||||
- Does it maintain awareness of the original goal?
|
||||
|
||||
Provide your analysis in the specified JSON format with concrete evidence."""
|
||||
|
||||
|
||||
ANALYSIS_PROMPT_TEMPLATE = """Analyze the following agent reasoning trace:
|
||||
|
||||
## Task
|
||||
{task}
|
||||
|
||||
## System Prompt Given to Agent
|
||||
{system_prompt}
|
||||
|
||||
## Reasoning Trace
|
||||
{trace}
|
||||
|
||||
## Tool Calls Made
|
||||
{tool_calls}
|
||||
|
||||
## Final Outcome
|
||||
Success: {success}
|
||||
Final Response: {final_response}
|
||||
Error (if any): {error}
|
||||
|
||||
---
|
||||
|
||||
Provide your analysis as JSON with this exact structure:
|
||||
```json
|
||||
{{
|
||||
"patterns": [
|
||||
{{
|
||||
"type": "<one of: context_degradation, tool_confusion, instruction_drift, hallucination, incomplete_reasoning, tool_misuse, goal_abandonment, circular_reasoning, premature_conclusion, missing_validation>",
|
||||
"severity": "<one of: low, medium, high, critical>",
|
||||
"description": "<what the pattern is>",
|
||||
"evidence": ["<excerpt from thinking>", "<another excerpt>"],
|
||||
"turn_indices": [0, 2],
|
||||
"suggestion": "<how to fix this>",
|
||||
"confidence": 0.85
|
||||
}}
|
||||
],
|
||||
"scores": {{
|
||||
"reasoning_clarity": 75,
|
||||
"goal_adherence": 80,
|
||||
"tool_usage_quality": 60,
|
||||
"error_recovery": 50,
|
||||
"overall": 66
|
||||
}},
|
||||
"strengths": ["<strength 1>", "<strength 2>"],
|
||||
"weaknesses": ["<weakness 1>", "<weakness 2>"],
|
||||
"recommendations": [
|
||||
"<specific actionable recommendation>",
|
||||
"<another recommendation>"
|
||||
]
|
||||
}}
|
||||
```
|
||||
|
||||
Think carefully about each aspect before providing your analysis."""
|
||||
|
||||
|
||||
class TraceAnalyzer:
|
||||
"""
|
||||
Analyzes reasoning traces using M2.1 to detect patterns and score quality.
|
||||
|
||||
The analyzer uses M2.1's interleaved thinking to deeply understand
|
||||
the agent's reasoning process and identify issues that wouldn't be
|
||||
visible from outputs alone.
|
||||
|
||||
Example:
|
||||
```python
|
||||
analyzer = TraceAnalyzer()
|
||||
result = analyzer.analyze(trace)
|
||||
|
||||
print(f"Overall score: {result.overall_score}")
|
||||
for pattern in result.patterns:
|
||||
print(f"Found: {pattern.type.value} ({pattern.severity.value})")
|
||||
```
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api_key: str | None = None,
|
||||
base_url: str = "https://api.minimax.io/anthropic",
|
||||
model: str = "MiniMax-M2.1",
|
||||
):
|
||||
"""
|
||||
Initialize TraceAnalyzer with M2.1 configuration.
|
||||
|
||||
Args:
|
||||
api_key: MiniMax API key
|
||||
base_url: API endpoint
|
||||
model: Model for analysis (M2.1 recommended for best results)
|
||||
"""
|
||||
self.model = model
|
||||
self.client = anthropic.Anthropic(
|
||||
api_key=api_key or os.environ.get("ANTHROPIC_API_KEY"),
|
||||
base_url=base_url,
|
||||
)
|
||||
|
||||
def analyze(
|
||||
self,
|
||||
trace: ReasoningTrace,
|
||||
max_tokens: int = 8192,
|
||||
) -> AnalysisResult:
|
||||
"""
|
||||
Analyze a reasoning trace and return detailed analysis.
|
||||
|
||||
Args:
|
||||
trace: The reasoning trace to analyze
|
||||
max_tokens: Maximum tokens for analysis response
|
||||
|
||||
Returns:
|
||||
AnalysisResult with patterns, scores, and recommendations
|
||||
"""
|
||||
# Format trace for analysis
|
||||
trace_text = self._format_trace_for_analysis(trace)
|
||||
tool_calls_text = self._format_tool_calls(trace)
|
||||
|
||||
prompt = ANALYSIS_PROMPT_TEMPLATE.format(
|
||||
task=trace.task,
|
||||
system_prompt=trace.system_prompt,
|
||||
trace=trace_text,
|
||||
tool_calls=tool_calls_text,
|
||||
success=trace.success,
|
||||
final_response=trace.final_response or "None",
|
||||
error=trace.error or "None",
|
||||
)
|
||||
|
||||
# Call M2.1 for analysis
|
||||
response = self.client.messages.create(
|
||||
model=self.model,
|
||||
max_tokens=max_tokens,
|
||||
system=ANALYSIS_SYSTEM_PROMPT,
|
||||
messages=[{"role": "user", "content": prompt}],
|
||||
)
|
||||
|
||||
# Extract thinking and text from response
|
||||
analyzer_thinking = ""
|
||||
analysis_text = ""
|
||||
|
||||
for block in response.content:
|
||||
if block.type == "thinking":
|
||||
analyzer_thinking = block.thinking
|
||||
elif block.type == "text":
|
||||
analysis_text = block.text
|
||||
|
||||
# Parse the JSON response
|
||||
result = self._parse_analysis_response(analysis_text, trace.session_id)
|
||||
result.analyzer_thinking = analyzer_thinking
|
||||
result.analyzer_model = self.model
|
||||
|
||||
return result
|
||||
|
||||
def analyze_batch(
|
||||
self,
|
||||
traces: list[ReasoningTrace],
|
||||
) -> list[AnalysisResult]:
|
||||
"""Analyze multiple traces and return results."""
|
||||
return [self.analyze(trace) for trace in traces]
|
||||
|
||||
def quick_score(
|
||||
self,
|
||||
trace: ReasoningTrace,
|
||||
) -> float:
|
||||
"""
|
||||
Get a quick overall score without full pattern analysis.
|
||||
|
||||
Useful for optimization loops where you need fast feedback.
|
||||
|
||||
Args:
|
||||
trace: The reasoning trace to score
|
||||
|
||||
Returns:
|
||||
Overall score from 0-100
|
||||
"""
|
||||
quick_prompt = f"""Rate this agent's performance from 0-100 based on its reasoning trace.
|
||||
|
||||
Task: {trace.task}
|
||||
Success: {trace.success}
|
||||
Turns: {trace.total_turns}
|
||||
|
||||
Thinking excerpts:
|
||||
{self._get_thinking_excerpts(trace, max_chars=2000)}
|
||||
|
||||
Respond with ONLY a number from 0-100."""
|
||||
|
||||
response = self.client.messages.create(
|
||||
model=self.model,
|
||||
max_tokens=100,
|
||||
messages=[{"role": "user", "content": quick_prompt}],
|
||||
)
|
||||
|
||||
# Extract score from response
|
||||
for block in response.content:
|
||||
if block.type == "text":
|
||||
try:
|
||||
score = float(block.text.strip())
|
||||
return min(100, max(0, score))
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return 50.0 # Default middle score if parsing fails
|
||||
|
||||
def _format_trace_for_analysis(self, trace: ReasoningTrace) -> str:
|
||||
"""Format thinking blocks for analysis."""
|
||||
parts = []
|
||||
for i, thinking in enumerate(trace.thinking_blocks):
|
||||
parts.append(f"[Turn {thinking.turn_index}] Thinking:")
|
||||
parts.append(thinking.content)
|
||||
parts.append("")
|
||||
|
||||
return "\n".join(parts)
|
||||
|
||||
def _format_tool_calls(self, trace: ReasoningTrace) -> str:
|
||||
"""Format tool calls for analysis."""
|
||||
if not trace.tool_calls:
|
||||
return "No tool calls made."
|
||||
|
||||
parts = []
|
||||
for tc in trace.tool_calls:
|
||||
status = "Success" if tc.success else f"Failed: {tc.error}"
|
||||
parts.append(
|
||||
f"- {tc.name}({json.dumps(tc.input)}) -> {status}\n"
|
||||
f" Result: {tc.result[:200] if tc.result else 'None'}..."
|
||||
)
|
||||
|
||||
return "\n".join(parts)
|
||||
|
||||
def _get_thinking_excerpts(self, trace: ReasoningTrace, max_chars: int = 2000) -> str:
|
||||
"""Get excerpts from thinking blocks."""
|
||||
excerpts = []
|
||||
remaining = max_chars
|
||||
|
||||
for thinking in trace.thinking_blocks:
|
||||
if remaining <= 0:
|
||||
break
|
||||
excerpt = thinking.content[:remaining]
|
||||
excerpts.append(f"[Turn {thinking.turn_index}]: {excerpt}")
|
||||
remaining -= len(excerpt) + 20
|
||||
|
||||
return "\n\n".join(excerpts)
|
||||
|
||||
def _parse_analysis_response(
|
||||
self,
|
||||
response_text: str,
|
||||
trace_id: str,
|
||||
) -> AnalysisResult:
|
||||
"""Parse the JSON analysis response from M2.1."""
|
||||
result = AnalysisResult(trace_id=trace_id)
|
||||
|
||||
try:
|
||||
# Extract JSON from response (may have markdown code blocks)
|
||||
json_text = response_text
|
||||
if "```json" in response_text:
|
||||
json_text = response_text.split("```json")[1].split("```")[0]
|
||||
elif "```" in response_text:
|
||||
json_text = response_text.split("```")[1].split("```")[0]
|
||||
|
||||
data = json.loads(json_text)
|
||||
|
||||
# Parse patterns
|
||||
for p in data.get("patterns", []):
|
||||
try:
|
||||
pattern = Pattern(
|
||||
type=PatternType(p["type"]),
|
||||
severity=Severity(p["severity"]),
|
||||
description=p["description"],
|
||||
evidence=p.get("evidence", []),
|
||||
turn_indices=p.get("turn_indices", []),
|
||||
suggestion=p.get("suggestion", ""),
|
||||
confidence=p.get("confidence", 0.5),
|
||||
)
|
||||
result.patterns.append(pattern)
|
||||
except (KeyError, ValueError):
|
||||
continue
|
||||
|
||||
# Parse scores
|
||||
scores = data.get("scores", {})
|
||||
result.reasoning_clarity = scores.get("reasoning_clarity", 0)
|
||||
result.goal_adherence = scores.get("goal_adherence", 0)
|
||||
result.tool_usage_quality = scores.get("tool_usage_quality", 0)
|
||||
result.error_recovery = scores.get("error_recovery", 0)
|
||||
result.overall_score = scores.get("overall", 0)
|
||||
|
||||
# Parse feedback
|
||||
result.strengths = data.get("strengths", [])
|
||||
result.weaknesses = data.get("weaknesses", [])
|
||||
result.recommendations = data.get("recommendations", [])
|
||||
|
||||
except (json.JSONDecodeError, KeyError) as e:
|
||||
# If parsing fails, try fallback extraction and set reasonable defaults
|
||||
result = self._fallback_parse_analysis(response_text, trace_id, str(e))
|
||||
|
||||
# Warn if score is suspiciously low (likely parsing failure)
|
||||
if result.overall_score == 0 and not result.patterns:
|
||||
result.weaknesses.append("WARNING: Analysis may have failed - score is 0 with no patterns detected")
|
||||
# Try to extract a score from the response text as fallback
|
||||
fallback_score = self._extract_fallback_score(response_text)
|
||||
if fallback_score > 0:
|
||||
result.overall_score = fallback_score
|
||||
result.recommendations.append(f"Score extracted via fallback: {fallback_score}")
|
||||
|
||||
return result
|
||||
|
||||
def _fallback_parse_analysis(
|
||||
self,
|
||||
response_text: str,
|
||||
trace_id: str,
|
||||
error_msg: str,
|
||||
) -> AnalysisResult:
|
||||
"""Fallback parsing when JSON extraction fails."""
|
||||
import re
|
||||
|
||||
result = AnalysisResult(trace_id=trace_id)
|
||||
|
||||
# Try to extract score from text patterns like "Overall Score: 75" or "overall": 75
|
||||
score_patterns = [
|
||||
r'overall["\s:]+(\d+)',
|
||||
r'Overall Score[:\s]+(\d+)',
|
||||
r'"overall"[:\s]+(\d+)',
|
||||
r'Score[:\s]+(\d+)/100',
|
||||
]
|
||||
|
||||
for pattern in score_patterns:
|
||||
match = re.search(pattern, response_text, re.IGNORECASE)
|
||||
if match:
|
||||
result.overall_score = min(100, max(0, int(match.group(1))))
|
||||
break
|
||||
|
||||
# If still no score, use a neutral default (not 0)
|
||||
if result.overall_score == 0:
|
||||
result.overall_score = 50 # Neutral default instead of 0
|
||||
|
||||
result.recommendations = [
|
||||
f"Analysis parsing failed ({error_msg}). Using fallback extraction.",
|
||||
"Consider re-running analysis if results seem inconsistent."
|
||||
]
|
||||
result.weaknesses = ["JSON parsing failed - analysis may be incomplete"]
|
||||
|
||||
return result
|
||||
|
||||
def _extract_fallback_score(self, response_text: str) -> float:
|
||||
"""Extract a score from response text when JSON parsing fails."""
|
||||
import re
|
||||
|
||||
patterns = [
|
||||
r'overall["\s:]+(\d+)',
|
||||
r'Overall Score[:\s]+(\d+)',
|
||||
r'"overall"[:\s]+(\d+)',
|
||||
r'(\d+)/100',
|
||||
r'score[:\s]+(\d+)',
|
||||
]
|
||||
|
||||
for pattern in patterns:
|
||||
match = re.search(pattern, response_text, re.IGNORECASE)
|
||||
if match:
|
||||
score = int(match.group(1))
|
||||
if 0 <= score <= 100:
|
||||
return float(score)
|
||||
|
||||
return 0.0
|
||||
|
||||
|
||||
def format_analysis_report(analysis: AnalysisResult) -> str:
|
||||
"""Format an analysis result as a human-readable report."""
|
||||
lines = [
|
||||
"=" * 60,
|
||||
"REASONING TRACE ANALYSIS REPORT",
|
||||
"=" * 60,
|
||||
"",
|
||||
f"Overall Score: {analysis.overall_score}/100",
|
||||
"",
|
||||
"Scores:",
|
||||
f" - Reasoning Clarity: {analysis.reasoning_clarity}/100",
|
||||
f" - Goal Adherence: {analysis.goal_adherence}/100",
|
||||
f" - Tool Usage Quality: {analysis.tool_usage_quality}/100",
|
||||
f" - Error Recovery: {analysis.error_recovery}/100",
|
||||
"",
|
||||
]
|
||||
|
||||
if analysis.patterns:
|
||||
lines.append("Detected Patterns:")
|
||||
for p in analysis.patterns:
|
||||
lines.append(f"\n [{p.severity.value.upper()}] {p.type.value}")
|
||||
lines.append(f" {p.description}")
|
||||
lines.append(f" Suggestion: {p.suggestion}")
|
||||
|
||||
if analysis.strengths:
|
||||
lines.append("\nStrengths:")
|
||||
for s in analysis.strengths:
|
||||
lines.append(f" + {s}")
|
||||
|
||||
if analysis.weaknesses:
|
||||
lines.append("\nWeaknesses:")
|
||||
for w in analysis.weaknesses:
|
||||
lines.append(f" - {w}")
|
||||
|
||||
if analysis.recommendations:
|
||||
lines.append("\nRecommendations:")
|
||||
for i, r in enumerate(analysis.recommendations, 1):
|
||||
lines.append(f" {i}. {r}")
|
||||
|
||||
return "\n".join(lines)
|
||||
@@ -0,0 +1,417 @@
|
||||
"""
|
||||
TraceCapture: Wraps M2.1 API to capture interleaved thinking traces.
|
||||
|
||||
This module provides the core functionality for executing agent tasks
|
||||
through MiniMax M2.1 while capturing all reasoning traces for analysis.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Any, Callable
|
||||
|
||||
import anthropic
|
||||
|
||||
from reasoning_trace_optimizer.models import (
|
||||
ReasoningTrace,
|
||||
ThinkingBlock,
|
||||
ToolCall,
|
||||
)
|
||||
|
||||
|
||||
class TraceCapture:
|
||||
"""
|
||||
Captures reasoning traces from MiniMax M2.1's interleaved thinking.
|
||||
|
||||
This class wraps the Anthropic SDK configured for M2.1 and captures
|
||||
all thinking blocks, tool calls, and responses during agent execution.
|
||||
|
||||
Example:
|
||||
```python
|
||||
capture = TraceCapture()
|
||||
trace = capture.run(
|
||||
task="What's the weather in San Francisco?",
|
||||
tools=[weather_tool],
|
||||
tool_executor=execute_tool
|
||||
)
|
||||
print(f"Captured {len(trace.thinking_blocks)} thinking blocks")
|
||||
```
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api_key: str | None = None,
|
||||
base_url: str = "https://api.minimax.io/anthropic",
|
||||
model: str = "MiniMax-M2.1",
|
||||
):
|
||||
"""
|
||||
Initialize TraceCapture with M2.1 configuration.
|
||||
|
||||
Args:
|
||||
api_key: MiniMax API key (defaults to ANTHROPIC_API_KEY env var)
|
||||
base_url: API base URL (international or China endpoint)
|
||||
model: Model to use (MiniMax-M2.1, MiniMax-M2.1-lightning, MiniMax-M2)
|
||||
"""
|
||||
self.model = model
|
||||
self.client = anthropic.Anthropic(
|
||||
api_key=api_key or os.environ.get("ANTHROPIC_API_KEY"),
|
||||
base_url=base_url,
|
||||
)
|
||||
|
||||
def run(
|
||||
self,
|
||||
task: str,
|
||||
system_prompt: str = "You are a helpful assistant.",
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_executor: Callable[[str, dict], str] | None = None,
|
||||
max_turns: int = 10,
|
||||
max_tokens: int = 4096,
|
||||
) -> ReasoningTrace:
|
||||
"""
|
||||
Execute a task and capture the full reasoning trace.
|
||||
|
||||
Args:
|
||||
task: The user task/query to execute
|
||||
system_prompt: System prompt for the agent
|
||||
tools: List of tool definitions in Anthropic format
|
||||
tool_executor: Function to execute tool calls (name, input) -> result
|
||||
max_turns: Maximum conversation turns before stopping
|
||||
max_tokens: Maximum tokens per response
|
||||
|
||||
Returns:
|
||||
ReasoningTrace containing all thinking blocks, tool calls, and responses
|
||||
"""
|
||||
trace = ReasoningTrace(
|
||||
session_id=str(uuid.uuid4()),
|
||||
task=task,
|
||||
system_prompt=system_prompt,
|
||||
model=self.model,
|
||||
started_at=datetime.now(),
|
||||
)
|
||||
|
||||
messages = [{"role": "user", "content": task}]
|
||||
turn = 0
|
||||
|
||||
try:
|
||||
while turn < max_turns:
|
||||
# Build request parameters
|
||||
params = {
|
||||
"model": self.model,
|
||||
"max_tokens": max_tokens,
|
||||
"system": system_prompt,
|
||||
"messages": messages,
|
||||
}
|
||||
if tools:
|
||||
params["tools"] = tools
|
||||
|
||||
# Make API call
|
||||
response = self.client.messages.create(**params)
|
||||
|
||||
# Process response content blocks
|
||||
thinking_blocks, text_blocks, tool_use_blocks = self._process_response(
|
||||
response, turn, trace
|
||||
)
|
||||
|
||||
# If no tool calls, we're done
|
||||
if not tool_use_blocks:
|
||||
trace.final_response = (
|
||||
text_blocks[0].text if text_blocks else None
|
||||
)
|
||||
trace.success = True
|
||||
break
|
||||
|
||||
# Append assistant response to history (CRITICAL for M2.1)
|
||||
messages.append({"role": "assistant", "content": response.content})
|
||||
|
||||
# Execute tools and collect results
|
||||
tool_results = []
|
||||
for tool_block in tool_use_blocks:
|
||||
result = self._execute_tool(
|
||||
tool_block, tool_executor, turn, trace
|
||||
)
|
||||
tool_results.append(
|
||||
{
|
||||
"type": "tool_result",
|
||||
"tool_use_id": tool_block.id,
|
||||
"content": result,
|
||||
}
|
||||
)
|
||||
|
||||
# Add tool results to messages
|
||||
messages.append({"role": "user", "content": tool_results})
|
||||
|
||||
turn += 1
|
||||
trace.total_turns = turn
|
||||
|
||||
# Check if we hit max turns without completion
|
||||
if turn >= max_turns and not trace.success:
|
||||
trace.success = False
|
||||
trace.error = f"Reached maximum turns ({max_turns}) without completion"
|
||||
|
||||
except Exception as e:
|
||||
trace.success = False
|
||||
trace.error = str(e)
|
||||
|
||||
trace.completed_at = datetime.now()
|
||||
return trace
|
||||
|
||||
def _process_response(
|
||||
self,
|
||||
response: anthropic.types.Message,
|
||||
turn: int,
|
||||
trace: ReasoningTrace,
|
||||
) -> tuple[list, list, list]:
|
||||
"""Process response content blocks and update trace."""
|
||||
thinking_blocks = []
|
||||
text_blocks = []
|
||||
tool_use_blocks = []
|
||||
|
||||
for block in response.content:
|
||||
if block.type == "thinking":
|
||||
thinking = ThinkingBlock(
|
||||
content=block.thinking,
|
||||
turn_index=turn,
|
||||
signature=getattr(block, "signature", None),
|
||||
)
|
||||
trace.thinking_blocks.append(thinking)
|
||||
thinking_blocks.append(block)
|
||||
|
||||
elif block.type == "text":
|
||||
text_blocks.append(block)
|
||||
|
||||
elif block.type == "tool_use":
|
||||
tool_use_blocks.append(block)
|
||||
|
||||
# Update token count
|
||||
trace.total_tokens += response.usage.input_tokens + response.usage.output_tokens
|
||||
|
||||
return thinking_blocks, text_blocks, tool_use_blocks
|
||||
|
||||
def _execute_tool(
|
||||
self,
|
||||
tool_block: Any,
|
||||
executor: Callable[[str, dict], str] | None,
|
||||
turn: int,
|
||||
trace: ReasoningTrace,
|
||||
) -> str:
|
||||
"""Execute a tool call and record it in the trace."""
|
||||
tool_call = ToolCall(
|
||||
id=tool_block.id,
|
||||
name=tool_block.name,
|
||||
input=tool_block.input,
|
||||
turn_index=turn,
|
||||
)
|
||||
|
||||
try:
|
||||
if executor:
|
||||
result = executor(tool_block.name, tool_block.input)
|
||||
else:
|
||||
result = f"[Mock result for {tool_block.name}]"
|
||||
|
||||
tool_call.result = result
|
||||
tool_call.success = True
|
||||
|
||||
except Exception as e:
|
||||
result = f"Error: {str(e)}"
|
||||
tool_call.result = result
|
||||
tool_call.success = False
|
||||
tool_call.error = str(e)
|
||||
|
||||
trace.tool_calls.append(tool_call)
|
||||
|
||||
# Link thinking to tool call
|
||||
if trace.thinking_blocks:
|
||||
last_thinking = trace.thinking_blocks[-1]
|
||||
if last_thinking.turn_index == turn:
|
||||
last_thinking.following_action = f"tool_use:{tool_block.name}"
|
||||
|
||||
return result
|
||||
|
||||
def run_streaming(
|
||||
self,
|
||||
task: str,
|
||||
system_prompt: str = "You are a helpful assistant.",
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_executor: Callable[[str, dict], str] | None = None,
|
||||
max_turns: int = 10,
|
||||
max_tokens: int = 4096,
|
||||
on_thinking: Callable[[str], None] | None = None,
|
||||
on_text: Callable[[str], None] | None = None,
|
||||
on_tool_call: Callable[[str, dict], None] | None = None,
|
||||
on_error: Callable[[str], None] | None = None,
|
||||
) -> ReasoningTrace:
|
||||
"""
|
||||
Execute a task with streaming output and capture reasoning trace.
|
||||
|
||||
Similar to run() but streams thinking and text content in real-time
|
||||
via callback functions.
|
||||
|
||||
Note: For multi-turn tool interactions, the non-streaming run() method
|
||||
is recommended as it provides more reliable trace capture. Use this
|
||||
method when you need real-time display of thinking/text content.
|
||||
|
||||
Args:
|
||||
task: The user task/query to execute
|
||||
system_prompt: System prompt for the agent
|
||||
tools: List of tool definitions
|
||||
tool_executor: Function to execute tool calls
|
||||
max_turns: Maximum conversation turns
|
||||
max_tokens: Maximum tokens per response
|
||||
on_thinking: Callback for thinking content chunks
|
||||
on_text: Callback for text content chunks
|
||||
on_tool_call: Callback when tool is called (name, input)
|
||||
on_error: Callback when an error occurs (error message)
|
||||
|
||||
Returns:
|
||||
ReasoningTrace containing the full captured trace
|
||||
"""
|
||||
trace = ReasoningTrace(
|
||||
session_id=str(uuid.uuid4()),
|
||||
task=task,
|
||||
system_prompt=system_prompt,
|
||||
model=self.model,
|
||||
started_at=datetime.now(),
|
||||
)
|
||||
|
||||
messages = [{"role": "user", "content": task}]
|
||||
turn = 0
|
||||
|
||||
try:
|
||||
while turn < max_turns:
|
||||
params = {
|
||||
"model": self.model,
|
||||
"max_tokens": max_tokens,
|
||||
"system": system_prompt,
|
||||
"messages": messages,
|
||||
"stream": True,
|
||||
}
|
||||
if tools:
|
||||
params["tools"] = tools
|
||||
|
||||
# Collect streamed content
|
||||
thinking_buffer = ""
|
||||
text_buffer = ""
|
||||
tool_use_blocks = []
|
||||
current_content = []
|
||||
|
||||
with self.client.messages.stream(**params) as stream:
|
||||
for event in stream:
|
||||
if event.type == "content_block_start":
|
||||
if hasattr(event, "content_block"):
|
||||
current_content.append(event.content_block)
|
||||
|
||||
elif event.type == "content_block_delta":
|
||||
if hasattr(event, "delta"):
|
||||
if event.delta.type == "thinking_delta":
|
||||
chunk = event.delta.thinking
|
||||
thinking_buffer += chunk
|
||||
if on_thinking:
|
||||
on_thinking(chunk)
|
||||
|
||||
elif event.delta.type == "text_delta":
|
||||
chunk = event.delta.text
|
||||
text_buffer += chunk
|
||||
if on_text:
|
||||
on_text(chunk)
|
||||
|
||||
# Get final message for tool_use blocks
|
||||
final_message = stream.get_final_message()
|
||||
for block in final_message.content:
|
||||
if block.type == "tool_use":
|
||||
tool_use_blocks.append(block)
|
||||
if on_tool_call:
|
||||
on_tool_call(block.name, block.input)
|
||||
|
||||
# Record thinking block
|
||||
if thinking_buffer:
|
||||
trace.thinking_blocks.append(
|
||||
ThinkingBlock(
|
||||
content=thinking_buffer,
|
||||
turn_index=turn,
|
||||
)
|
||||
)
|
||||
|
||||
# Update tokens
|
||||
trace.total_tokens += (
|
||||
final_message.usage.input_tokens + final_message.usage.output_tokens
|
||||
)
|
||||
|
||||
# If no tool calls, we're done
|
||||
if not tool_use_blocks:
|
||||
trace.final_response = text_buffer or None
|
||||
trace.success = True
|
||||
break
|
||||
|
||||
# Append to history
|
||||
messages.append({"role": "assistant", "content": final_message.content})
|
||||
|
||||
# Execute tools
|
||||
tool_results = []
|
||||
for tool_block in tool_use_blocks:
|
||||
result = self._execute_tool(tool_block, tool_executor, turn, trace)
|
||||
tool_results.append(
|
||||
{
|
||||
"type": "tool_result",
|
||||
"tool_use_id": tool_block.id,
|
||||
"content": result,
|
||||
}
|
||||
)
|
||||
|
||||
messages.append({"role": "user", "content": tool_results})
|
||||
turn += 1
|
||||
trace.total_turns = turn
|
||||
|
||||
if turn >= max_turns and not trace.success:
|
||||
trace.success = False
|
||||
trace.error = f"Reached maximum turns ({max_turns})"
|
||||
|
||||
except Exception as e:
|
||||
trace.success = False
|
||||
trace.error = str(e)
|
||||
if on_error:
|
||||
on_error(str(e))
|
||||
|
||||
trace.completed_at = datetime.now()
|
||||
return trace
|
||||
|
||||
|
||||
def format_trace_for_display(trace: ReasoningTrace) -> str:
|
||||
"""Format a reasoning trace for human-readable display."""
|
||||
lines = [
|
||||
f"Session: {trace.session_id}",
|
||||
f"Task: {trace.task}",
|
||||
f"Model: {trace.model}",
|
||||
f"Status: {'Success' if trace.success else 'Failed'}",
|
||||
f"Turns: {trace.total_turns}",
|
||||
f"Tokens: {trace.total_tokens}",
|
||||
"",
|
||||
"=" * 60,
|
||||
"REASONING TRACE",
|
||||
"=" * 60,
|
||||
]
|
||||
|
||||
for i, thinking in enumerate(trace.thinking_blocks):
|
||||
lines.append(f"\n[Turn {thinking.turn_index}] Thinking:")
|
||||
lines.append("-" * 40)
|
||||
lines.append(thinking.content[:500] + "..." if len(thinking.content) > 500 else thinking.content)
|
||||
|
||||
# Show tool calls at this turn
|
||||
turn_tools = trace.get_tool_calls_at_turn(thinking.turn_index)
|
||||
for tool in turn_tools:
|
||||
lines.append(f"\n Tool: {tool.name}({json.dumps(tool.input)})")
|
||||
lines.append(f" Result: {tool.result[:100]}..." if tool.result and len(tool.result) > 100 else f" Result: {tool.result}")
|
||||
|
||||
if trace.final_response:
|
||||
lines.append("\n" + "=" * 60)
|
||||
lines.append("FINAL RESPONSE")
|
||||
lines.append("=" * 60)
|
||||
lines.append(trace.final_response)
|
||||
|
||||
if trace.error:
|
||||
lines.append("\n" + "=" * 60)
|
||||
lines.append("ERROR")
|
||||
lines.append("=" * 60)
|
||||
lines.append(trace.error)
|
||||
|
||||
return "\n".join(lines)
|
||||
@@ -0,0 +1,271 @@
|
||||
"""
|
||||
CLI interface for Reasoning Trace Optimizer.
|
||||
|
||||
Provides command-line access to the optimization tools.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from rich.console import Console
|
||||
|
||||
from reasoning_trace_optimizer.analyzer import TraceAnalyzer, format_analysis_report
|
||||
from reasoning_trace_optimizer.capture import TraceCapture, format_trace_for_display
|
||||
from reasoning_trace_optimizer.loop import OptimizationLoop, LoopConfig
|
||||
from reasoning_trace_optimizer.skill_generator import SkillGenerator
|
||||
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
def cmd_capture(args: argparse.Namespace) -> None:
|
||||
"""Run a task and capture reasoning trace."""
|
||||
capture = TraceCapture(
|
||||
api_key=args.api_key,
|
||||
base_url=args.base_url,
|
||||
model=args.model,
|
||||
)
|
||||
|
||||
console.print(f"[cyan]Capturing trace for task: {args.task}[/cyan]")
|
||||
|
||||
trace = capture.run(
|
||||
task=args.task,
|
||||
system_prompt=args.system_prompt or "You are a helpful assistant.",
|
||||
max_turns=args.max_turns,
|
||||
)
|
||||
|
||||
# Output trace
|
||||
output = format_trace_for_display(trace)
|
||||
if args.output:
|
||||
Path(args.output).write_text(output)
|
||||
console.print(f"[green]Trace saved to: {args.output}[/green]")
|
||||
else:
|
||||
console.print(output)
|
||||
|
||||
|
||||
def cmd_analyze(args: argparse.Namespace) -> None:
|
||||
"""Analyze a captured reasoning trace."""
|
||||
# For now, run capture + analyze together
|
||||
# In future, could load trace from file
|
||||
|
||||
capture = TraceCapture(
|
||||
api_key=args.api_key,
|
||||
base_url=args.base_url,
|
||||
model=args.model,
|
||||
)
|
||||
analyzer = TraceAnalyzer(
|
||||
api_key=args.api_key,
|
||||
base_url=args.base_url,
|
||||
model=args.model,
|
||||
)
|
||||
|
||||
console.print(f"[cyan]Capturing and analyzing: {args.task}[/cyan]")
|
||||
|
||||
trace = capture.run(
|
||||
task=args.task,
|
||||
system_prompt=args.system_prompt or "You are a helpful assistant.",
|
||||
)
|
||||
|
||||
analysis = analyzer.analyze(trace)
|
||||
|
||||
# Output analysis
|
||||
output = format_analysis_report(analysis)
|
||||
if args.output:
|
||||
Path(args.output).write_text(output)
|
||||
console.print(f"[green]Analysis saved to: {args.output}[/green]")
|
||||
else:
|
||||
console.print(output)
|
||||
|
||||
|
||||
def cmd_optimize(args: argparse.Namespace) -> None:
|
||||
"""Run full optimization loop."""
|
||||
config = LoopConfig(
|
||||
max_iterations=args.max_iterations,
|
||||
convergence_threshold=args.convergence_threshold,
|
||||
min_score_threshold=args.min_score,
|
||||
save_artifacts=True,
|
||||
artifacts_dir=args.artifacts_dir,
|
||||
verbose=True,
|
||||
)
|
||||
|
||||
loop = OptimizationLoop(
|
||||
config=config,
|
||||
api_key=args.api_key,
|
||||
base_url=args.base_url,
|
||||
model=args.model,
|
||||
)
|
||||
|
||||
console.print(f"[cyan]Starting optimization for: {args.task}[/cyan]")
|
||||
|
||||
result = loop.run(
|
||||
task=args.task,
|
||||
initial_prompt=args.system_prompt or "You are a helpful assistant.",
|
||||
)
|
||||
|
||||
# Output final prompt
|
||||
if args.output:
|
||||
Path(args.output).write_text(result.final_prompt)
|
||||
console.print(f"[green]Optimized prompt saved to: {args.output}[/green]")
|
||||
|
||||
# Generate skill if requested
|
||||
if args.generate_skill:
|
||||
generator = SkillGenerator(
|
||||
api_key=args.api_key,
|
||||
base_url=args.base_url,
|
||||
model=args.model,
|
||||
)
|
||||
skill_path = generator.generate(
|
||||
result=result,
|
||||
skill_name=args.skill_name or "optimized-agent",
|
||||
output_dir=args.skills_dir,
|
||||
)
|
||||
console.print(f"[green]Generated skill at: {skill_path}[/green]")
|
||||
|
||||
|
||||
def cmd_generate_skill(args: argparse.Namespace) -> None:
|
||||
"""Generate a skill from optimization artifacts."""
|
||||
# Load summary from artifacts
|
||||
artifacts_dir = Path(args.artifacts_dir)
|
||||
summary_path = artifacts_dir / "summary.json"
|
||||
|
||||
if not summary_path.exists():
|
||||
console.print("[red]Error: No optimization summary found. Run optimize first.[/red]")
|
||||
sys.exit(1)
|
||||
|
||||
with open(summary_path) as f:
|
||||
summary = json.load(f)
|
||||
|
||||
# Create minimal loop result from summary
|
||||
from reasoning_trace_optimizer.models import LoopResult, LoopIteration, ReasoningTrace, AnalysisResult
|
||||
|
||||
# Load final prompt
|
||||
final_prompt_path = artifacts_dir / "final_prompt.txt"
|
||||
final_prompt = final_prompt_path.read_text() if final_prompt_path.exists() else ""
|
||||
|
||||
result = LoopResult(
|
||||
task=summary.get("task", "Unknown task"),
|
||||
final_prompt=final_prompt,
|
||||
total_iterations=summary.get("total_iterations", 0),
|
||||
initial_score=summary.get("initial_score", 0),
|
||||
final_score=summary.get("final_score", 0),
|
||||
improvement_percentage=summary.get("improvement_percentage", 0),
|
||||
converged=summary.get("converged", False),
|
||||
)
|
||||
|
||||
generator = SkillGenerator(
|
||||
api_key=args.api_key,
|
||||
base_url=args.base_url,
|
||||
model=args.model,
|
||||
)
|
||||
|
||||
skill_path = generator.generate(
|
||||
result=result,
|
||||
skill_name=args.skill_name,
|
||||
output_dir=args.output_dir,
|
||||
)
|
||||
|
||||
console.print(f"[green]Generated skill at: {skill_path}[/green]")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Main CLI entry point."""
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="rto",
|
||||
description="Reasoning Trace Optimizer - Debug and optimize AI agents using M2.1's interleaved thinking",
|
||||
)
|
||||
|
||||
# Global arguments
|
||||
parser.add_argument(
|
||||
"--api-key",
|
||||
help="MiniMax API key (or set ANTHROPIC_API_KEY env var)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--base-url",
|
||||
default="https://api.minimax.io/anthropic",
|
||||
help="API base URL",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--model",
|
||||
default="MiniMax-M2.1",
|
||||
choices=["MiniMax-M2.1", "MiniMax-M2.1-lightning", "MiniMax-M2"],
|
||||
help="Model to use",
|
||||
)
|
||||
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
# Capture command
|
||||
capture_parser = subparsers.add_parser(
|
||||
"capture",
|
||||
help="Capture reasoning trace for a task",
|
||||
)
|
||||
capture_parser.add_argument("task", help="Task to execute")
|
||||
capture_parser.add_argument("--system-prompt", "-s", help="System prompt")
|
||||
capture_parser.add_argument("--max-turns", type=int, default=10)
|
||||
capture_parser.add_argument("--output", "-o", help="Output file path")
|
||||
capture_parser.set_defaults(func=cmd_capture)
|
||||
|
||||
# Analyze command
|
||||
analyze_parser = subparsers.add_parser(
|
||||
"analyze",
|
||||
help="Capture and analyze reasoning trace",
|
||||
)
|
||||
analyze_parser.add_argument("task", help="Task to analyze")
|
||||
analyze_parser.add_argument("--system-prompt", "-s", help="System prompt")
|
||||
analyze_parser.add_argument("--output", "-o", help="Output file path")
|
||||
analyze_parser.set_defaults(func=cmd_analyze)
|
||||
|
||||
# Optimize command
|
||||
optimize_parser = subparsers.add_parser(
|
||||
"optimize",
|
||||
help="Run full optimization loop",
|
||||
)
|
||||
optimize_parser.add_argument("task", help="Task to optimize for")
|
||||
optimize_parser.add_argument("--system-prompt", "-s", help="Initial system prompt")
|
||||
optimize_parser.add_argument("--max-iterations", type=int, default=5)
|
||||
optimize_parser.add_argument("--convergence-threshold", type=float, default=5.0)
|
||||
optimize_parser.add_argument("--min-score", type=float, default=80.0)
|
||||
optimize_parser.add_argument(
|
||||
"--artifacts-dir",
|
||||
default="./optimization_artifacts",
|
||||
help="Directory for artifacts",
|
||||
)
|
||||
optimize_parser.add_argument("--output", "-o", help="Output file for final prompt")
|
||||
optimize_parser.add_argument(
|
||||
"--generate-skill",
|
||||
action="store_true",
|
||||
help="Generate Agent Skill from results",
|
||||
)
|
||||
optimize_parser.add_argument("--skill-name", help="Name for generated skill")
|
||||
optimize_parser.add_argument(
|
||||
"--skills-dir",
|
||||
default="./generated_skills",
|
||||
help="Directory for generated skills",
|
||||
)
|
||||
optimize_parser.set_defaults(func=cmd_optimize)
|
||||
|
||||
# Generate skill command
|
||||
skill_parser = subparsers.add_parser(
|
||||
"generate-skill",
|
||||
help="Generate skill from optimization artifacts",
|
||||
)
|
||||
skill_parser.add_argument("skill_name", help="Name for the skill")
|
||||
skill_parser.add_argument(
|
||||
"--artifacts-dir",
|
||||
default="./optimization_artifacts",
|
||||
help="Directory with optimization artifacts",
|
||||
)
|
||||
skill_parser.add_argument(
|
||||
"--output-dir",
|
||||
default="./generated_skills",
|
||||
help="Output directory for skill",
|
||||
)
|
||||
skill_parser.set_defaults(func=cmd_generate_skill)
|
||||
|
||||
args = parser.parse_args()
|
||||
args.func(args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,468 @@
|
||||
"""
|
||||
OptimizationLoop: Orchestrates the full capture → analyze → improve → re-run cycle.
|
||||
|
||||
This is the main entry point for automated prompt optimization,
|
||||
running iterative improvements until convergence or max iterations.
|
||||
"""
|
||||
|
||||
import json
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable
|
||||
|
||||
from rich.console import Console
|
||||
from rich.panel import Panel
|
||||
from rich.progress import Progress, SpinnerColumn, TextColumn
|
||||
from rich.table import Table
|
||||
|
||||
from reasoning_trace_optimizer.analyzer import TraceAnalyzer, format_analysis_report
|
||||
from reasoning_trace_optimizer.capture import TraceCapture, format_trace_for_display
|
||||
from reasoning_trace_optimizer.models import (
|
||||
AnalysisResult,
|
||||
LoopIteration,
|
||||
LoopResult,
|
||||
OptimizationResult,
|
||||
ReasoningTrace,
|
||||
)
|
||||
from reasoning_trace_optimizer.optimizer import PromptOptimizer, format_optimization_report
|
||||
|
||||
|
||||
console = Console()
|
||||
|
||||
|
||||
@dataclass
|
||||
class LoopConfig:
|
||||
"""Configuration for the optimization loop."""
|
||||
|
||||
max_iterations: int = 5
|
||||
convergence_threshold: float = 3.0 # Stop if improvement < this %
|
||||
min_score_threshold: float = 75.0 # Stop if score >= this (realistic for complex tasks)
|
||||
regression_threshold: float = 8.0 # Rollback if score drops by this much
|
||||
|
||||
# Scoring weights
|
||||
success_weight: float = 0.4
|
||||
score_weight: float = 0.4
|
||||
error_weight: float = 0.2
|
||||
|
||||
# Optimization behavior
|
||||
use_best_prompt: bool = True # Use best performing prompt, not final
|
||||
max_prompt_growth: float = 5.0 # Max ratio of new prompt length to original
|
||||
|
||||
# Output options
|
||||
save_artifacts: bool = True
|
||||
artifacts_dir: str = "./optimization_artifacts"
|
||||
verbose: bool = True
|
||||
|
||||
|
||||
class OptimizationLoop:
|
||||
"""
|
||||
Orchestrates the full optimization cycle.
|
||||
|
||||
Runs iterative loops of:
|
||||
1. Execute agent with current prompt
|
||||
2. Capture reasoning trace
|
||||
3. Analyze trace for issues
|
||||
4. Generate optimized prompt
|
||||
5. Repeat until convergence
|
||||
|
||||
Example:
|
||||
```python
|
||||
loop = OptimizationLoop()
|
||||
result = loop.run(
|
||||
task="Search for Python tutorials and summarize them",
|
||||
initial_prompt="You are a helpful research assistant.",
|
||||
tools=[search_tool],
|
||||
tool_executor=execute_search
|
||||
)
|
||||
|
||||
print(f"Improved from {result.initial_score} to {result.final_score}")
|
||||
print(f"Final prompt:\\n{result.final_prompt}")
|
||||
```
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: LoopConfig | None = None,
|
||||
api_key: str | None = None,
|
||||
base_url: str = "https://api.minimax.io/anthropic",
|
||||
model: str = "MiniMax-M2.1",
|
||||
):
|
||||
"""
|
||||
Initialize the optimization loop.
|
||||
|
||||
Args:
|
||||
config: Loop configuration
|
||||
api_key: MiniMax API key
|
||||
base_url: API endpoint
|
||||
model: Model to use for all components
|
||||
"""
|
||||
self.config = config or LoopConfig()
|
||||
|
||||
# Initialize components with same configuration
|
||||
self.capture = TraceCapture(api_key=api_key, base_url=base_url, model=model)
|
||||
self.analyzer = TraceAnalyzer(api_key=api_key, base_url=base_url, model=model)
|
||||
self.optimizer = PromptOptimizer(api_key=api_key, base_url=base_url, model=model)
|
||||
|
||||
# Create artifacts directory
|
||||
if self.config.save_artifacts:
|
||||
Path(self.config.artifacts_dir).mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def run(
|
||||
self,
|
||||
task: str,
|
||||
initial_prompt: str,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_executor: Callable[[str, dict], str] | None = None,
|
||||
on_iteration: Callable[[LoopIteration], None] | None = None,
|
||||
) -> LoopResult:
|
||||
"""
|
||||
Run the full optimization loop.
|
||||
|
||||
Args:
|
||||
task: The task to optimize for
|
||||
initial_prompt: Starting system prompt
|
||||
tools: Tool definitions for the agent
|
||||
tool_executor: Function to execute tool calls
|
||||
on_iteration: Optional callback after each iteration
|
||||
|
||||
Returns:
|
||||
LoopResult with all iterations and final optimized prompt
|
||||
"""
|
||||
result = LoopResult(task=task, final_prompt=initial_prompt)
|
||||
current_prompt = initial_prompt
|
||||
|
||||
# Track best performing iteration
|
||||
best_score = 0.0
|
||||
best_prompt = initial_prompt
|
||||
best_iteration = 0
|
||||
consecutive_regressions = 0
|
||||
|
||||
if self.config.verbose:
|
||||
console.print(Panel(
|
||||
f"[bold]Starting Optimization Loop[/bold]\n\n"
|
||||
f"Task: {task}\n"
|
||||
f"Max Iterations: {self.config.max_iterations}\n"
|
||||
f"Convergence Threshold: {self.config.convergence_threshold}%",
|
||||
title="Reasoning Trace Optimizer"
|
||||
))
|
||||
|
||||
with Progress(
|
||||
SpinnerColumn(),
|
||||
TextColumn("[progress.description]{task.description}"),
|
||||
console=console,
|
||||
disable=not self.config.verbose,
|
||||
) as progress:
|
||||
|
||||
for i in range(self.config.max_iterations):
|
||||
task_id = progress.add_task(f"Iteration {i + 1}/{self.config.max_iterations}", total=4)
|
||||
|
||||
# Step 1: Capture trace
|
||||
progress.update(task_id, description=f"[cyan]Iteration {i + 1}: Capturing trace...")
|
||||
trace = self.capture.run(
|
||||
task=task,
|
||||
system_prompt=current_prompt,
|
||||
tools=tools,
|
||||
tool_executor=tool_executor,
|
||||
)
|
||||
progress.advance(task_id)
|
||||
|
||||
# Step 2: Analyze trace
|
||||
progress.update(task_id, description=f"[cyan]Iteration {i + 1}: Analyzing trace...")
|
||||
analysis = self.analyzer.analyze(trace)
|
||||
progress.advance(task_id)
|
||||
|
||||
# Calculate iteration score
|
||||
iteration_score = self._calculate_score(trace, analysis)
|
||||
|
||||
# Record initial score
|
||||
if i == 0:
|
||||
result.initial_score = iteration_score
|
||||
best_score = iteration_score
|
||||
best_prompt = current_prompt
|
||||
|
||||
# Step 3: Check convergence
|
||||
should_continue, reason = self._check_convergence(
|
||||
iteration=i,
|
||||
score=iteration_score,
|
||||
prev_score=result.iterations[-1].analysis.overall_score if result.iterations else 0,
|
||||
best_score=best_score,
|
||||
consecutive_regressions=consecutive_regressions,
|
||||
)
|
||||
|
||||
# Step 4: Optimize if continuing
|
||||
optimization = None
|
||||
if should_continue:
|
||||
progress.update(task_id, description=f"[cyan]Iteration {i + 1}: Optimizing prompt...")
|
||||
optimization = self.optimizer.optimize(
|
||||
original_prompt=current_prompt,
|
||||
analysis=analysis,
|
||||
trace=trace,
|
||||
)
|
||||
|
||||
# Check for excessive prompt growth
|
||||
new_prompt = optimization.optimized_prompt
|
||||
if len(new_prompt) > len(initial_prompt) * self.config.max_prompt_growth:
|
||||
if self.config.verbose:
|
||||
console.print(f"[yellow]Warning: Prompt grew too large ({len(new_prompt)} chars), limiting growth[/yellow]")
|
||||
# Keep the current prompt instead of the bloated one
|
||||
new_prompt = current_prompt
|
||||
|
||||
current_prompt = new_prompt
|
||||
progress.advance(task_id)
|
||||
|
||||
# Track best performing iteration AFTER optimization
|
||||
# This ensures we capture the optimized prompt, not the input prompt
|
||||
if iteration_score > best_score:
|
||||
best_score = iteration_score
|
||||
# Use the optimized prompt if available, otherwise the current prompt
|
||||
if optimization and optimization.optimized_prompt != initial_prompt:
|
||||
best_prompt = optimization.optimized_prompt
|
||||
else:
|
||||
best_prompt = current_prompt
|
||||
best_iteration = i + 1
|
||||
consecutive_regressions = 0
|
||||
elif iteration_score < best_score - self.config.regression_threshold:
|
||||
consecutive_regressions += 1
|
||||
if self.config.verbose:
|
||||
console.print(f"[yellow]Warning: Score regressed from {best_score:.1f} to {iteration_score:.1f}[/yellow]")
|
||||
|
||||
# Record iteration
|
||||
iteration = LoopIteration(
|
||||
iteration=i + 1,
|
||||
trace=trace,
|
||||
analysis=analysis,
|
||||
optimization=optimization,
|
||||
task_completed=trace.success or False,
|
||||
error_count=len([tc for tc in trace.tool_calls if not tc.success]),
|
||||
token_usage=trace.total_tokens,
|
||||
)
|
||||
result.iterations.append(iteration)
|
||||
|
||||
# Callback
|
||||
if on_iteration:
|
||||
on_iteration(iteration)
|
||||
|
||||
# Print iteration summary
|
||||
if self.config.verbose:
|
||||
self._print_iteration_summary(iteration)
|
||||
|
||||
# Save artifacts
|
||||
if self.config.save_artifacts:
|
||||
self._save_iteration_artifacts(iteration, i + 1)
|
||||
|
||||
# Check if we should stop
|
||||
if not should_continue:
|
||||
if self.config.verbose:
|
||||
console.print(f"\n[green]Stopping: {reason}[/green]")
|
||||
result.converged = True
|
||||
break
|
||||
|
||||
progress.remove_task(task_id)
|
||||
|
||||
# Finalize result - use best prompt if configured
|
||||
if self.config.use_best_prompt and best_score > result.iterations[-1].analysis.overall_score:
|
||||
result.final_prompt = best_prompt
|
||||
result.final_score = best_score
|
||||
if self.config.verbose:
|
||||
console.print(f"[green]Using best prompt from iteration {best_iteration} (score: {best_score:.1f})[/green]")
|
||||
else:
|
||||
result.final_prompt = current_prompt
|
||||
result.final_score = result.iterations[-1].analysis.overall_score if result.iterations else 0
|
||||
|
||||
result.total_iterations = len(result.iterations)
|
||||
result.improvement_percentage = (
|
||||
(result.final_score - result.initial_score) / max(result.initial_score, 1) * 100
|
||||
)
|
||||
|
||||
# Warn if prompt was never successfully optimized
|
||||
if result.final_prompt == initial_prompt:
|
||||
if self.config.verbose:
|
||||
console.print(
|
||||
"[yellow]Warning: Final prompt unchanged from initial. "
|
||||
"Optimization may have failed to parse model responses.[/yellow]"
|
||||
)
|
||||
# Check if any iteration actually produced a different prompt
|
||||
any_optimized = any(
|
||||
i.optimization and i.optimization.optimized_prompt != initial_prompt
|
||||
for i in result.iterations
|
||||
if i.optimization
|
||||
)
|
||||
if not any_optimized:
|
||||
console.print(
|
||||
"[yellow]No successful prompt optimizations were extracted. "
|
||||
"Check artifacts for raw optimizer responses.[/yellow]"
|
||||
)
|
||||
|
||||
# Print final summary
|
||||
if self.config.verbose:
|
||||
self._print_final_summary(result)
|
||||
|
||||
# Save final artifacts
|
||||
if self.config.save_artifacts:
|
||||
self._save_final_artifacts(result)
|
||||
|
||||
return result
|
||||
|
||||
def run_single(
|
||||
self,
|
||||
task: str,
|
||||
prompt: str,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_executor: Callable[[str, dict], str] | None = None,
|
||||
) -> tuple[ReasoningTrace, AnalysisResult]:
|
||||
"""
|
||||
Run a single capture + analysis cycle (no optimization).
|
||||
|
||||
Useful for debugging or when you just want analysis without
|
||||
automatic optimization.
|
||||
|
||||
Returns:
|
||||
Tuple of (trace, analysis)
|
||||
"""
|
||||
trace = self.capture.run(
|
||||
task=task,
|
||||
system_prompt=prompt,
|
||||
tools=tools,
|
||||
tool_executor=tool_executor,
|
||||
)
|
||||
analysis = self.analyzer.analyze(trace)
|
||||
return trace, analysis
|
||||
|
||||
def _calculate_score(
|
||||
self,
|
||||
trace: ReasoningTrace,
|
||||
analysis: AnalysisResult,
|
||||
) -> float:
|
||||
"""Calculate weighted score from trace and analysis."""
|
||||
success_score = 100 if trace.success else 0
|
||||
error_penalty = len([tc for tc in trace.tool_calls if not tc.success]) * 10
|
||||
|
||||
weighted = (
|
||||
success_score * self.config.success_weight
|
||||
+ analysis.overall_score * self.config.score_weight
|
||||
- error_penalty * self.config.error_weight
|
||||
)
|
||||
|
||||
return max(0, min(100, weighted))
|
||||
|
||||
def _check_convergence(
|
||||
self,
|
||||
iteration: int,
|
||||
score: float,
|
||||
prev_score: float,
|
||||
best_score: float = 0.0,
|
||||
consecutive_regressions: int = 0,
|
||||
) -> tuple[bool, str]:
|
||||
"""Check if optimization should continue."""
|
||||
# Check score threshold
|
||||
if score >= self.config.min_score_threshold:
|
||||
return False, f"Score {score:.1f} >= threshold {self.config.min_score_threshold}"
|
||||
|
||||
# Check for consecutive regressions (stop if we've regressed twice in a row)
|
||||
if consecutive_regressions >= 2:
|
||||
return False, f"Consecutive regressions detected (best was {best_score:.1f})"
|
||||
|
||||
# Check improvement threshold (after first iteration)
|
||||
if iteration > 0:
|
||||
improvement = score - prev_score
|
||||
if abs(improvement) < self.config.convergence_threshold and score >= prev_score:
|
||||
return False, f"Converged (improvement {improvement:.1f}% < threshold)"
|
||||
|
||||
# Check max iterations
|
||||
if iteration >= self.config.max_iterations - 1:
|
||||
return False, f"Reached max iterations ({self.config.max_iterations})"
|
||||
|
||||
return True, ""
|
||||
|
||||
def _print_iteration_summary(self, iteration: LoopIteration) -> None:
|
||||
"""Print summary of an iteration."""
|
||||
table = Table(title=f"Iteration {iteration.iteration} Summary")
|
||||
table.add_column("Metric", style="cyan")
|
||||
table.add_column("Value", style="green")
|
||||
|
||||
table.add_row("Task Completed", "Yes" if iteration.task_completed else "No")
|
||||
table.add_row("Overall Score", f"{iteration.analysis.overall_score:.1f}/100")
|
||||
table.add_row("Patterns Found", str(len(iteration.analysis.patterns)))
|
||||
table.add_row("Tool Errors", str(iteration.error_count))
|
||||
table.add_row("Token Usage", str(iteration.token_usage))
|
||||
|
||||
if iteration.optimization:
|
||||
table.add_row(
|
||||
"Predicted Improvement",
|
||||
f"{iteration.optimization.predicted_improvement}%"
|
||||
)
|
||||
|
||||
console.print(table)
|
||||
|
||||
def _print_final_summary(self, result: LoopResult) -> None:
|
||||
"""Print final optimization summary."""
|
||||
console.print("\n")
|
||||
panel_content = (
|
||||
f"[bold]Iterations:[/bold] {result.total_iterations}\n"
|
||||
f"[bold]Converged:[/bold] {'Yes' if result.converged else 'No'}\n"
|
||||
f"[bold]Initial Score:[/bold] {result.initial_score:.1f}\n"
|
||||
f"[bold]Final Score:[/bold] {result.final_score:.1f}\n"
|
||||
f"[bold]Improvement:[/bold] {result.improvement_percentage:+.1f}%"
|
||||
)
|
||||
console.print(Panel(panel_content, title="[green]Optimization Complete[/green]"))
|
||||
|
||||
def _save_iteration_artifacts(self, iteration: LoopIteration, num: int) -> None:
|
||||
"""Save iteration artifacts to disk."""
|
||||
base_path = Path(self.config.artifacts_dir) / f"iteration_{num}"
|
||||
base_path.mkdir(exist_ok=True)
|
||||
|
||||
# Save trace
|
||||
with open(base_path / "trace.txt", "w") as f:
|
||||
f.write(format_trace_for_display(iteration.trace))
|
||||
|
||||
# Save analysis
|
||||
with open(base_path / "analysis.txt", "w") as f:
|
||||
f.write(format_analysis_report(iteration.analysis))
|
||||
|
||||
# Save optimization if present
|
||||
if iteration.optimization:
|
||||
with open(base_path / "optimization.txt", "w") as f:
|
||||
f.write(format_optimization_report(iteration.optimization))
|
||||
|
||||
with open(base_path / "optimized_prompt.txt", "w") as f:
|
||||
f.write(iteration.optimization.optimized_prompt)
|
||||
|
||||
def _save_final_artifacts(self, result: LoopResult) -> None:
|
||||
"""Save final optimization artifacts."""
|
||||
base_path = Path(self.config.artifacts_dir)
|
||||
|
||||
# Save final prompt
|
||||
with open(base_path / "final_prompt.txt", "w") as f:
|
||||
f.write(result.final_prompt)
|
||||
|
||||
# Save summary JSON
|
||||
summary = {
|
||||
"task": result.task,
|
||||
"total_iterations": result.total_iterations,
|
||||
"converged": result.converged,
|
||||
"initial_score": result.initial_score,
|
||||
"final_score": result.final_score,
|
||||
"improvement_percentage": result.improvement_percentage,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
}
|
||||
with open(base_path / "summary.json", "w") as f:
|
||||
json.dump(summary, f, indent=2)
|
||||
|
||||
|
||||
def run_quick_optimization(
|
||||
task: str,
|
||||
initial_prompt: str,
|
||||
tools: list[dict[str, Any]] | None = None,
|
||||
tool_executor: Callable[[str, dict], str] | None = None,
|
||||
max_iterations: int = 3,
|
||||
) -> str:
|
||||
"""
|
||||
Quick helper function for one-shot optimization.
|
||||
|
||||
Returns the optimized prompt directly.
|
||||
"""
|
||||
config = LoopConfig(max_iterations=max_iterations, verbose=False)
|
||||
loop = OptimizationLoop(config=config)
|
||||
result = loop.run(task, initial_prompt, tools, tool_executor)
|
||||
return result.final_prompt
|
||||
@@ -0,0 +1,193 @@
|
||||
"""
|
||||
Core data models for reasoning trace optimization.
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
|
||||
|
||||
class PatternType(Enum):
|
||||
"""Types of patterns detected in reasoning traces."""
|
||||
|
||||
CONTEXT_DEGRADATION = "context_degradation"
|
||||
TOOL_CONFUSION = "tool_confusion"
|
||||
INSTRUCTION_DRIFT = "instruction_drift"
|
||||
HALLUCINATION = "hallucination"
|
||||
INCOMPLETE_REASONING = "incomplete_reasoning"
|
||||
TOOL_MISUSE = "tool_misuse"
|
||||
GOAL_ABANDONMENT = "goal_abandonment"
|
||||
CIRCULAR_REASONING = "circular_reasoning"
|
||||
PREMATURE_CONCLUSION = "premature_conclusion"
|
||||
MISSING_VALIDATION = "missing_validation"
|
||||
|
||||
|
||||
class Severity(Enum):
|
||||
"""Severity levels for detected patterns."""
|
||||
|
||||
LOW = "low"
|
||||
MEDIUM = "medium"
|
||||
HIGH = "high"
|
||||
CRITICAL = "critical"
|
||||
|
||||
|
||||
@dataclass
|
||||
class ThinkingBlock:
|
||||
"""A single thinking/reasoning block from the model."""
|
||||
|
||||
content: str
|
||||
turn_index: int
|
||||
timestamp: datetime = field(default_factory=datetime.now)
|
||||
token_count: int = 0
|
||||
signature: str | None = None # M2.1 thinking signature
|
||||
|
||||
# Context at time of thinking
|
||||
preceding_tool_call: str | None = None
|
||||
preceding_tool_result: str | None = None
|
||||
following_action: str | None = None # tool_use, text, or end_turn
|
||||
|
||||
|
||||
@dataclass
|
||||
class ToolCall:
|
||||
"""A tool call made by the agent."""
|
||||
|
||||
id: str
|
||||
name: str
|
||||
input: dict[str, Any]
|
||||
turn_index: int
|
||||
result: str | None = None
|
||||
success: bool | None = None
|
||||
error: str | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class ReasoningTrace:
|
||||
"""Complete reasoning trace for an agent session."""
|
||||
|
||||
session_id: str
|
||||
task: str
|
||||
system_prompt: str
|
||||
thinking_blocks: list[ThinkingBlock] = field(default_factory=list)
|
||||
tool_calls: list[ToolCall] = field(default_factory=list)
|
||||
final_response: str | None = None
|
||||
|
||||
# Metadata
|
||||
model: str = "MiniMax-M2.1"
|
||||
total_turns: int = 0
|
||||
total_tokens: int = 0
|
||||
success: bool | None = None
|
||||
error: str | None = None
|
||||
started_at: datetime = field(default_factory=datetime.now)
|
||||
completed_at: datetime | None = None
|
||||
|
||||
def get_thinking_at_turn(self, turn: int) -> ThinkingBlock | None:
|
||||
"""Get thinking block at specific turn."""
|
||||
for block in self.thinking_blocks:
|
||||
if block.turn_index == turn:
|
||||
return block
|
||||
return None
|
||||
|
||||
def get_tool_calls_at_turn(self, turn: int) -> list[ToolCall]:
|
||||
"""Get all tool calls at specific turn."""
|
||||
return [tc for tc in self.tool_calls if tc.turn_index == turn]
|
||||
|
||||
|
||||
@dataclass
|
||||
class Pattern:
|
||||
"""A detected pattern in reasoning traces."""
|
||||
|
||||
type: PatternType
|
||||
severity: Severity
|
||||
description: str
|
||||
evidence: list[str] # Excerpts from thinking blocks
|
||||
turn_indices: list[int]
|
||||
suggestion: str
|
||||
confidence: float # 0.0 to 1.0
|
||||
|
||||
|
||||
@dataclass
|
||||
class AnalysisResult:
|
||||
"""Result of analyzing a reasoning trace."""
|
||||
|
||||
trace_id: str
|
||||
patterns: list[Pattern] = field(default_factory=list)
|
||||
|
||||
# Scores (0-100)
|
||||
reasoning_clarity: float = 0.0
|
||||
goal_adherence: float = 0.0
|
||||
tool_usage_quality: float = 0.0
|
||||
error_recovery: float = 0.0
|
||||
overall_score: float = 0.0
|
||||
|
||||
# Feedback
|
||||
strengths: list[str] = field(default_factory=list)
|
||||
weaknesses: list[str] = field(default_factory=list)
|
||||
recommendations: list[str] = field(default_factory=list)
|
||||
|
||||
# Analysis metadata
|
||||
analyzer_model: str = "MiniMax-M2.1"
|
||||
analyzer_thinking: str = "" # The analyzer's own reasoning
|
||||
|
||||
|
||||
@dataclass
|
||||
class PromptDiff:
|
||||
"""Difference between original and optimized prompt."""
|
||||
|
||||
section: str # e.g., "system_prompt", "tool_description", "instruction"
|
||||
original: str
|
||||
optimized: str
|
||||
reason: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class OptimizationResult:
|
||||
"""Result of prompt optimization."""
|
||||
|
||||
original_prompt: str
|
||||
optimized_prompt: str
|
||||
diffs: list[PromptDiff] = field(default_factory=list)
|
||||
|
||||
# Improvement predictions
|
||||
predicted_improvement: float = 0.0 # Percentage
|
||||
confidence: float = 0.0
|
||||
|
||||
# Optimizer reasoning
|
||||
optimizer_thinking: str = ""
|
||||
key_changes: list[str] = field(default_factory=list)
|
||||
|
||||
|
||||
@dataclass
|
||||
class LoopIteration:
|
||||
"""Single iteration of the optimization loop."""
|
||||
|
||||
iteration: int
|
||||
trace: ReasoningTrace
|
||||
analysis: AnalysisResult
|
||||
optimization: OptimizationResult | None
|
||||
|
||||
# Metrics
|
||||
task_completed: bool = False
|
||||
error_count: int = 0
|
||||
token_usage: int = 0
|
||||
|
||||
|
||||
@dataclass
|
||||
class LoopResult:
|
||||
"""Result of running the full optimization loop."""
|
||||
|
||||
task: str
|
||||
iterations: list[LoopIteration] = field(default_factory=list)
|
||||
|
||||
# Final state
|
||||
final_prompt: str = ""
|
||||
converged: bool = False
|
||||
total_iterations: int = 0
|
||||
|
||||
# Improvement metrics
|
||||
initial_score: float = 0.0
|
||||
final_score: float = 0.0
|
||||
improvement_percentage: float = 0.0
|
||||
|
||||
# Generated artifacts
|
||||
generated_skill_path: str | None = None
|
||||
@@ -0,0 +1,449 @@
|
||||
"""
|
||||
PromptOptimizer: Generates improved prompts based on trace analysis.
|
||||
|
||||
Uses M2.1 to synthesize analysis results into concrete prompt improvements,
|
||||
with full reasoning transparency via interleaved thinking.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
import anthropic
|
||||
|
||||
from reasoning_trace_optimizer.models import (
|
||||
AnalysisResult,
|
||||
OptimizationResult,
|
||||
PromptDiff,
|
||||
ReasoningTrace,
|
||||
)
|
||||
|
||||
|
||||
OPTIMIZER_SYSTEM_PROMPT = """You are an expert prompt engineer specializing in AI agent optimization.
|
||||
|
||||
Your task is to improve agent prompts based on reasoning trace analysis.
|
||||
You have access to:
|
||||
1. The original prompt that was used
|
||||
2. Analysis of how the agent reasoned (its thinking trace)
|
||||
3. Detected patterns and issues
|
||||
4. Specific recommendations
|
||||
|
||||
Your goal is to create an IMPROVED prompt that:
|
||||
- Addresses identified weaknesses
|
||||
- Maintains existing strengths
|
||||
- Prevents detected failure patterns
|
||||
- Improves clarity and specificity
|
||||
|
||||
When optimizing, consider:
|
||||
- Adding explicit guardrails for common failure modes
|
||||
- Clarifying ambiguous instructions
|
||||
- Adding examples for complex behaviors
|
||||
- Restructuring for better context positioning
|
||||
- Adding validation steps where missing
|
||||
|
||||
Provide the optimized prompt with clear explanations of changes."""
|
||||
|
||||
|
||||
OPTIMIZATION_PROMPT_TEMPLATE = """Optimize the following agent prompt based on trace analysis:
|
||||
|
||||
## Original Task
|
||||
{task}
|
||||
|
||||
## Original System Prompt
|
||||
```
|
||||
{original_prompt}
|
||||
```
|
||||
|
||||
## Analysis Results
|
||||
|
||||
### Overall Score: {overall_score}/100
|
||||
|
||||
### Detected Patterns
|
||||
{patterns}
|
||||
|
||||
### Weaknesses
|
||||
{weaknesses}
|
||||
|
||||
### Recommendations
|
||||
{recommendations}
|
||||
|
||||
### Analyzer's Reasoning
|
||||
{analyzer_thinking}
|
||||
|
||||
---
|
||||
|
||||
Provide your optimization as JSON:
|
||||
```json
|
||||
{{
|
||||
"optimized_prompt": "<the full improved prompt>",
|
||||
"diffs": [
|
||||
{{
|
||||
"section": "<which part changed, e.g., 'instructions', 'guardrails', 'examples'>",
|
||||
"original": "<original text or 'N/A' if new>",
|
||||
"optimized": "<new/changed text>",
|
||||
"reason": "<why this change helps>"
|
||||
}}
|
||||
],
|
||||
"key_changes": [
|
||||
"<summary of major change 1>",
|
||||
"<summary of major change 2>"
|
||||
],
|
||||
"predicted_improvement": 15,
|
||||
"confidence": 0.75
|
||||
}}
|
||||
```
|
||||
|
||||
Think carefully about what changes will have the biggest impact on agent performance."""
|
||||
|
||||
|
||||
class PromptOptimizer:
|
||||
"""
|
||||
Optimizes agent prompts based on reasoning trace analysis.
|
||||
|
||||
Uses M2.1's interleaved thinking to generate thoughtful improvements
|
||||
with full transparency into the optimization reasoning.
|
||||
|
||||
Example:
|
||||
```python
|
||||
optimizer = PromptOptimizer()
|
||||
result = optimizer.optimize(
|
||||
original_prompt=system_prompt,
|
||||
analysis=analysis_result,
|
||||
trace=reasoning_trace
|
||||
)
|
||||
|
||||
print(f"Predicted improvement: {result.predicted_improvement}%")
|
||||
print(f"New prompt:\\n{result.optimized_prompt}")
|
||||
```
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api_key: str | None = None,
|
||||
base_url: str = "https://api.minimax.io/anthropic",
|
||||
model: str = "MiniMax-M2.1",
|
||||
):
|
||||
"""
|
||||
Initialize PromptOptimizer with M2.1 configuration.
|
||||
|
||||
Args:
|
||||
api_key: MiniMax API key
|
||||
base_url: API endpoint
|
||||
model: Model for optimization
|
||||
"""
|
||||
self.model = model
|
||||
self.client = anthropic.Anthropic(
|
||||
api_key=api_key or os.environ.get("ANTHROPIC_API_KEY"),
|
||||
base_url=base_url,
|
||||
)
|
||||
|
||||
def optimize(
|
||||
self,
|
||||
original_prompt: str,
|
||||
analysis: AnalysisResult,
|
||||
trace: ReasoningTrace | None = None,
|
||||
max_tokens: int = 8192,
|
||||
) -> OptimizationResult:
|
||||
"""
|
||||
Generate an optimized prompt based on analysis.
|
||||
|
||||
Args:
|
||||
original_prompt: The original system prompt to improve
|
||||
analysis: Analysis results from TraceAnalyzer
|
||||
trace: Optional original trace for additional context
|
||||
max_tokens: Maximum tokens for response
|
||||
|
||||
Returns:
|
||||
OptimizationResult with new prompt and change details
|
||||
"""
|
||||
# Format analysis for prompt
|
||||
patterns_text = self._format_patterns(analysis)
|
||||
weaknesses_text = "\n".join(f"- {w}" for w in analysis.weaknesses)
|
||||
recommendations_text = "\n".join(f"- {r}" for r in analysis.recommendations)
|
||||
|
||||
prompt = OPTIMIZATION_PROMPT_TEMPLATE.format(
|
||||
task=trace.task if trace else "Unknown task",
|
||||
original_prompt=original_prompt,
|
||||
overall_score=analysis.overall_score,
|
||||
patterns=patterns_text,
|
||||
weaknesses=weaknesses_text or "None identified",
|
||||
recommendations=recommendations_text or "None provided",
|
||||
analyzer_thinking=analysis.analyzer_thinking[:2000] if analysis.analyzer_thinking else "Not available",
|
||||
)
|
||||
|
||||
# Call M2.1 for optimization
|
||||
response = self.client.messages.create(
|
||||
model=self.model,
|
||||
max_tokens=max_tokens,
|
||||
system=OPTIMIZER_SYSTEM_PROMPT,
|
||||
messages=[{"role": "user", "content": prompt}],
|
||||
)
|
||||
|
||||
# Extract thinking and response
|
||||
optimizer_thinking = ""
|
||||
optimization_text = ""
|
||||
|
||||
for block in response.content:
|
||||
if block.type == "thinking":
|
||||
optimizer_thinking = block.thinking
|
||||
elif block.type == "text":
|
||||
optimization_text = block.text
|
||||
|
||||
# Parse the response
|
||||
result = self._parse_optimization_response(optimization_text, original_prompt)
|
||||
result.optimizer_thinking = optimizer_thinking
|
||||
|
||||
return result
|
||||
|
||||
def optimize_iterative(
|
||||
self,
|
||||
original_prompt: str,
|
||||
analyses: list[AnalysisResult],
|
||||
traces: list[ReasoningTrace],
|
||||
) -> OptimizationResult:
|
||||
"""
|
||||
Optimize based on multiple analysis iterations.
|
||||
|
||||
Synthesizes patterns across multiple runs for more robust improvements.
|
||||
|
||||
Args:
|
||||
original_prompt: The original system prompt
|
||||
analyses: List of analysis results from multiple runs
|
||||
traces: Corresponding reasoning traces
|
||||
|
||||
Returns:
|
||||
OptimizationResult incorporating learnings from all iterations
|
||||
"""
|
||||
# Aggregate patterns across all analyses
|
||||
all_patterns = []
|
||||
all_weaknesses = []
|
||||
all_recommendations = []
|
||||
avg_score = 0
|
||||
|
||||
for analysis in analyses:
|
||||
all_patterns.extend(analysis.patterns)
|
||||
all_weaknesses.extend(analysis.weaknesses)
|
||||
all_recommendations.extend(analysis.recommendations)
|
||||
avg_score += analysis.overall_score
|
||||
|
||||
avg_score /= len(analyses) if analyses else 1
|
||||
|
||||
# Create aggregated analysis
|
||||
aggregated = AnalysisResult(
|
||||
trace_id="aggregated",
|
||||
patterns=all_patterns,
|
||||
overall_score=avg_score,
|
||||
weaknesses=list(set(all_weaknesses)), # Deduplicate
|
||||
recommendations=list(set(all_recommendations)),
|
||||
)
|
||||
|
||||
# Optimize based on aggregated analysis
|
||||
return self.optimize(
|
||||
original_prompt=original_prompt,
|
||||
analysis=aggregated,
|
||||
trace=traces[0] if traces else None,
|
||||
)
|
||||
|
||||
def suggest_tool_improvements(
|
||||
self,
|
||||
tools: list[dict[str, Any]],
|
||||
analysis: AnalysisResult,
|
||||
trace: ReasoningTrace,
|
||||
) -> dict[str, str]:
|
||||
"""
|
||||
Suggest improvements for tool definitions based on analysis.
|
||||
|
||||
Args:
|
||||
tools: Original tool definitions
|
||||
analysis: Analysis results
|
||||
trace: Original reasoning trace
|
||||
|
||||
Returns:
|
||||
Dict mapping tool names to suggested description improvements
|
||||
"""
|
||||
tool_issues = [
|
||||
p for p in analysis.patterns
|
||||
if p.type.value in ("tool_confusion", "tool_misuse")
|
||||
]
|
||||
|
||||
if not tool_issues:
|
||||
return {}
|
||||
|
||||
prompt = f"""Based on these tool usage issues:
|
||||
|
||||
{self._format_patterns_for_tools(tool_issues)}
|
||||
|
||||
And the original tool definitions:
|
||||
{json.dumps(tools, indent=2)}
|
||||
|
||||
Suggest improved tool descriptions. Respond as JSON:
|
||||
```json
|
||||
{{
|
||||
"tool_name": "improved description that addresses the confusion"
|
||||
}}
|
||||
```"""
|
||||
|
||||
response = self.client.messages.create(
|
||||
model=self.model,
|
||||
max_tokens=2048,
|
||||
messages=[{"role": "user", "content": prompt}],
|
||||
)
|
||||
|
||||
for block in response.content:
|
||||
if block.type == "text":
|
||||
try:
|
||||
text = block.text
|
||||
if "```json" in text:
|
||||
text = text.split("```json")[1].split("```")[0]
|
||||
return json.loads(text)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
return {}
|
||||
|
||||
def _format_patterns(self, analysis: AnalysisResult) -> str:
|
||||
"""Format patterns for optimization prompt."""
|
||||
if not analysis.patterns:
|
||||
return "No significant patterns detected."
|
||||
|
||||
parts = []
|
||||
for p in analysis.patterns:
|
||||
parts.append(
|
||||
f"[{p.severity.value.upper()}] {p.type.value}\n"
|
||||
f" Description: {p.description}\n"
|
||||
f" Evidence: {', '.join(p.evidence[:2])}\n"
|
||||
f" Suggestion: {p.suggestion}"
|
||||
)
|
||||
return "\n\n".join(parts)
|
||||
|
||||
def _format_patterns_for_tools(self, patterns: list) -> str:
|
||||
"""Format tool-related patterns."""
|
||||
return "\n".join(
|
||||
f"- {p.type.value}: {p.description}" for p in patterns
|
||||
)
|
||||
|
||||
def _parse_optimization_response(
|
||||
self,
|
||||
response_text: str,
|
||||
original_prompt: str,
|
||||
) -> OptimizationResult:
|
||||
"""Parse the JSON optimization response with fallback extraction."""
|
||||
result = OptimizationResult(
|
||||
original_prompt=original_prompt,
|
||||
optimized_prompt=original_prompt, # Default to original if parsing fails
|
||||
)
|
||||
|
||||
try:
|
||||
json_text = response_text
|
||||
if "```json" in response_text:
|
||||
json_text = response_text.split("```json")[1].split("```")[0]
|
||||
elif "```" in response_text:
|
||||
json_text = response_text.split("```")[1].split("```")[0]
|
||||
|
||||
data = json.loads(json_text)
|
||||
|
||||
result.optimized_prompt = data.get("optimized_prompt", original_prompt)
|
||||
result.predicted_improvement = data.get("predicted_improvement", 0)
|
||||
result.confidence = data.get("confidence", 0.5)
|
||||
result.key_changes = data.get("key_changes", [])
|
||||
|
||||
# Parse diffs
|
||||
for d in data.get("diffs", []):
|
||||
diff = PromptDiff(
|
||||
section=d.get("section", "unknown"),
|
||||
original=d.get("original", ""),
|
||||
optimized=d.get("optimized", ""),
|
||||
reason=d.get("reason", ""),
|
||||
)
|
||||
result.diffs.append(diff)
|
||||
|
||||
except (json.JSONDecodeError, KeyError) as e:
|
||||
# Fallback: try to extract optimized_prompt directly from response
|
||||
extracted_prompt = self._fallback_extract_prompt(response_text)
|
||||
if extracted_prompt and extracted_prompt != original_prompt:
|
||||
result.optimized_prompt = extracted_prompt
|
||||
result.key_changes = [f"JSON parsing failed ({type(e).__name__}), extracted prompt via fallback"]
|
||||
result.confidence = 0.3 # Lower confidence for fallback extraction
|
||||
else:
|
||||
result.key_changes = [f"Optimization parsing failed ({type(e).__name__}) - using original prompt"]
|
||||
|
||||
return result
|
||||
|
||||
def _fallback_extract_prompt(self, response_text: str) -> str | None:
|
||||
"""
|
||||
Fallback method to extract optimized prompt when JSON parsing fails.
|
||||
|
||||
Tries multiple strategies to find the prompt content.
|
||||
"""
|
||||
import re
|
||||
|
||||
# Strategy 1: Look for "optimized_prompt": "..." pattern
|
||||
match = re.search(r'"optimized_prompt"\s*:\s*"([^"]+)"', response_text, re.DOTALL)
|
||||
if match:
|
||||
# Unescape the string
|
||||
return match.group(1).replace('\\n', '\n').replace('\\"', '"')
|
||||
|
||||
# Strategy 2: Look for content between specific markers
|
||||
markers = [
|
||||
('## Optimized Prompt', '##'),
|
||||
('**Optimized Prompt**', '**'),
|
||||
('OPTIMIZED PROMPT:', '\n\n'),
|
||||
('Here is the improved prompt:', '\n\n---'),
|
||||
]
|
||||
|
||||
for start_marker, end_marker in markers:
|
||||
if start_marker in response_text:
|
||||
start_idx = response_text.find(start_marker) + len(start_marker)
|
||||
remaining = response_text[start_idx:].strip()
|
||||
if end_marker in remaining:
|
||||
end_idx = remaining.find(end_marker)
|
||||
extracted = remaining[:end_idx].strip()
|
||||
if len(extracted) > 50: # Minimum length check
|
||||
return extracted
|
||||
|
||||
# Strategy 3: Look for a substantial code block that might be the prompt
|
||||
code_blocks = re.findall(r'```(?:text|markdown)?\n(.*?)```', response_text, re.DOTALL)
|
||||
for block in code_blocks:
|
||||
# Skip JSON blocks, look for prose blocks that could be prompts
|
||||
if not block.strip().startswith('{') and len(block) > 100:
|
||||
return block.strip()
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def format_optimization_report(result: OptimizationResult) -> str:
|
||||
"""Format an optimization result as a human-readable report."""
|
||||
lines = [
|
||||
"=" * 60,
|
||||
"PROMPT OPTIMIZATION REPORT",
|
||||
"=" * 60,
|
||||
"",
|
||||
f"Predicted Improvement: {result.predicted_improvement}%",
|
||||
f"Confidence: {result.confidence * 100:.0f}%",
|
||||
"",
|
||||
]
|
||||
|
||||
if result.key_changes:
|
||||
lines.append("Key Changes:")
|
||||
for change in result.key_changes:
|
||||
lines.append(f" - {change}")
|
||||
lines.append("")
|
||||
|
||||
if result.diffs:
|
||||
lines.append("Detailed Changes:")
|
||||
for diff in result.diffs:
|
||||
lines.append(f"\n [{diff.section}]")
|
||||
if diff.original and diff.original != "N/A":
|
||||
lines.append(f" Before: {diff.original[:100]}...")
|
||||
lines.append(f" After: {diff.optimized[:100]}...")
|
||||
lines.append(f" Reason: {diff.reason}")
|
||||
|
||||
lines.extend([
|
||||
"",
|
||||
"=" * 60,
|
||||
"OPTIMIZED PROMPT",
|
||||
"=" * 60,
|
||||
result.optimized_prompt,
|
||||
])
|
||||
|
||||
return "\n".join(lines)
|
||||
@@ -0,0 +1,502 @@
|
||||
"""
|
||||
SkillGenerator: Converts optimization insights into shareable Agent Skills.
|
||||
|
||||
Transforms the learnings from optimization loops into reusable skills
|
||||
following the Agent Skills template format.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import anthropic
|
||||
|
||||
from reasoning_trace_optimizer.models import (
|
||||
AnalysisResult,
|
||||
LoopResult,
|
||||
Pattern,
|
||||
PatternType,
|
||||
)
|
||||
|
||||
|
||||
SKILL_TEMPLATE = '''---
|
||||
name: {skill_name}
|
||||
description: "{description}"
|
||||
---
|
||||
|
||||
# {title}
|
||||
|
||||
{intro}
|
||||
|
||||
## When to Activate
|
||||
|
||||
{activation}
|
||||
|
||||
## Core Concepts
|
||||
|
||||
{concepts}
|
||||
|
||||
## Patterns to Avoid
|
||||
|
||||
{anti_patterns}
|
||||
|
||||
## Recommended Practices
|
||||
|
||||
{practices}
|
||||
|
||||
## Guidelines
|
||||
|
||||
{guidelines}
|
||||
|
||||
## Examples
|
||||
|
||||
{examples}
|
||||
|
||||
---
|
||||
|
||||
## Skill Metadata
|
||||
|
||||
**Generated**: {date}
|
||||
**Source**: Reasoning Trace Optimizer
|
||||
**Optimization Iterations**: {iterations}
|
||||
**Score Improvement**: {initial_score:.1f} → {final_score:.1f} (+{improvement:.1f}%)
|
||||
'''
|
||||
|
||||
|
||||
GENERATOR_SYSTEM_PROMPT = """You are an expert at converting agent optimization insights into reusable skills.
|
||||
|
||||
Your task is to analyze optimization results and generate a shareable Agent Skill that
|
||||
captures the learnings so other developers can benefit.
|
||||
|
||||
The skill should:
|
||||
1. Describe WHEN to use these learnings (activation triggers)
|
||||
2. Explain the PATTERNS to avoid (anti-patterns found)
|
||||
3. Provide CONCRETE practices that improved performance
|
||||
4. Give VERIFIABLE guidelines (things that can be checked)
|
||||
5. Include EXAMPLES showing before/after improvements
|
||||
|
||||
Write in a clear, direct style. Focus on actionable guidance, not theory."""
|
||||
|
||||
|
||||
def _format_list_to_markdown(items: list | str) -> str:
|
||||
"""Convert a list to markdown bullet points."""
|
||||
if isinstance(items, str):
|
||||
return items
|
||||
if not items:
|
||||
return ""
|
||||
|
||||
import re
|
||||
formatted = []
|
||||
for item in items:
|
||||
# Strip any existing leading bullet points/dashes to avoid duplication
|
||||
cleaned = re.sub(r'^[-*•]\s*', '', str(item).strip())
|
||||
formatted.append(f"- {cleaned}")
|
||||
return "\n".join(formatted)
|
||||
|
||||
|
||||
def _format_numbered_list_to_markdown(items: list | str) -> str:
|
||||
"""Convert a list to markdown numbered list."""
|
||||
if isinstance(items, str):
|
||||
return items
|
||||
if not items:
|
||||
return ""
|
||||
|
||||
import re
|
||||
formatted = []
|
||||
for i, item in enumerate(items):
|
||||
# Strip any existing leading numbers (e.g., "1. ", "2. ") to avoid duplication
|
||||
cleaned = re.sub(r'^\d+\.\s*', '', str(item).strip())
|
||||
formatted.append(f"{i+1}. {cleaned}")
|
||||
return "\n".join(formatted)
|
||||
|
||||
|
||||
def _format_examples_to_markdown(examples: list | str) -> str:
|
||||
"""Convert example dicts to markdown format."""
|
||||
if isinstance(examples, str):
|
||||
return examples
|
||||
if not examples:
|
||||
return ""
|
||||
|
||||
parts = []
|
||||
for i, ex in enumerate(examples):
|
||||
if isinstance(ex, dict):
|
||||
parts.append(f"### Example {i+1}: {ex.get('context', 'Scenario')}")
|
||||
if ex.get('before'):
|
||||
parts.append(f"\n**Before:**\n```\n{ex['before']}\n```")
|
||||
if ex.get('after'):
|
||||
parts.append(f"\n**After:**\n```\n{ex['after']}\n```")
|
||||
if ex.get('improvement'):
|
||||
parts.append(f"\n**Improvement:** {ex['improvement']}")
|
||||
parts.append("")
|
||||
else:
|
||||
parts.append(f"- {ex}")
|
||||
return "\n".join(parts)
|
||||
|
||||
|
||||
class SkillGenerator:
|
||||
"""
|
||||
Generates shareable Agent Skills from optimization results.
|
||||
|
||||
Converts the learnings from optimization loops into the standard
|
||||
Agent Skills format for sharing with other developers.
|
||||
|
||||
Example:
|
||||
```python
|
||||
generator = SkillGenerator()
|
||||
skill_path = generator.generate(
|
||||
result=loop_result,
|
||||
skill_name="web-search-agent",
|
||||
output_dir="./generated_skills"
|
||||
)
|
||||
print(f"Generated skill at: {skill_path}")
|
||||
```
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api_key: str | None = None,
|
||||
base_url: str = "https://api.minimax.io/anthropic",
|
||||
model: str = "MiniMax-M2.1",
|
||||
):
|
||||
"""
|
||||
Initialize SkillGenerator.
|
||||
|
||||
Args:
|
||||
api_key: MiniMax API key
|
||||
base_url: API endpoint
|
||||
model: Model for skill generation
|
||||
"""
|
||||
self.model = model
|
||||
self.client = anthropic.Anthropic(
|
||||
api_key=api_key or os.environ.get("ANTHROPIC_API_KEY"),
|
||||
base_url=base_url,
|
||||
)
|
||||
|
||||
def generate(
|
||||
self,
|
||||
result: LoopResult,
|
||||
skill_name: str,
|
||||
output_dir: str = "./generated_skills",
|
||||
title: str | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
Generate an Agent Skill from optimization results.
|
||||
|
||||
Args:
|
||||
result: The optimization loop result
|
||||
skill_name: Name for the skill (lowercase-with-hyphens)
|
||||
output_dir: Directory to save the skill
|
||||
title: Optional human-readable title
|
||||
|
||||
Returns:
|
||||
Path to the generated SKILL.md file
|
||||
"""
|
||||
# Extract insights from all iterations
|
||||
all_patterns = self._collect_patterns(result)
|
||||
all_recommendations = self._collect_recommendations(result)
|
||||
key_changes = self._collect_key_changes(result)
|
||||
|
||||
# Generate skill content using M2.1
|
||||
content = self._generate_skill_content(
|
||||
task=result.task,
|
||||
patterns=all_patterns,
|
||||
recommendations=all_recommendations,
|
||||
key_changes=key_changes,
|
||||
initial_prompt=result.iterations[0].trace.system_prompt if result.iterations else "",
|
||||
final_prompt=result.final_prompt,
|
||||
)
|
||||
|
||||
# Format content - convert lists to markdown
|
||||
formatted_content = {
|
||||
"activation": _format_list_to_markdown(content.get("activation", "")),
|
||||
"concepts": _format_list_to_markdown(content.get("concepts", "")),
|
||||
"anti_patterns": _format_list_to_markdown(content.get("anti_patterns", "")),
|
||||
"practices": _format_list_to_markdown(content.get("practices", "")),
|
||||
"guidelines": _format_numbered_list_to_markdown(content.get("guidelines", "")),
|
||||
"examples": _format_examples_to_markdown(content.get("examples", "")),
|
||||
}
|
||||
|
||||
# Format using template
|
||||
skill_content = SKILL_TEMPLATE.format(
|
||||
skill_name=skill_name,
|
||||
description=content.get("description", f"Optimized practices for {skill_name}"),
|
||||
title=title or content.get("title", skill_name.replace("-", " ").title()),
|
||||
intro=content.get("intro", ""),
|
||||
activation=formatted_content["activation"],
|
||||
concepts=formatted_content["concepts"],
|
||||
anti_patterns=formatted_content["anti_patterns"],
|
||||
practices=formatted_content["practices"],
|
||||
guidelines=formatted_content["guidelines"],
|
||||
examples=formatted_content["examples"],
|
||||
date=datetime.now().strftime("%Y-%m-%d"),
|
||||
iterations=result.total_iterations,
|
||||
initial_score=result.initial_score,
|
||||
final_score=result.final_score,
|
||||
improvement=result.improvement_percentage,
|
||||
)
|
||||
|
||||
# Save skill
|
||||
skill_dir = Path(output_dir) / skill_name
|
||||
skill_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
skill_path = skill_dir / "SKILL.md"
|
||||
with open(skill_path, "w") as f:
|
||||
f.write(skill_content)
|
||||
|
||||
# Save optimization data as reference
|
||||
self._save_references(skill_dir, result, content)
|
||||
|
||||
return str(skill_path)
|
||||
|
||||
def generate_from_analysis(
|
||||
self,
|
||||
analyses: list[AnalysisResult],
|
||||
skill_name: str,
|
||||
task_description: str,
|
||||
output_dir: str = "./generated_skills",
|
||||
) -> str:
|
||||
"""
|
||||
Generate a skill from multiple analysis results (without full loop).
|
||||
|
||||
Useful when you have analysis data but didn't run the full optimization loop.
|
||||
|
||||
Args:
|
||||
analyses: List of analysis results
|
||||
skill_name: Name for the skill
|
||||
task_description: Description of the task context
|
||||
output_dir: Output directory
|
||||
|
||||
Returns:
|
||||
Path to generated skill
|
||||
"""
|
||||
# Aggregate patterns and recommendations
|
||||
all_patterns = []
|
||||
all_recommendations = []
|
||||
|
||||
for analysis in analyses:
|
||||
all_patterns.extend(analysis.patterns)
|
||||
all_recommendations.extend(analysis.recommendations)
|
||||
|
||||
content = self._generate_skill_content(
|
||||
task=task_description,
|
||||
patterns=all_patterns,
|
||||
recommendations=list(set(all_recommendations)),
|
||||
key_changes=[],
|
||||
initial_prompt="",
|
||||
final_prompt="",
|
||||
)
|
||||
|
||||
# Calculate average score
|
||||
avg_score = sum(a.overall_score for a in analyses) / len(analyses) if analyses else 0
|
||||
|
||||
skill_content = SKILL_TEMPLATE.format(
|
||||
skill_name=skill_name,
|
||||
description=content.get("description", f"Learnings for {skill_name}"),
|
||||
title=content.get("title", skill_name.replace("-", " ").title()),
|
||||
intro=content.get("intro", ""),
|
||||
activation=content.get("activation", ""),
|
||||
concepts=content.get("concepts", ""),
|
||||
anti_patterns=content.get("anti_patterns", ""),
|
||||
practices=content.get("practices", ""),
|
||||
guidelines=content.get("guidelines", ""),
|
||||
examples=content.get("examples", ""),
|
||||
date=datetime.now().strftime("%Y-%m-%d"),
|
||||
iterations=len(analyses),
|
||||
initial_score=avg_score,
|
||||
final_score=avg_score,
|
||||
improvement=0,
|
||||
)
|
||||
|
||||
skill_dir = Path(output_dir) / skill_name
|
||||
skill_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
skill_path = skill_dir / "SKILL.md"
|
||||
with open(skill_path, "w") as f:
|
||||
f.write(skill_content)
|
||||
|
||||
return str(skill_path)
|
||||
|
||||
def _collect_patterns(self, result: LoopResult) -> list[Pattern]:
|
||||
"""Collect all unique patterns from iterations."""
|
||||
patterns = []
|
||||
seen = set()
|
||||
|
||||
for iteration in result.iterations:
|
||||
for pattern in iteration.analysis.patterns:
|
||||
key = (pattern.type, pattern.description[:50])
|
||||
if key not in seen:
|
||||
patterns.append(pattern)
|
||||
seen.add(key)
|
||||
|
||||
return patterns
|
||||
|
||||
def _collect_recommendations(self, result: LoopResult) -> list[str]:
|
||||
"""Collect all unique recommendations."""
|
||||
recommendations = []
|
||||
seen = set()
|
||||
|
||||
for iteration in result.iterations:
|
||||
for rec in iteration.analysis.recommendations:
|
||||
if rec not in seen:
|
||||
recommendations.append(rec)
|
||||
seen.add(rec)
|
||||
|
||||
return recommendations
|
||||
|
||||
def _collect_key_changes(self, result: LoopResult) -> list[str]:
|
||||
"""Collect all key changes from optimizations."""
|
||||
changes = []
|
||||
|
||||
for iteration in result.iterations:
|
||||
if iteration.optimization:
|
||||
changes.extend(iteration.optimization.key_changes)
|
||||
|
||||
return changes
|
||||
|
||||
def _generate_skill_content(
|
||||
self,
|
||||
task: str,
|
||||
patterns: list[Pattern],
|
||||
recommendations: list[str],
|
||||
key_changes: list[str],
|
||||
initial_prompt: str,
|
||||
final_prompt: str,
|
||||
) -> dict[str, str]:
|
||||
"""Use M2.1 to generate skill content sections."""
|
||||
patterns_text = "\n".join(
|
||||
f"- [{p.severity.value}] {p.type.value}: {p.description}"
|
||||
for p in patterns
|
||||
)
|
||||
|
||||
recommendations_text = "\n".join(f"- {r}" for r in recommendations)
|
||||
changes_text = "\n".join(f"- {c}" for c in key_changes)
|
||||
|
||||
prompt = f"""Generate an Agent Skill based on these optimization insights:
|
||||
|
||||
## Task Context
|
||||
{task}
|
||||
|
||||
## Patterns Detected (Anti-patterns to avoid)
|
||||
{patterns_text or "No significant patterns detected"}
|
||||
|
||||
## Recommendations from Analysis
|
||||
{recommendations_text or "No specific recommendations"}
|
||||
|
||||
## Key Changes That Improved Performance
|
||||
{changes_text or "No recorded changes"}
|
||||
|
||||
## Prompt Evolution
|
||||
Initial: {initial_prompt[:500] if initial_prompt else "N/A"}...
|
||||
Final: {final_prompt[:500] if final_prompt else "N/A"}...
|
||||
|
||||
---
|
||||
|
||||
Generate skill content as JSON:
|
||||
```json
|
||||
{{
|
||||
"title": "Human-readable skill title",
|
||||
"description": "One-line description for skill discovery (what triggers this skill)",
|
||||
"intro": "2-3 sentence introduction explaining what this skill teaches",
|
||||
"activation": "Bullet points of when to activate this skill (specific keywords, task types)",
|
||||
"concepts": "Core concepts this skill covers (3-5 key ideas)",
|
||||
"anti_patterns": "Patterns to AVOID - formatted as markdown list with descriptions",
|
||||
"practices": "Recommended practices - formatted as markdown list",
|
||||
"guidelines": "Numbered verifiable guidelines (things that can be checked)",
|
||||
"examples": "1-2 concrete before/after examples showing improvement"
|
||||
}}
|
||||
```"""
|
||||
|
||||
response = self.client.messages.create(
|
||||
model=self.model,
|
||||
max_tokens=4096,
|
||||
system=GENERATOR_SYSTEM_PROMPT,
|
||||
messages=[{"role": "user", "content": prompt}],
|
||||
)
|
||||
|
||||
# Parse response
|
||||
for block in response.content:
|
||||
if block.type == "text":
|
||||
try:
|
||||
text = block.text
|
||||
if "```json" in text:
|
||||
text = text.split("```json")[1].split("```")[0]
|
||||
return json.loads(text)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
# Return defaults if parsing fails
|
||||
return {
|
||||
"title": "Generated Agent Skill",
|
||||
"description": f"Optimized practices for {task}",
|
||||
"intro": "This skill contains learnings from automated prompt optimization.",
|
||||
"activation": "- When working on similar tasks\n- When debugging agent failures",
|
||||
"concepts": "See recommendations section.",
|
||||
"anti_patterns": patterns_text or "No patterns identified.",
|
||||
"practices": recommendations_text or "No specific practices.",
|
||||
"guidelines": "1. Review the anti-patterns before implementation\n2. Apply recommended practices",
|
||||
"examples": "See optimization artifacts for detailed examples.",
|
||||
}
|
||||
|
||||
def _save_references(
|
||||
self,
|
||||
skill_dir: Path,
|
||||
result: LoopResult,
|
||||
content: dict[str, str],
|
||||
) -> None:
|
||||
"""Save reference materials alongside the skill."""
|
||||
refs_dir = skill_dir / "references"
|
||||
refs_dir.mkdir(exist_ok=True)
|
||||
|
||||
# Save optimization summary
|
||||
summary = {
|
||||
"task": result.task,
|
||||
"iterations": result.total_iterations,
|
||||
"initial_score": result.initial_score,
|
||||
"final_score": result.final_score,
|
||||
"improvement": result.improvement_percentage,
|
||||
"converged": result.converged,
|
||||
"generated_at": datetime.now().isoformat(),
|
||||
}
|
||||
with open(refs_dir / "optimization_summary.json", "w") as f:
|
||||
json.dump(summary, f, indent=2)
|
||||
|
||||
# Save final optimized prompt
|
||||
with open(refs_dir / "optimized_prompt.txt", "w") as f:
|
||||
f.write(result.final_prompt)
|
||||
|
||||
# Save all patterns found
|
||||
patterns_data = []
|
||||
for iteration in result.iterations:
|
||||
for p in iteration.analysis.patterns:
|
||||
patterns_data.append({
|
||||
"type": p.type.value,
|
||||
"severity": p.severity.value,
|
||||
"description": p.description,
|
||||
"suggestion": p.suggestion,
|
||||
"iteration": iteration.iteration,
|
||||
})
|
||||
|
||||
with open(refs_dir / "patterns_found.json", "w") as f:
|
||||
json.dump(patterns_data, f, indent=2)
|
||||
|
||||
|
||||
def generate_skill_from_loop(
|
||||
result: LoopResult,
|
||||
skill_name: str,
|
||||
output_dir: str = "./generated_skills",
|
||||
) -> str:
|
||||
"""
|
||||
Quick helper to generate a skill from optimization results.
|
||||
|
||||
Args:
|
||||
result: Optimization loop result
|
||||
skill_name: Name for the skill
|
||||
output_dir: Output directory
|
||||
|
||||
Returns:
|
||||
Path to generated skill
|
||||
"""
|
||||
generator = SkillGenerator()
|
||||
return generator.generate(result, skill_name, output_dir)
|
||||
@@ -0,0 +1 @@
|
||||
"""Tests for Reasoning Trace Optimizer."""
|
||||
@@ -0,0 +1,144 @@
|
||||
"""Tests for data models."""
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from reasoning_trace_optimizer.models import (
|
||||
AnalysisResult,
|
||||
LoopResult,
|
||||
OptimizationResult,
|
||||
Pattern,
|
||||
PatternType,
|
||||
PromptDiff,
|
||||
ReasoningTrace,
|
||||
Severity,
|
||||
ThinkingBlock,
|
||||
ToolCall,
|
||||
)
|
||||
|
||||
|
||||
def test_thinking_block_creation():
|
||||
"""Test ThinkingBlock creation with defaults."""
|
||||
block = ThinkingBlock(
|
||||
content="This is a test thinking block.",
|
||||
turn_index=0,
|
||||
)
|
||||
assert block.content == "This is a test thinking block."
|
||||
assert block.turn_index == 0
|
||||
assert block.token_count == 0
|
||||
assert isinstance(block.timestamp, datetime)
|
||||
|
||||
|
||||
def test_tool_call_creation():
|
||||
"""Test ToolCall creation."""
|
||||
tc = ToolCall(
|
||||
id="call_123",
|
||||
name="get_weather",
|
||||
input={"location": "San Francisco"},
|
||||
turn_index=1,
|
||||
)
|
||||
assert tc.id == "call_123"
|
||||
assert tc.name == "get_weather"
|
||||
assert tc.input["location"] == "San Francisco"
|
||||
assert tc.success is None
|
||||
|
||||
|
||||
def test_reasoning_trace_creation():
|
||||
"""Test ReasoningTrace creation and methods."""
|
||||
trace = ReasoningTrace(
|
||||
session_id="test-session",
|
||||
task="Test task",
|
||||
system_prompt="Test prompt",
|
||||
)
|
||||
|
||||
# Add thinking block
|
||||
block = ThinkingBlock(content="Thinking...", turn_index=0)
|
||||
trace.thinking_blocks.append(block)
|
||||
|
||||
# Add tool call
|
||||
tc = ToolCall(
|
||||
id="call_1",
|
||||
name="test_tool",
|
||||
input={},
|
||||
turn_index=0,
|
||||
)
|
||||
trace.tool_calls.append(tc)
|
||||
|
||||
# Test methods
|
||||
assert trace.get_thinking_at_turn(0) == block
|
||||
assert trace.get_thinking_at_turn(1) is None
|
||||
assert len(trace.get_tool_calls_at_turn(0)) == 1
|
||||
assert len(trace.get_tool_calls_at_turn(1)) == 0
|
||||
|
||||
|
||||
def test_pattern_creation():
|
||||
"""Test Pattern creation."""
|
||||
pattern = Pattern(
|
||||
type=PatternType.CONTEXT_DEGRADATION,
|
||||
severity=Severity.HIGH,
|
||||
description="Model lost track of goal",
|
||||
evidence=["Evidence 1", "Evidence 2"],
|
||||
turn_indices=[2, 3],
|
||||
suggestion="Add explicit reminders",
|
||||
confidence=0.85,
|
||||
)
|
||||
assert pattern.type == PatternType.CONTEXT_DEGRADATION
|
||||
assert pattern.severity == Severity.HIGH
|
||||
assert pattern.confidence == 0.85
|
||||
|
||||
|
||||
def test_analysis_result_creation():
|
||||
"""Test AnalysisResult creation."""
|
||||
result = AnalysisResult(trace_id="test-trace")
|
||||
assert result.overall_score == 0.0
|
||||
assert len(result.patterns) == 0
|
||||
assert len(result.recommendations) == 0
|
||||
|
||||
|
||||
def test_optimization_result_creation():
|
||||
"""Test OptimizationResult creation."""
|
||||
result = OptimizationResult(
|
||||
original_prompt="Original",
|
||||
optimized_prompt="Optimized",
|
||||
)
|
||||
result.diffs.append(PromptDiff(
|
||||
section="instructions",
|
||||
original="Original text",
|
||||
optimized="Improved text",
|
||||
reason="Better clarity",
|
||||
))
|
||||
assert len(result.diffs) == 1
|
||||
assert result.diffs[0].section == "instructions"
|
||||
|
||||
|
||||
def test_loop_result_creation():
|
||||
"""Test LoopResult creation."""
|
||||
result = LoopResult(task="Test task")
|
||||
assert result.total_iterations == 0
|
||||
assert result.converged is False
|
||||
assert result.improvement_percentage == 0.0
|
||||
|
||||
|
||||
def test_pattern_types():
|
||||
"""Test all PatternType values exist."""
|
||||
expected_types = [
|
||||
"context_degradation",
|
||||
"tool_confusion",
|
||||
"instruction_drift",
|
||||
"hallucination",
|
||||
"incomplete_reasoning",
|
||||
"tool_misuse",
|
||||
"goal_abandonment",
|
||||
"circular_reasoning",
|
||||
"premature_conclusion",
|
||||
"missing_validation",
|
||||
]
|
||||
for type_name in expected_types:
|
||||
assert PatternType(type_name) is not None
|
||||
|
||||
|
||||
def test_severity_levels():
|
||||
"""Test all Severity levels exist."""
|
||||
assert Severity.LOW.value == "low"
|
||||
assert Severity.MEDIUM.value == "medium"
|
||||
assert Severity.HIGH.value == "high"
|
||||
assert Severity.CRITICAL.value == "critical"
|
||||
Reference in New Issue
Block a user