最近在做一个内部知识库的Agent,用Llama-3-8B做底座,拿几千条工具调用的对话数据做了LoRA微调。单轮工具选择准确率还行,但一旦涉及多轮对话,模型经常把上一个tool的结果当参数传给下一个tool,或者干脆自己编一个不存在的工具名。我确认过数据格式和system prompt都没问题,推理时temperature也降到0.1了。想问下各位大佬,这种多轮工具调用的“记忆混乱”一般是微调数据里缺少了某些负样本,还是说LoRA的rank和alpha设置得不合适?或者跟基座模型本身的多轮能力关系更大?求指点,孩子已经被这个搞了快两周了。
微调后的模型做Agent工具调用总跑偏,是数据问题还是训练参数没调对?
全部回复
共 38 条多轮跑偏大概率是负样本不够,得专门塞点“错误调用”让模型学会拒绝,参数倒不是主因。
八成是负样本太少了,多轮里得塞点故意传错参数的例子让模型学会拒绝。
这种问题我调RAG agent时也遇到过,后来发现纯粹是LoRA rank调太高(比如64)导致灾难性遗忘,把基座的多轮能力冲掉了。你试试rank降到8-16,alpha跟着减半,同时把训练数据里故意混入一些“错误调用后纠正”的负样本,让模型学会看到异常结果就停手。另外8B基座本身对复杂状态跟踪就弱,如果数据量不大,不如换个Qwen-2.5-7B或14B的base再试,实测多轮稳定性好不少。
说实话你这个现象我太熟了,之前用7B模型做类似任务也卡了大半个月。我个人感觉大概率不是LoRA参数的问题,rank和alpha只要不是特别离谱(比如rank=1或者alpha=64),对多轮行为的影响远没有数据分布来得大。你单轮准但多轮崩,典型的“上下文漂移”症状——模型在微调时见过的多轮样本里,可能工具返回结果和下一轮用户问题之间的关联模式太单一了,它没学会“工具结果要经过推理再决定怎么用”,只是死记硬背了“上轮输出接本轮输入”这个表面规律。
建议你先把训练数据里的多轮轨迹单独拎出来看,是不是有很大比例都是工具结果直接作为参数传入下一个工具,而缺少了那种“工具返回后需要先总结、再结合用户意图决定是否调用”的中间步骤。另外负样本很关键,我那时候加了大概10%的“错误调用但最后被纠正”的对话,以及一些“工具不存在时应该拒绝”的样本,效果提升特别明显。你还可以试试在推理时把system prompt里明确加上“只能用列表中的工具,如果工具名不在列表就回答不知道”,这能压掉一部分编造工具名的行为。
最后说句实话,Llama-3-8B本身的多轮跟随能力就一般,尤其是工具结果比较长的时候,注意力很容易被带偏。如果数据清洗过、负样本也加了还是不行,建议换Qwen2.5-7B或者干脆用同参数量的带工具调用预训练的模型,省很多事。两周时间不算长,别太灰心,这问题很常见。
我之前也踩过类似的坑,后来发现多轮跑偏大概率不是单一原因。你提到缺负样本这点很关键,LoRA微调数据里如果全是正例,模型很容易把“记忆上一个结果”学成默认行为,建议专门造一些工具返回异常或空值的样本进去。另外rank可以试试16到32之间,alpha跟着调大一点,有时候低rank会让模型对上下文敏感度不够。不过说实话,Llama-3-8B本身多轮指令跟随就偏弱,如果数据清洗没问题,可能真得考虑换更擅长对话的基座,或者加一层显式的状态管理缓存来兜底。
我之前做类似项目也踩过这个坑,多轮对话里工具结果串场的问题,大概率不是LoRA参数的事。你想想,单轮准确率高说明模型已经学会了工具选择的基本模式,但多轮调用涉及的是“状态跟踪”能力,这恰恰是8B模型比较薄弱的地方。我后来试过在数据里刻意加入一些“上一个tool返回了错误格式”或者“工具结果为空”的样本,让模型学会在这种情况下怎么处理,效果改善很明显。另外你可以检查下是不是训练数据里多轮对话的轮次太短,如果平均只有2-3轮,模型很难学到长上下文的依赖关系。还有一个偏门但有用的技巧,就是把工具描述改成更口语化的指令,比如“如果上个结果里没有xxx字段,就调用查询接口”,这样模型更容易理解边界条件。至于rank和alpha,我一般用16和32起步,但如果数据量才几千条,调高了反而容易过拟合,建议先固定住,重点折腾数据构造。最后想说,如果实在不行,可以试试在推理时给模型加一个“显式记忆”的prompt,把最近两轮的工具结果用结构化文本放在对话历史里,比让模型自己隐式记住靠谱多了。
说实话我第一反应是数据问题,多轮工具调用的负样本太关键了,模型没见过“上一步结果不该传给下一步”的例子,它就默认了所有参数都该从上下文里拿。你可以试试在数据里故意塞一些错误传递的case,标注成需要拒绝或纠正,LoRA rank和alpha倒不是首要怀疑对象。另外Llama-3-8B本身的多轮跟踪能力就一般,你也可以看看是不是上下文窗口被工具返回结果撑爆了,导致早期信息被截断。
这问题我太有共鸣了,之前做类似场景也卡了挺久。你试试在微调数据里刻意加一些“错误调用后模型如何纠正”的对话样本,纯正样本确实容易让模型养成瞎传参的惯性。LoRA参数我个人感觉不是主因,但rank可以往32以上拉一拉,alpha按2倍去设,有时候确实能改善指令跟随的稳定性。另外多轮记忆混乱也可能是基座模型对长上下文的注意力分配不行,建议把历史工具的返回结果在拼接时做个截断或摘要,别让无用信息干扰当前决策。
同款问题遇到过,最后排查下来是负样本不够,LoRA参数反而是次要的。你得在数据里故意塞一些“不该调用工具”或“参数类型不匹配”的例子,模型才能学会拒绝和纠错。另外试试把多轮历史对话直接拼进user消息里,别依赖模型自己记context,8B底座这块确实弱。
八成是负样本太少了,模型压根没见过错误调用长啥样,光调rank没用。
这问题八成出在数据上,多轮负样本太少了,模型没见过错的长啥样自然瞎编。
我遇到过类似问题,最后发现是多轮数据里缺少“纠错”样本,模型没学会区分上一轮的工具输出和当前轮的参数。建议你混入一些故意给错参数让模型修正的负例,另外LoRA rank别太小,我之前8调到32效果明显好了点。多轮能力基座确实有影响,但8B不至于这么拉胯,先查数据多样性吧。
说实话你这现象我调过类似的也遇到过,负样本确实关键,多轮里模型得学会区分“该用新输入”还是“沿用上轮结果”,建议你专门构造些工具返回异常或无关数据的样本喂进去。再一个LoRA的rank我个人觉得影响没数据大,但alpha可以试着往上拉到32或64看看,有时候收敛太狠反而把基座的多轮能力压没了。最后你可以对比下不加system prompt纯靠对话历史的few-shot效果,如果差距不大,就真得考虑换基座了,Llama-3-8B本身对长程工具状态跟踪就挺吃力的。
大概率是数据问题,尤其多轮里工具结果和下一轮参数之间的关联没学明白。你试试在负样本里混入“把上轮输出错误传给下轮”的场景,让模型明确知道这是错的。另外LoRA rank如果太小(比如8),多轮依赖关系可能学不进去,调到16或32看看。基座模型的多轮能力确实有影响,但8B在短上下文里应该够用,先别急着换模型。
数据里多塞点工具不存在和参数错位的负样本试试,这比调rank管用。
我之前也踩过类似的坑,最后发现是负样本不够——模型压根没见过“该拒绝调用”或“工具返回异常”的情况,导致它只能硬着头皮编。你试试在数据里混入一些故意给错参数、或让上一轮工具结果失效的对话,让模型学会“不信任”上下文。另外LoRA的rank我建议从16往上调,alpha跟着设成32,太低的话新知识学不进去,但太高又容易把基座能力冲掉,这俩得配着试。多轮记忆混乱有时候真不是参数锅,Llama-3-8B本身对长上下文的注意力分配就一般,你可以把每轮对话的tool result在prompt里单独分段并加个明确标记,比让它自己从历史里找要稳得多。
跟你遇到几乎一样的问题,后来我对比了下,发现多轮跑偏大概率是数据里缺少“纠错路径”的负样本。模型没见过“tool结果不该被当作参数”的例子,它就自己瞎编逻辑,光调rank和alpha救不回来。
我试过把单轮数据拆成多轮时,刻意加入“上一轮结果与当前query无关”的样本,准确率明显稳了。另外你确认下数据里工具名是不是足够多样?要是总那几种,模型容易偷懒记成固定套路。
基座模型底子弱倒是次要的,毕竟8B做复杂推理本身就吃力。可以先拿GPT-4或别的强模型跑一遍你的多轮场景,看它会不会也犯同样错,能帮你区分是数据问题还是模型上限问题。
这种多轮里把上次结果当参数、还自己编工具名的现象,我踩过类似的坑。大概率不是LoRA rank的问题,而是你训练数据里几乎全是“正确调用”的正样本,模型没学过“工具返回后该怎么接着走”的节奏。建议补一些多轮轨迹,特别是工具返回错误、参数缺失、需要追问的负样本。另外可以查下训练时是不是把历史工具结果也当成了可预测的文本,模型很容易学着去复制它。