Macaron-V1 把多种能力压进一次后训练,先分清各自的任务边界

文章导读
看到 Macaron-V1 把多种能力放进一次后训练,容易顺手想成“一个模型全包”。更稳的做法是反过来:先拿到未经转述的能力条目,按输入输出形态切成几堆任务,把堆与堆重叠的地方标出来,再给每堆写一条验收样例。这样后续调提示词时,能分清是 Macaron-V1 在某个任务上本来就弱,还是提示写法把 Macaron-V1 带到了另一堆任务的输出习惯上。公开的能力描述通常只有任务类型加一句原话,既不含边
📋 目录
  1. 一 把公开描述里的能力项抄成原始清单
  2. 二 按输入输出形态给任务分堆
  3. 三 找出堆与堆之间的重叠区
  4. 四 为每堆写一条验收样例
A A

看到 Macaron-V1 把多种能力放进一次后训练,容易顺手想成“一个模型全包”。更稳的做法是反过来:先拿到未经转述的能力条目,按输入输出形态切成几堆任务,把堆与堆重叠的地方标出来,再给每堆写一条验收样例。这样后续调提示词时,能分清是 Macaron-V1 在某个任务上本来就弱,还是提示写法把 Macaron-V1 带到了另一堆任务的输出习惯上。公开的能力描述通常只有任务类型加一句原话,既不含边界条件,也不含冲突说明,把原话抄成清单比凭印象分类更可靠。

处理顺序建议固定为四步:抄原始能力清单、按输入输出形态分堆、标注重叠区、给每堆写验收样例。适用场景是同一个模型承接多种任务、并且已经出现同类输入输出不稳定的情况;操作动作是把能力描述拆成可勾选的任务项,而不是继续无止境地改提示词;验证方式是用固定输入各跑一遍,只看输出形态是否落在预期那一堆;风险边界是能力清单本身可能滞后于实际权重,清单外的任务需要单独试,不能默认继承同一套提示词和同一套验收标准。

把公开描述里的能力项抄成原始清单

第一步不做分类,只做抄录。打开 Macaron-V1 的模型卡、发布说明、README 或控制台里的能力介绍页,把每一条能力按“任务类型 + 描述原话 + 出处页面”三列抄下来。抄录阶段有三条纪律:原话不改写,不把意思相近的两条合并,不在清单里写推断。遇到描述含糊的地方用“原文未说明”占位,不要自己补一句“应该也能做”。

# capability_raw.yaml —— 只抄原话
# 下面条目是格式示意,具体内容以你手上实际页面为准
- id: C-01
  task_type: 文本生成
  quote: 这里粘贴页面上的原句,一个字不改
  source: 模型卡 / 能力介绍页 URL
  note: ''
- id: C-02
  task_type: 多轮对话
  quote: 这里粘贴页面上的原句
  source: 同上
  note: 原文未说明是否限制轮数
- id: C-03
  task_type: 结构化输出
  quote: 这里粘贴页面上的原句
  source: 同上
  note: 原文未说明是否强制 JSON

这份清单的用途,是把“印象里的能力”换成可逐条对照的条目。执行位置放在仓库里的 docs 目录或表格工具中,跟着提示词版本一起提交;验证方式是通读一遍,确认每条都能指回一句原文,凡是指不回去的条目就先删掉。清单条目数量不必求多,能覆盖你实际要跑的几类任务即可。

按输入输出形态给任务分堆

按任务名字分堆容易重复,按输入输出形态分堆更可操作:看输入是什么、输出必须是自由文本还是一定形状的数据、是否需要跨轮携带状态。通常可以分成四堆——纯文本生成、多轮对话、结构化输出、判定打标。同一句能力原话可能同时落进两堆,先按主要输出形态归堆,重叠的部分留到下一步处理。

