做这个项目之前,我一直觉得“AI Agent 能跑起来”才是最难的部分,后来真正上了线才发现,让一个 Agent 稳定、可靠地持续变好,才是真正烧脑的环节。尤其是当你面对的是 Harness 这种既要约束模型行为、又要应对复杂真实请求的框架时,最直接的痛点其实是:用户的每一条不满意反馈都在“白给”,而我们的系统却始终反应迟钝。于是我们做了这样一套基于用户反馈的模型微调加 Prompt 优化双轨流程,把 Agent Harness 变成一个有自我进化能力的闭环系统。这篇文章就是把整个流程的设计思路、数据管道、迭代方法、踩坑记录都摊开来讲,适合那些正在做 Agent 类产品、被线上反馈淹没却不知道如何下手的工程师参考。
1. 为什么需要自我进化机制:先看清 Harness 的定位
1.1 Agent Harness 在系统里到底管什么
很多同学第一次听到“Harness Engineering”会以为是什么花哨的装备,其实它就是把 Agent 框在一个可控的执行环境里。通俗点说,Harness 就像给一个能力很强但性格不稳定的员工配了一位资深项目经理——模型负责出主意,Harness 负责让主意在正确的轨道上落地。它管理的内容包括会话状态、工具调用路由、上下文管理、权限边界、以及策略注入。换句话说,模型是大脑,Harness 是神经系统和四肢。
在实际项目里,Harness 层做的事情非常琐碎但关键。例如,用户问“帮我把这份列表按时间排序再汇总一下”,模型本身可能只会回答“好的,我可以这样做”,但如果 Harness 没有正确解析工具调用、没有把排序结果包装成用户可以理解的摘要,整个交互就是失败的。我们初期踩过很多坑,以为是模型能力不够,后来发现大部分问题其实出在 Harness 的编排策略上——比如工具返回结果太长,直接把上下文塞爆;比如多个工具并行调用时,结果顺序错乱。
Harness 的核心价值在于“可控”。模型是概率输出的,同一个 Prompt 每次生成的内容都可能不同,而 Harness 能把这种行为框在一个可接受范围内。比如规定模型必须按照某个 JSON Schema 输出工具调用参数,如果不符合就解析失败重试;比如设置上下文窗口的使用上限,超出就做压缩或摘要。这些规则保障了 Agent 在大多数场景下不会彻底放飞自我。但是问题也来了:这些规则是谁定的?答案通常是工程师在开发阶段拍脑袋定的。一旦上线,用户请求的分布千变万化,静态规则很快就会和真实场景脱节。
1.2 静态编排撑不住动态场景,自我进化不是锦上添花
我见过不少 Agent 项目的做法是:上线后发现某个问题,就由开发手动修改一段 Prompt 或者加一条 Harness 规则,然后重新发版。这种做法在 Demo 阶段没问题,但在真实业务里完全不可持续。用户反馈是 7×24 小时不断流入的,靠人工盯帖子、盯工单、盯系统日志来定位问题,存在三个致命缺陷。
第一,响应速度太慢。一个反馈从用户提交到被工程师看到,再到修改 Prompt、测试、发版,往往需要好几天。这段时间内,大量同类用户持续遭遇同样糟糕的体验。第二,人工修改的覆盖度极其有限。线上不断出现新类型的失败,很多是极其小众的长尾场景,开发团队根本不可能为每一种情况都手工设计规则。第三,人工优化缺乏统一衡量标准。每个人改 Prompt 都有自己的偏好,可能某次修改让 A 类请求变好了,却让 B 类请求变差了,而这种副作用往往要等上线很久之后才暴露。
自我进化机制的意义就在于把整个改进过程从“人工驱动”变成“数据驱动”。用户反馈本身就是天然的、免费的标注数据,它直接告诉我们模型在哪些地方让用户不满意了。把这些反馈结构化、标签化之后,既可以用来看清楚问题的分布,也可以通过两种路径去消耗数据:一种是快速路径,通过自动化的 Prompt 优化去修正 Harness 层的指令策略;另一种是深度路径,通过模型微调去修改模型本身的行为偏好。两条路径的结合,让整条链路不再依赖人的实时介入,而是形成一条“感知-分析-优化-验证”的自动闭环。
想强调的是:自我进化不等于让 Agent 完全自治地乱改自己。进化必须在受控的 Harness 框架里进行,每一轮优化都要有明确的触发条件、实验验证和回滚机制,否则很容易出现“越改越歪”的失控状态。我们后面所有内容,都是围绕“可控地进化”这一点展开的。
2. 反馈信号的设计与采集:进化机制的燃料
2.1 显式反馈与隐式反馈怎么分工
自我进化机制的起点不是模型,也不是 Prompt,而是反馈信号。没有高质量且持续稳定的反馈流,后面的优化全部是无源之水。反馈从采集方式上可以分成显式和隐式两类,两者必须配合使用。
显式反馈指的是用户主动表达态度的信号。最典型的就是聊天气泡下面的点赞/点踩按钮,或者用户在对话框旁边输入一条简短评价,比如“回答不对”“太啰嗦了”。显式反馈的优点在于意图明确,可靠性高;缺点是覆盖率低,大多数用户根本懒得点。尤其是一个 Agent 回答得中规中矩时,用户基本不会给出任何积极反馈,导致正样本稀疏。
隐式反馈则是从用户行为里“猜”出来的态度信号。举例来说,用户复制了 Agent 的某段回答,很可能是这段内容对他有用;用户点击了 Agent 推荐的工具或内容,说明这条推荐是对的;用户在一次回答后立刻关闭了对话窗口,可能就是不满意;用户连续两次编辑同一个回复,说明生成内容不符合他的需求。这些信号不需要用户主动操作,覆盖率高,但噪声也大,需要仔细定义阈值和结合上下文判断。
在实际项目中,我们同时采集这两类信号,但采用的处理策略完全不同。显式反馈直接进入高优先级处理队列,因为它的置信度最高;隐式反馈则会先做一轮规则过滤和交叉验证,例如“复制行为”这个信号只有在上下文窗口确实包含 Agent 生成的代码或地址时才被记为正面反馈。“重新生成”这个信号我们同时结合其后的最终采纳结果,如果用户点了重新生成之后没有继续操作,则记为中性的体验差信号。
2.2 构建可用的反馈标签体系
原始反馈只是零散的满意/不满意,但如果你想把反馈用于 Prompt 优化和模型微调,就必须把“不满意”拆解成可操作的具体问题。我们在项目里设计了一套轻量标签体系,核心是回答“用户到底对什么不满意”。
这套标签体系分成了几个大类。意图理解错误:Agent 没有正确理解用户的目的,回答方向跑偏了。信息缺失:回答内容不够完整,用户需要的信息没有被覆盖。事实错误或幻觉:生成的内容和客观事实不一致,或干脆编造信息。格式不合格:用户要求表格,Agent 给了一段长文本;用户要 JSON,Agent 回了 Markdown。工具调用失败:Harness 没能正确触发、解析或执行工具调用,导致任务中断。风格与态度问题:语气、详细度不符合用户预期。
标签怎么打?我们采用三层策略。第一层,规则打标。比如检测到输出格式不符合要求、工具返回 error 状态码,这类问题可以直接用确定性规则标记。第二层,模型自动打标,也就是用一个独立的小模型对反馈样本进行多标签分类,这里不需要特别复杂的模型,普通的分类模型或者当前的基模就好。第三层,用户主动表态。如果用户点踩时选了“回答错误”等预置原因,直接采用。这套标签体系是整个进化机制的关键,因为后续的 Prompt 优化和微调都需要“带有明确问题类型”的样本,而不是笼统的坏样本。
还有一个容易被忽略的点:每条反馈需要带上对应的会话上下文快照,至少要包含完整的用户问题、Agent 当时的回复、Harness 输入给模型的那份 Prompt 片段、以及工具调用的过程记录。没有上下文,标签做得再准,也无法用于后续优化。
2.3 反馈质量管理:清洗与去重
反馈信号天然带着大量噪声,尤其是隐式反馈。直接拿脏数据去做优化,轻则浪费计算资源,重则把模型带偏。反馈质量管理这步做不好,后面所有环节都是失衡的。
首先要过滤掉的是“无效反馈”。有些用户会连续在同一轮对话里点多次踩,可能只是手滑;有些用户根本不使用 Agent 的核心能力,只是单纯地乱输入;还有一些反馈内容长度不足、与对话主题毫无关联。我们用一套简单的规则做初筛:反馈文本长度不低于一定阈值,且不能只包含表情符号;同一会话内短时间内重复性质相同的反馈只保留一条;对话轮的上下文缺失超过一半的,丢弃。
其次要做内容脱敏和合规处理。用户反馈里可能包含电话号码、地址、姓名等私人信息。这些数据在进入训练管道之前必须经过脱敏处理。我们直接采用实体识别加替换的方式,把所有手机号、邮箱、身份证号、地址替换为占位符。这里提醒一句:这一步千万不要省,因为微调数据一旦把用户隐私带进去,模型生成时可能把这些信息“背”出来,这是重大安全事故。
最后是去重。线上会遇到大量近似重复的反馈,例如几十个用户都在问同一种报表导出的问题,回答都是格式不对。如果不做去重,模型会严重偏向这些高频问题,导致长尾能力退化。我们的做法是做语义聚类去重,用嵌入向量对反馈样本做粗聚类,再限制同一个簇在一个训练批次中的样本数量上限。这样既保留了高频问题的代表性,也不至于让它彻底淹没低频问题。
3. 从反馈到训练数据:数据管道的具体做法
3.1 反馈如何转化为训练样本
反馈经清洗和标签化之后,还只是“问题描述”,距离模型训练数据的标准格式还有一步。这条转化管道的核心是把用户反馈变成模型能学的东西。不同路径需要不同格式的样本,这里重点说三种最常用的。
第一种是偏好对样本,也是直接偏好优化或奖励模型最常用的数据形态。一个样本包含同一个用户问题下的两个回答:一个是被用户嫌弃的“拒绝回答”,一个是经过验证的“偏好回答”。挑战在于,用户往往只给出了负面反馈,偏好回答从哪来?我们通常从两个渠道获取:一是其他真实用户对同类问题的满意回答;二是让更擅长该任务的模型针对失败原因进行修正生成。对于后者,我们还会加入人工抽检,确保修正后的回答没有引入新的错误。
第二种是修正样本,主要服务于监督微调。它的核心思路是把“失败案例”变成“修正案例”。具体操作方式是:拿到一条失败对话,保留原始用户问题,用人工或更强模型重写一遍完整的期望回答,然后把重写后的回答作为监督目标。修正样本的优点是简单直接,易于大规模生成;缺点是如果重写质量参差不齐,会让模型学到不稳定的输出风格。
第三种是行为轨迹样本,专门用于 Harness 层的优化。这一类的特点在于重写目标不是最终回答文本,而是模型决策的过程,比如正确的工具调用顺序、正确的参数提取方式、正确的上下文取舍。我们会在反馈样本中标记工具调用失败类标签,然后重跑一遍该任务,记录新的正确轨迹,形成“用户问题+期望工具调用序列+期望最终输出”的三元组。
这些样本统一进入数据仓库,记录来源、标签、时间、所属模型版本等元信息。别小看这一步,后续做效果归因时,数据来源不明会造成极大的排查困难。
3.2 数据配比与采样策略
训练数据不是把反馈样本一股脑丢给模型就完事,数据配比直接决定了优化后模型的实际表现。我们最早犯过一个错误:把大量反馈修正样本堆在一起微调,结果模型在反馈密集的类型上表现大幅提升,但在普通业务请求上却出现了明显的退化,说话方式也变了。后来我们引入了严格的数据配比策略。
第一,基础能力数据必须占大头。无论反馈样本多么珍贵,模型自身的通用能力不能被破坏。我们在微调数据里保留了大量的通用指令数据、领域常识数据,这部分通常占整体训练数据量的 60% 以上。第二,反馈相关数据控制在合理份额。我们把所有反馈修正样本和偏好对放在一起,整体占 25% 左右,并确保其中每个细分问题类型不超过整体 5%。第三,任务特定正样本占到剩余份额。这里的正样本来自历史表现优秀的高满意度对话,它的作用是稳住模型在某些优秀场景的表现,防止微调过程把这些能力冲淡。
采样策略上也有一些细节值得分享。高频问题我们要控制住数量,低频长尾问题要保证至少出现若干次。我们的做法是基于标签体系做分层采样,每个标签类别内保证最小样本数量,类别内再按语义多样性排序采样。这样处理后的训练集在业务分布上会比原始反馈集健康得多。
3.3 质量门槛与人工抽检
自动化的数据管道产出的训练样本,质量一定不是均衡的,必须设置质量门槛。我们的做法是双重过滤加人工抽检。
双重过滤的第一重是规则过滤,主要检查格式和内容完整性。比如偏好对中两个回答完全一致,或者修正样本重写后的回答仍然包含明显幻觉内容的,直接丢弃。第二重是模型过滤,用一个质量评估模型对所有训练样本打分,评估维度包括:回答是否完整、是否忠于上下文、是否符合用户意图。只有分数超过阈值的样本才进入最终训练集。
人工抽检的比例虽然不能太高,但绝对不能没有。我们保持每周抽检一批新增样本,按问题类型分层抽取 100 到 200 条,由团队内不同角色分别看,然后对“该样本是否可用于训练”和“重写答案是否比原始答案更优”两个问题做标注。如果某类标签下人工认可率低于 85%,我们就认为这一类样本的质量不可靠,会暂时关闭该标签的数据流入并排查原因。
很多人会忽略抽检的价值,觉得有自动化过滤就够了。但我的经验是,自动过滤只能挡住明显的坏样本,却挡不住“看起来没问题但隐含文化偏见”或“重写风格与产品调性不一致”的软性问题,这些只能靠人眼判断。
4. Prompt 优化的自动迭代:轻量进化路径
4.1 自动 Prompt 优化的核心逻辑
Prompt 优化和模型微调并不是非此即彼的关系。在实际工程节奏里,我们通常优先做 Prompt 优化,因为它的成本低、周期短、可解释性强,而且可以直接作用在 Harness 层,不需要重新部署模型。
自动 Prompt 优化的核心思想可以用一个循环来概括:给定一个固定的评估集,让一个“优化器模型”分析当前 Prompt 在评估集上的失败案例,生成若干候选 Prompt 变体,然后在评估集上对全部候选 Prompt 做一次批量评估,保留效果最好、且未引入明显副作用的一个,进入下一轮迭代。
这个思路听起来很朴素,但实际落地时有几个关键细节决定了成败。第一,评估集必须固定且具有代表性。如果评估集不稳定,每一轮之间就没有对比基础,你根本无法判断是 Prompt 变好还是运气变好。第二,优化器模型不能只盲目改写,它必须能够获得“当前 Prompt 的失败样本 + 失败原因分析”的信息,否则它只会做一些同义替换式的无效改写。第三,候选 Prompt 必须保留一定随机性,每次生成多个变体,从中选择最优,而不是只生成一个。
在实际项目里,我们会在每一次迭代循环中做如下操作:先把评估集上的失败样本汇总,按照问题类型分组;然后构造一段“反思输入”,包含当前 Prompt 全文、失败案例、失败原因分析、历史优化记录,交给优化模型生成 5 到 10 个 Prompt 变体;接着并发生成所有变体在评估集上的输出结果,用多维度评分函数打分;最后选择得分最高且与当前 Prompt 差异可控的变体作为新的候选。
4.2 实现一个可落地的 Prompt 迭代循环
这里用一个简化的伪代码来描述我们的 Prompt 自动迭代循环,方便没有接触过类似机制的同学理解整个流程:
# 简化版 Prompt 自动优化循环 def auto_optimize_data_flow(initial_prompt, eval_set, optimizer_model, scorer, max_iterations=10): current_prompt = initial_prompt for step in range(max_iterations): # 1. 在当前 Prompt 下评估 results = run_evaluation(current_prompt, eval_set) failures = filter_failures(results) # 2. 如果失败样本过少,则停止 if len(failures) < threshold: break # 3. 构造反思输入并生成候选 Prompt reflection = build_reflection(current_prompt, failures, history) candidates = optimizer_model.generate_candidates(reflection, num=8) # 4. 批量评估候选 Prompt best_candidate = None best_score = -inf for candidate in candidates: cand_results = run_evaluation(candidate, eval_set) score = scorer.evaluate(cand_results) if score > best_score and not has_regression(cand_results, results): best_candidate = candidate best_score = score # 5. 收效显著则更新,否则提前终止 if best_candidate and best_score - scorer.baseline(results) > min_gain: current_prompt = best_candidate else: break return current_prompt这个循环的关键在于has_regression这步,它比较候选 Prompt 评估结果和历史基线,如果某个类别的得分明显下降,即使总分提升也不采纳。这一步能防止 Prompt 为了在总体上拿高分而牺牲特定用户群体。
在工程实现上,评估集的规模不需要很大,我们一般在 200 到 500 条之间,关键是覆盖面广,每条样本都要有明确的问题分类。跑一轮循环大概只需要几百次模型调用,成本可控。Prompt 优化的一个天然优势是它在 Harness 内部完成,不涉及模型权重变化,所以回滚极其容易——只要把 Prompt 恢复成上一个 commit 就行了。
4.3 评估指标怎么选才不会走偏
Prompt 优化的效果好不好,评估指标说了算。指标设计不当,很容易出现“跑分很漂亮,上线却很惨”的情况。我们实践下来,评估体系必须是多层次、多维度的,不能只看单一指标。
首先是任务成功率。这个指标最直接,Agent 是否完成了用户的目标。在一些工具调用场景,可以用“是否在限定步骤内成功执行工具并返回结果”来判定。其次是输出格式合规率。Harness 对输出格式有硬性要求,格式不合格就可能导致下游解析失败。然后是用户可见的质量维度,包括信息完整性、事实一致性、语气合理性。这部分我们用一个大模型评估下游模型输出,用 1 到 5 分制打分。
有一点必须提醒:大模型评估员,也就是 LLM-as-Judge,并不是万能的。它在对比两个回答时,经常更倾向于“更长、更像人”的那个,哪怕事实上另一个更简洁准确。我们在评估维度里加入了“简洁性”这一项,并且明确要求评估模型先给理由、再给分数。还有,评估模型本身也会偏袒某些表达风格,因此我们会定期更换评估模型的版本,并用人工标注校正分数。
最重要的是,评估集不能一成不变。每当发现某类新问题开始频繁出现,我们就往评估集里添加对应样本。这样,评估集本身也会随系统进化而更新,避免整个优化过程陷入“自我感觉良好”的状态。最终,我们知道 Prompt 到了什么水平,是否该启动下一层级的模型微调。
5. 模型微调路径:重度进化手段
5.1 选 LoRA 还是全参微调
Prompt 优化能够修正一部分行为,但遇到真正需要“模型自身能力”的场景,它就会撞到天花板。比如,某个领域的专有术语和表达偏好,靠一段 Prompt 是没法真正内化到模型行为里的。这时候就必须启动模型微调。
模型微调的第一步是选择微调方式。全参数微调在数据不足、算力有限、且希望频繁回滚的场景下显得过于笨重——每次都要训练一个新完整模型,存储成本高、迭代周期长。因此我们通常选择 LoRA 这类参数高效微调方法。LoRA 的核心思想是在原始权重旁边加一圈低秩矩阵,训练时只更新这圈小矩阵,最终推理时把矩阵合并回原始权重或者动态加载,不对原模型带来不可逆的修改。
LoRA 的好处非常直观。第一,训练成本极低,在先前的大模型上做一次 LoRA 微调,用少量显卡就能跑完;第二,可插拔性极强,同一个底座模型可以同时挂多个不同的 LoRA 分支,按业务场景自由切换,也就是说同一套基础设施可以服务多个定制能力;第三,回滚极其方便,不满意就换回原来的基底模型。
LoRA 的关键参数也在这里集中说一下。秩和缩放系数的组合是最主要的影响因素,秩一般在 8 到 64 之间,我们需要根据数据量做选择。数据量小时用较小的秩,比如 16;数据量大时可以用较大的秩,比如 32 或 64。缩放系数一般设置为秩的 2 倍或与秩相同,典型配置是r=16, alpha=32。学习率我们常用 1e-4 到 2e-4 之间。训练轮数则更敏感,LoRA 特别容易过拟合,常规是 1 到 3 轮,跑完每轮都存一个 checkpoint,方便后续选最优。
5.2 微调训练集的构建与配比
模型微调数据的构建方式与 Prompt 优化不同,它不依赖线上实时信号,而是把之前积累的反馈样本重新组织成标准训练格式。这里说的标准格式,是指符合模型训练模板的对话格式。我们以 ChatML 风格为例,每个训练样本包含system、user、assistant三种角色,完整地还原一段对话上下文。
配比上要非常小心。我特别提醒一下偏好对与修正样本的配比。纯粹使用修正样本,模型会学会“复述标准答案”,但面对开放式问题时可能缺少判断力。纯粹使用偏好对,则训练信号相对稀疏且不稳定。我们的做法大致是 70% 修正样本、20% 偏好对、10% 真实优秀对话样本。这个比例不是拍脑袋,而是经过多组实验比较后得出的相对均衡值,既能让模型快速学会新行为,又不至于丢掉原有能力。
微调时还有一个容易忽视的问题:灾难性遗忘。模型在专门数据上训练太猛,它会产生“回灌效应”,把源领域的能力压下去。具体表现可以是通用对话能力下降或基础常识出错。我们解决这个问题的方法有三个。第一,在训练数据中加入 10% 到 20% 的通用指令数据作为“记忆锚点”。第二,采用较小的学习率和较少的训练轮数,用保守训练策略。第三,在训练过程中保留每个 epoch 的 checkpoint,评估时重点关注基准通用能力指标是否下降,一旦下降超过阈值就停止训练,选择上一个 checkpoint。
5.3 微调上线后的回滚与灰度
微调版本上线,不能一上来就全量放量。我们通常会把一个 LoRA 训练产物挂在 Harness 后面,采用灰度的方式逐渐放量。灰度切分的维度可以按用户 ID 分流,也可以按请求类型或业务场景切分。
这里有一个具体的实践流程。假设我们合并出一个微调后的模型权重,我们在网关层配置权重切换:10% 的请求流量走新模型,90% 走旧模型,并实时对比两边的关键指标。这里的关键指标不是泛泛的“用户满意度”,而是更细的:任务完成率、工具调用成功率、单轮平均交互次数、驳回和重试比例、以及用户显式差评比例。只有这些指标都优于旧模型,我们才会逐步把流量从 10% 提高到 30%、50%、再全量。
全量放量后也不等于万事大吉。我们会保留一个新版本和旧版本的双通道日志拉取能力,持续观察一个自然周左右,确认没有明显回退后,才把旧线路的权重彻底删除。如果中途发现问题,立刻把流量切回旧模型。整个操作在设计上要足够轻量,因为模型优化是一个反复迭代的过程,每一次失败后的回滚都要做到分钟级完成。
LoRA 微调同时还要考虑线上推理的工程实现。合并权重的推理方式耗时更短,适合高并发场景;但代价是每次切换版本都要重新加载参数。我们团队自己的选择是短路径直接合并,中路径采用动态挂载,具体要看你们的推理框架支持程度,灵活取舍。
6. 双轨合并:Prompt 优化与模型微调如何协同
6.1 两条路径的边界与叠加风险
很多团队在推进时容易陷入一个误区,就是认为 Prompt 优化和微调可以同时进行、并行迭代、快速叠加收益。但实际做下来,这两条路径同时放开,往往会让你难以判断效果到底来自哪边,甚至会造成行为冲突。
举例来说,你在 Prompt 中加入了“回答前先确认用户意图”的规则,同时在微调数据里也大量强化了这类行为。结果就是模型在大部分请求中都会先做一轮冗长的确认,哪怕有些请求意图已经非常明确,反而破坏体验。这其实是“过度纠正”的典型表现。更隐蔽的冲突是风格上的:Prompt 要求简洁作答,但微调数据里的人工重写答案偏偏是细致风格,模型内部可能会分裂。
因此我们制定了一条原则:同一时期只放开一条优化路径。如果当前问题更偏向 Harness 和指令层面的错误,比如输出格式、工具调用步骤、上下文理解,那就先做 Prompt 优化。如果当前问题更偏向模型的事实性、风格、领域偏好,那就停下来固定 Prompt,切到微调路径。等微调收敛、稳定上线后,再重新审视 Prompt 是否需要跟着微调结果做一次适配。
这条策略让整个系统的变化保持“单变量”,也让效果归因变得简单。否则,当线上指标波动时,你根本说不清是 Prompt 的问题还是微调权重的问题。工程迭代最怕不是没有改进方向,而是不知道问题出在哪一环。
6.2 版本管理与效果归因
双轨机制下的版本管理,远比直接训练模型要复杂。我们为每一轮迭代建立了一条完整的版本链,记录了当时的 Prompt 版本、模型版本、训练数据集版本、评估集版本,以及评测结果。这个版本链直接决定你是否能“回到昨夜那个运行良好的状态”。
实际操作中,我们把 Prompt、模型、数据集每一份都当成独立的可回滚文件看待。Prompt 存入代码仓库,跟踪每次提交的差异。数据集用数据版本管理工具管理,每一个训练集都有唯一的哈希标识。模型自然不用多说,每一个 checkpoint 都会带上对应的训练元信息。线上跑的是哪一套组合,对应的是哪个版本链,全部在配置清单里写清楚。
一旦线上出现明显的指标回退,我们的排查流程是:先看最近 24 小时内哪些版本组合发生了变化,再把变化前后两组配置放到在线的影子评估集上去对跑一遍,定位到具体哪个组件引起回退。如果没有严格的版本管理,这一步几乎不可能快速完成,你可能需要同时排查几个月来所有改动,那种场面非常痛苦。
效果归因还有一个技巧:每次只调整一个维度。比如这一轮我们只动 Prompt,微调版本保持不动,那么线上效果若有变化,就基本可以归因到 Prompt 层面上。这种谨慎归因的方式牺牲了一些迭代速度,但大大提升了系统的稳定性和可持续演进能力。在整个自我进化机制中,稳定性比短期刷分重要得多,因为进化是一个长期过程,你不可能每次都在一团乱麻里缝缝补补。
7. 常见问题与排查实录
7.1 问题速查表
这里把我们在项目实战中遇到的高频问题归纳成一张速查表,按照“现象—可能原因—排查方法—解决方案”的格式组织,方便大家直接对照。
| 现象 | 可能原因 | 排查方向 | 解决方案 |
|---|---|---|---|
| Prompt 优化后线上好评率下降 | 评估集与线上分布不一致 | 对比评估集与线上请求语义分布 | 按线上采样扩充评估集,补充新问题类型 |
| 微调后模型通用能力下降 | 数据配比失衡或训练轮数过多 | 检查训练集配比,观察通用评估集得分 | 加入通用数据锚点,降低 epoch,退回前一个 checkpoint |
| 同一条用户问题出现不同回复 | 未约束解码参数或 Prompt 过拟合 | 检查 temperature 设置和 Prompt 中是否过度指定细节 | 增加解码参数确定性,精简 Prompt 冗余内容 |
| 用户点踩但无法定位具体原因 | 标签体系覆盖不足,反馈信息过少 | 分析反馈文本与对话上下文相关性 | 细化标签,增加人工复核流程 |
| 工具调用失败问题反复出现 | Prompt 和微调同时围绕该行为叠加修正 | 查看版本链中两边变更时间点 | 固定单一路径迭代,另一条路径保持冻结 |
| 优化后长尾场景反而变差 | 高频问题样本占据训练集中过大比例 | 检查反馈采样和去重参数 | 使用分层采样加聚类约束,控制类别比例 |
| 评估模型打分与用户感受不一致 | 评估维度不完整或评估模型版本过旧 | 人工抽样对比评估输出和用户反馈 | 增加人工校正集,升级评估模型并校正分数 |
这张表并不能覆盖所有问题,但它提供了一个通用排查框架。遇到问题时,不要只盯着模型输出本身,更要去检查整个反馈链路和数据管道是否健康。
7.2 避坑经验与实录
最后聊几个我花了不少学费才换来的经验,希望能帮后来的人少走弯路。
第一个经验是,不要迷信自动优化循环的“自动”二字。自动 Prompt 优化看起来可以完全无人值守地迭代,但实际上它需要非常频繁的人工干预,只不过干预点从“改 Prompt”变成了“审查数据质量和评估结果”。我们没有让循环完全自动运转几周不闻不问,而是在每轮迭代后强制加入一个人工确认环节,确认当前最优 Prompt 是否真的符合产品语义。经过一段时间后,这个确认成本会随着数据质量提升而慢慢降低。
第二个经验是,用户反馈里的“坏样本”比例比你想象的高得多。我们发现线上点踩的样本中,有相当一部分其实并不是 Agent 答错了,而是用户自己诉求表达不清、或用户对产品预期有偏差。这类样本如果进入训练集,会让模型变得越来越“顺从”,甚至开始迎合用户的不合理要求。我们后来专门加了一个类别标签叫作“无法判定的反馈”,这类样本只做存档,不参与任何训练。
第三个经验是,评估模型自身的漂移问题。我们早期一直使用同一个小版本评估模型做评分,后来发现它给出的分数越来越高,但人工抽查却发现生成质量并没有同步提升,最后调查确认是评估模型偏好发生了变化,导致同样的输出在新旧版本上得分差异明显。自那以后,每当我们替换评估模型,都会在固定的黄金测试集上重新校准打分,确保前后对比口径一致。
还有一个值得记录的细节是,几次迭代之后,我们把“Prompt 回滚”做成了非常快速的动作,复杂度缩小到一个配置文件切换,这带来的收益远远超出想象。曾经有一次线上新 Prompt 虽然平均分提升了,但在某个用户群体中引发了严重误解,我们在一分钟内就完成了回滚,几乎没有造成任何实际损失。做进化机制,最重要的不是每次都确认进化方向正确,而是确保一旦发现自己走错方向,能以最低代价退回来。进化动力小的退路没有保障,大胆尝试也会变成一场豪赌。
在实际操作中,我也越来越感受到,所谓自我进化机制并不是一个花里胡哨的“全自动 AI”,它更像是一套精心设计的工程流程,把人类反馈、数据治理、模型训练、在线实验这几块有机地串联起来,让每一次模型的进步都是建立在可量化、可解释、可回退的基础上。这条路需要持续打磨反馈质量,需要克制地选择优化路径,更需要敬畏线上系统的稳定性。如果你也正准备在自己的 Agent 系统中搭建这样一套反馈闭环,希望这些踩坑经验和代码思路能帮你节省几周的调研时间,让你的进化机制一开始就站在稳妥的地基上。