1. 项目背景与核心思路
作为一名长期奋战在AI应用开发一线的工程师,我深知prompt调优的痛苦。就像在黑暗房间里摸索电灯开关,你永远不知道下一个微调会让效果变好还是更糟。最近看到Andrej Karpathy的autoresearch方法被Ole Lehmann应用到Claude Code的skill优化上,pass rate从50%提升到90%,这让我眼前一亮。
当时我正在调试brain-search这个skill——它能调用Brave Search API返回结构化搜索结果,但输出质量极不稳定。有时完美呈现来源链接和清晰结构,有时却变成杂乱无章的文字堆砌。手动调了四五版prompt后,效果依然像老式收音机的信号,稍微一动就"飘"了。
autoresearch的核心思想很简单:把"假设-实验-评估"的科研流程自动化。在机器学习中,它自动调整训练代码;在prompt工程中,它自动迭代文本内容。这本质上是一种进化算法:生成变异、评估适应度、保留优势变种。我决定把这个方法通用化,做成一个能优化各类AI skill的独立工具。
2. 系统设计与关键技术实现
2.1 架构选型与核心决策
与Lehmann的方案相比,我做了三个关键改进:
脚本驱动替代对话驱动
传统方法需要工程师与AI持续对话,像教小孩写字一样手把手指导。我的方案将其转化为一个命令行工具:
bash复制python autoresearch.py \
--target skills/brain-search/SKILL.md \
--evals eval.json \
--provider minimax \
--max-experiments 10
这种设计让优化过程可以后台运行,解放工程师的时间。就像把手动挡换成自动驾驶,设定好目的地就能放手。
混合评估策略
评估标准分为两类:
- 规则型评估:用正则表达式检查URL格式、字数统计等确定性指标
- LLM评估:当需要语义理解时,让另一个AI作为裁判
这就像考试设计:选择题保证评分效率,主观题测量深层能力。以下是eval.json的示例:
json复制{
"test_inputs": ["search for latest AI agent frameworks"],
"evals": [
{
"name": "has_source_url",
"type": "rule",
"rule": "regex",
"pattern": "https?://[^\\s]+"
},
{
"name": "clear_structure",
"type": "llm",
"question": "Is the output organized with headers, bullets, or numbered lists?",
"pass_description": "Output uses clear visual structure for easy scanning",
"fail_description": "Output is a wall of text without structure"
}
]
}
零依赖设计
仅使用Python标准库实现,不引入第三方包。这使得工具能在各种环境(包括受限的Docker容器)中即装即用。HTTP请求用urllib,JSON处理用json模块,正则匹配用re——这些标准库就像瑞士军刀的基础工具,虽然简陋但足够可靠。
2.2 多Agent协同开发
开发过程本身也采用了AI协同的模式。我同时启动三个Claude Code agent并行工作:
- 文档Agent:负责编写SKILL.md,定义skill的接口规范和使用说明
- 核心逻辑Agent:实现autoresearch.py主脚本,包含LLM调用、评估运行和实验循环
- 示例Agent:创建eval-guide.md和示例eval文件
这种分工类似敏捷开发中的特性团队,每个agent专注自己的领域,通过约定好的接口(如eval.json格式)协作。完成后又用第四个code-reviewer agent进行审查,发现了7个关键bug,例如:
- 中文分词错误:直接用空格split会把整段中文计为1个词
- API密钥检测漏洞:未处理找不到任何密钥的边界情况
- JSON解析缺陷:只支持数组格式忽略单值情况
经验分享:多agent开发时,明确定义接口规范比代码本身更重要。我们为eval.json建立了严格的schema文档,这避免了80%的集成问题。
3. 实战效果与优化过程
3.1 brain-search skill的优化历程
用brain-search作为测试案例,设定了4条评估标准(含中英文测试输入),初始pass rate仅37.5%。分析失败案例发现两个主要问题:
- 来源URL引用格式不一致
- 输出结构混乱
实验1-2:针对性改进
优化器自动在prompt中添加了两条明确指令:
- URL引用必须采用
[标题](URL)的Markdown格式 - 结果必须用二级标题和列表组织
这使得pass rate提升到54.2%。有趣的是,这些改动直指具体问题,而我之前手动调整时总在纠结"语气是否友好"这类模糊因素。
实验3-5:激进尝试
后续实验尝试了更激进的改动,如强制中文查询必须用中文回复。但这些改动导致英文查询质量下降,最终被自动回滚。这展示了autoresearch的核心优势:严格的数据驱动,避免人类的主观偏见。
3.2 踩坑实录:MiniMax的thinking陷阱
最棘手的bug出现在MiniMax M2.7的API集成中。与其他厂商不同,MiniMax的响应包含thinking块:
json复制[
{"type": "thinking", "thinking": "分析问题中..."},
{"type": "text", "text": "YES"}
]
最初设置max_tokens=16导致thinking块耗尽限额,text块为空。所有LLM评估都因无法获取YES/NO而失败。修复方案包括:
- 增加max_tokens到256
- 添加thinking块的回退解析逻辑
python复制# 修复后的调用参数
resp = self.provider.call(
system="",
user=prompt,
temperature=0.0,
max_tokens=256 # 预留足够空间
)
避坑指南:不同厂商的API行为差异就像浏览器兼容性问题。建议为新接入的LLM编写专门的适配层,而不是直接替换端点URL。
4. 评估体系设计方法论
4.1 评估指标的三层架构
有效的评估体系应该像金字塔一样分层:
-
基础合规层(规则型)
- 格式检查:URL、日期、数字等模式匹配
- 长度控制:最小/最大字数限制
- 关键词检测:必须包含或排除的术语
-
语义准确层(LLM型)
- 事实一致性:输出是否与输入需求匹配
- 逻辑连贯性:论点是否自洽
- 领域适应性:是否符合专业规范
-
用户体验层(人工评估)
- 易读性:信息组织是否清晰
- 实用性:是否解决实际问题
- 优雅度:表达是否精炼得体
4.2 评估用例设计技巧
好的测试用例应该像显微镜下的切片,能清晰暴露问题:
- 多样性覆盖:至少包含3类输入(简单、典型、边缘)
- 母语平衡:如果支持多语言,每种语言都应单独测试
- 对抗性测试:故意提供模糊、矛盾或不完整的输入
- 压力测试:超长输入、特殊字符、空值等异常情况
例如测试搜索skill时,我会设计这样的输入组合:
json复制"test_inputs": [
"python的GIL是什么", // 中文明确查询
"latest research on LLM quantization", // 英文专业术语
"查找昨天的重要新闻", // 时间敏感型
"介绍一下...", // 不完整输入
"搜索:'OR 1=1--" // 对抗性输入
]
5. 扩展应用与未来方向
5.1 多skill协同优化
当前工具针对单个skill独立优化。下一步计划实现:
- 跨skill评估:检测相似skill的功能重叠
- 共享优化:将某个skill学到的prompt技巧应用到同类skill
- 组合测试:验证多个skill串联时的表现
这需要建立skill的元信息标注体系,例如:
markdown复制<!-- SKILL.md -->
categories: [search, information-retrieval]
dependencies: [web-access]
interface:
input: search_query
output: markdown
5.2 动态评估权重调整
固定评估标准可能陷入局部最优。计划引入:
- 自适应权重:根据用户实际使用数据动态调整评估项重要性
- 反馈学习:将用户手动修正记录为新的评估样本
- 多目标优化:平衡准确性、响应速度、成本等因素
python复制# 伪代码:动态权重算法
def update_weights(user_feedback):
for eval_item in evals:
if eval_item in user_feedback['issues']:
eval_item.weight *= 1.2 # 强化问题项
else:
eval_item.weight *= 0.9 # 弱化非关键项
这个项目给我的最大启示是:prompt工程正在从玄学走向科学。通过系统化的评估和自动化优化,我们终于可以像调试代码一样精确地调试自然语言指令。如果你也在为AI应用的不稳定输出头疼,不妨试试这种数据驱动的方法——它可能不会一次解决所有问题,但至少能让优化过程不再像在黑暗中掷飞镖。