堆输入样例期望输出形态
纯文本生成把下面这段产品说明改写成一段摘要:……连续自然段,不带标题、不带项目符号
多轮对话第一轮给一段背景,第二轮追问“那第二点怎么处理”能正确承接上文指代,答案落在第二轮提出的问题上
结构化输出从这段文字里取出标题、时间、地点,按给定字段返回可直接解析的数据结构,字段齐全,无多余说明文字
判定打标这句话属于投诉还是咨询,只回一个标签单个标签词,不带解释、不带标点

每堆先固定一条最小可跑样例,写进自己的测试脚本当回归输入。样例要短,短到出问题时能一眼看输出形态变了没有;样例太长会把格式问题和内容问题混在一起。堆名建议直接作为请求日志里的一个字段,后面排查时能按堆统计输出形态的偏差。

找出堆与堆之间的重叠区

重叠区是最容易把提示词写歪的地方,因为同一个提示词里同时约束了两种输出习惯。下面几处是比较常见的:

  • 结构化输出 × 多轮对话:前面轮次已经返回过一版字段结构,后续追问时模型可能沿用旧键名或旧字段集合,出现字段漂移。干扰点在上下文里残留的那份示例结构。
  • 判分打标 × 纯文本生成:要求“只回一个标签”时,生成倾向会把标签扩写成一句判断语,还带上理由。干扰点在提示词里没有写死输出长度、没有明确禁止解释。
  • 结构化输出 × 代码生成:要求返回结构化数据时,代码块围栏或行内注释可能被一并输出;反过来在写代码的场景里强行套严格数据格式,又会把注释和空行吃掉。干扰点在两种输出习惯的默认格式不同。
  • 多轮对话 × 纯文本生成:多轮中某一轮要求“简短回答”,但前几轮的长回答已经把长度预期带偏,后面很难压回来。

对每处重叠写一行“触发条件 + 观察点”,跟着请求日志一起记录:请求 id、所属堆名、提示词版本、输出是否通过形态校验。验证方式很直接:同一个输入,用只约束一种形态的提示词和同时约束两种形态的提示词各跑一次,看输出落到哪一堆。如果两种写法结果明显不同,说明当前任务跨堆,建议拆成两次调用,而不是在一段提示词里同时压两个约束。

为每堆写一条验收样例

验收样例不比“写得好不好”,只比“形态对不对”。每条包含输入、期望输出形态、判定句;判定句要能直接回答是或否,不写“较为合理”“基本符合”这类无法执行的描述。

  • 纯文本生成 输入:一段两百字左右的产品说明加一句“改写成一段摘要”。期望输出形态:单个自然段。判定句:输出为单一自然段、不含标题与项目符号,视为达标;出现列表、小标题或以“以下是”开头,判不达标。
  • 多轮对话 输入:第一轮给三条背景,第二轮只问“第二条的例外情况是什么”。期望输出形态:指向第二条的答复。判定句:输出明确对应该条并且没有把三条全部重述,视为达标;答成“你没有提供背景”或把三条重新列一遍,判不达标。
  • 结构化输出 输入:一段含标题、时间、地点的文本,加上字段名清单。期望输出形态:可直接解析的数据。判定句:输出能被解析器一次性解析且字段集合与要求一致,视为达标;含围栏、注释或解析前的说明文字,判不达标。
  • 判定打标 输入:一句用户留言加“只回一个标签”。期望输出形态:一个约定标签。判定句:输出严格等于约定标签之一,视为达标;带解释、带标点或出现约定之外的词,判不达标。
import json

def check_structured(text, required_fields):
    # 只做形态校验,不评价内容质量
    try:
        data = json.loads(text)   # 有围栏或多条说明文字时这里会失败
    except json.JSONDecodeError:
        return False, 'not-json'
    missing = [k for k in required_fields if k not in data]
    if missing:
        return False, 'missing:' + ','.join(missing)
    return True, 'ok'

这段校验函数放在测试脚本里,每跑一次就把堆名、提示词版本和返回值写进日志。需要提醒的边界有两条:一是能力清单和模型实际行为可能不一致,清单只作为待测项来源,不作为结论;二是验收样例只覆盖输出形态,不覆盖事实是否正确,涉及事实的任务要另加一条人工核对,别把形态通过当成内容通过。