深度研究 Agent 训练项目 — 测试题答案
请先独立作答,再查看答案!对应题目见 [[深度研究Agent训练项目_笔记]]
基础概念题
A1:labels 中 -100 的含义
-100 是 PyTorch CrossEntropyLoss 的忽略索引(ignore_index)。
在训练时,我们只希望模型学习"如何生成 assistant 的回复",而不需要学习 system prompt、用户问题、或工具返回结果。
因此对于非 assistant 角色的 token,将 labels 设为 -100,损失函数会跳过这些位置,不计算、不反向传播。
A2:LoRA 的核心思想与优势
核心思想:假设模型权重的"更新量"ΔW 是低秩的。将 ΔW 分解为两个小矩阵 B × A(B: [d × r],A: [r × d],r « d)的乘积,只训练这两个小矩阵,原始权重冻结。
与全量微调的对比:
| 维度 | 全量微调 | LoRA |
|---|---|---|
| 可训练参数量 | 100%(数十亿) | 约 0.1-1%(数百万) |
| 显存需求 | 极高 | 大幅降低 |
| 训练速度 | 慢 | 快 |
| 存储(checkpoint) | 完整模型大小 | 只存 LoRA 权重(几十 MB) |
| 灾难性遗忘风险 | 较高 | 较低(原权重冻结) |
A3:最多调用次数及限制原因
最多调用 4 次(最多 3 个功能性工具 + 1 个 finish)。
限制原因:
- 效率:SME 咨询场景需要快速响应,无限循环会拖慢速度
- 成本控制:每次工具调用都消耗 API 费用(搜索、读取)
- 防止幻觉循环:限制步数迫使模型学会在有限信息内整合答案,而不是无休止搜索
- 训练数据一致性:固定最大步数使训练数据格式统一,易于学习
A4:<think> 和 <tool_call> 的含义
<think>...</think>:模型的内部推理过程,用于分析当前状态、决定下一步行动。不直接对用户可见,是"思维链"(Chain of Thought)的载体。<tool_call>...</tool_call>:包裹工具调用指令,内容是 JSON 格式的工具名和参数,由系统解析并执行。
缺少 <think> 标签:会导致格式验证失败(quick_eval 评分为 0),因为系统设计强制要求先思考再行动。训练数据 build_format_boost.py 正是用于过滤这类缺少 <think> 的低质量样本。
A5:4 行业 × 6 问题类型示例
| 类型 | finance | catering | startup | smart_transport |
|---|---|---|---|---|
| policy | “小微企业贷款利率上限是多少?” | “餐饮店办理食品经营许可证需要哪些条件?” | “高新技术企业认定有哪些优惠政策?” | “网约车平台需要申请哪些资质?” |
| market | “2024年消费金融市场规模?” | “奶茶行业年增长率如何?” | “AI 创业赛道融资情况如何?” | “智慧停车市场空间有多大?” |
| competitor | “招商银行与建设银行小微贷款对比” | “喜茶与奈雪的茶商业模式差异” | “字节跳动与腾讯在 AI 投资上的区别” | “滴滴与高德打车的竞争优势” |
| calculation | “贷款 50 万、利率 4.5%、3年期,月供多少?” | “开一家 100㎡奶茶店,预计回本周期?” | “天使轮稀释 20%,估值如何计算?” | “日均 500 单货运,月营收预估” |
| risk | “小微贷款逾期有什么后果?” | “食品安全事故的法律风险” | “创业融资协议中的反稀释条款风险” | “网约车驾驶员事故责任归属” |
| expansion | “小贷公司如何拓展下沉市场?” | “餐饮品牌如何进行城市扩张?” | “SaaS 产品如何从 ToB 扩展到 ToC?” | “城市物流如何拓展同城配送” |
项目结构题
A6:tool_executor.py vs tool_definitions.py 的分工
tool_definitions.py:只包含工具的 JSON Schema 定义(工具名、参数名、参数类型、描述),用于告诉模型"有哪些工具、每个工具的参数是什么",即放入 system prompt 的工具文档。tool_executor.py:负责真实调用工具——接收解析好的工具名和参数,调用博查搜索 API、Jina Reader API,或执行数学表达式,返回结果字符串。
为什么分开?
遵循单一职责原则:Schema 定义可以被 LLM Prompt 构建和数据合成复用,执行逻辑只在推理时使用。如果需要更换搜索 API,只改 tool_executor.py 即可,不影响 Schema 定义。
A7:quick_eval.py vs full_eval.py 的区别
| 维度 | quick_eval.py | full_eval.py |
|---|---|---|
| 评测内容 | 只检查格式(<think> + <tool_call> 是否正确) | 格式 + 工具选择准确率 + 答案质量 |
| 速度 | 快(不执行工具,不调用 judge LLM) | 慢(需要执行真实工具调用和 LLM 打分) |
| API 消耗 | 低 | 高(搜索 API + judge LLM) |
| 使用场景 | 训练过程中快速验证模型是否"学会格式" | 最终评测,需要全面了解模型能力时 |
建议:每次训练完先跑 quick_eval,确认格式无误后再跑 full_eval,节省资源。
A8:build_format_boost.py 的作用
该脚本从训练数据中筛选出格式最严格规范的样本(必须同时包含正确的 <think> 标签和合法的 JSON <tool_call>),生成一个格式增强子集。
使用场景:当 quick_eval 显示格式得分很低时(如基础模型的 4/20),可以用这个格式增强数据集单独训练一轮,让模型先"学会格式",再用完整数据集训练工具调用和推理能力。相当于先教格式规范,再教内容。
代码理解题
A9:Loss Masking 代码解释
| |
完整解释:
- 遍历对话中每条消息
- 如果是
assistant说的话(思考过程 + 工具调用),将其 token id 加入labels,训练时模型需要学会生成这些内容 - 如果是其他角色(system、user、tool_response),用
-100填充labels,PyTorch 不对这些位置计算交叉熵损失 - 效果:模型只学习"在什么情境下应该说什么",而不是死记硬背系统提示词或用户问题
A10:工具调用格式判断
| |
判断:不符合规范
原因:
- 缺少
<think>...</think>标签——推理过程"我需要先搜索相关信息"应该放在<think>标签内 - 正确格式应为:
| |
分析与优化题
A11:格式提升比工具调用提升更容易的原因
本质差异:格式学习是模式匹配任务,工具调用是推理决策任务。
- 格式(4→20):模型只需学会"每次回复都要先输出
<think>...</think>,再输出<tool_call>...</tool_call>"——这是纯粹的序列模式,1140 条样本已经足够强化这个规律。 - 工具调用(0→2):模型需要理解"什么时候用哪个工具"、“何时停止搜索直接回答”——这需要深层语义理解和多步推理能力,1140 条样本对于 0.6B-1.7B 的小模型来说还不够。
结论:小模型学习浅层格式比深层推理容易,这也是为什么先用 quick_eval 验证格式的原因——格式是基础,推理是上层建筑。
A12:排查 calculator 工具不被调用的问题
按优先级排查:
数据分布:检查训练数据中
calculation类型问题占比是否太低(用validate_data_v2.py查看统计),占比过低会导致模型很少见到calculator的调用示例。- 解决:用
expand_seeds_with_llm.py专门扩充calculation类型的种子问题
- 解决:用
问题类型:检查测试问题是否真的需要计算(如果问题是"政策是什么",模型正确选择不调用 calculator)
工具定义:检查
tool_definitions.py中calculator的描述是否清晰,参数expression的格式说明是否明确格式问题:检查训练数据中
calculator调用的格式是否一致(expression 是否用标准数学表达式)模型容量:0.6B 模型可能不够大,升级到 1.7B 或 4B 尝试
A13:数据分布不均的问题与解决方案
问题:
- 模型会过度偏向金融行业的回答风格,在其他行业表现差
- 对餐饮/创业/智慧交通的专业术语和场景理解不足
- 评测时可能看起来还好(因为 finance 问题多),但实际应用中遇到非金融问题会失败
解决方案:
- 过采样:复制少数类样本(餐饮/创业/交通各随机复制到与金融同等数量)
- 欠采样:从金融数据中随机抽样,使各类均衡
- 数据增强:用
expand_seeds_with_llm.py专门为餐饮/创业/交通生成更多种子问题变体 - 加权损失:在
data_loader_v2.py中为少数类样本设置更高的 loss weight
最佳实践:目标是 4 个行业各 25%,6 种问题类型各约 16-17%,做到双维度均衡。
A14:DPO 及其解决的问题
DPO(Direct Preference Optimization):一种基于人类(或 AI)偏好的对齐方法。不需要独立的奖励模型,直接用"选择的答案 vs 拒绝的答案"的对比数据来优化模型,使模型更倾向于生成被偏好的回答。
数据格式:
| |
在本项目中解决的问题:
SFT(监督微调)只能让模型学习"如何模仿训练数据中的答案",但无法区分答案好坏。如果训练数据本身有噪声,模型会同样学习低质量答案。
DPO 可以解决:
- 答案准确性:训练模型偏好"引用来源正确的答案"而非"捏造来源的答案"
- 回答完整性:偏好"涵盖多角度分析的答案"而非"片面的答案"
- 格式一致性:在 SFT 已建立格式基础上,进一步强化高质量格式
在本项目的应用:可以用 build_before_after_judged_set.py 生成的"模型A错误、模型B正确"数据作为 DPO 的 rejected/chosen 对,进一步提升答案质量(从 2/10 向更高分数逼近)。