WeLM 上手做中文改写,先把输入长度和输出格式固定下来

文章导读
第一次用 WeLM 做中文改写,建议先把两个变量冻结:单次输入的原文长度,和输出要用的字段结构。风格、术语白名单先不动,跑顺了再逐个放开。多数「每次结果都不一样」的观感,来自提示里没给边界。
📋 目录
  1. 壹 把一条中文改写需求拆成指令、原文、约束三段
  2. 贰 用同一段原文跑 200 字、500 字、1000 字三档输入
  3. 叁 在输出里固定字段名,逐条核对格式有没有被守住
  4. 肆 把守不住格式的用例单独存档并标出输入特征
A A

第一次用 WeLM 做中文改写,建议先把两个变量冻结:单次输入的原文长度,和输出要用的字段结构。风格、术语白名单先不动,跑顺了再逐个放开。多数「每次结果都不一样」的观感,来自提示里没给边界。

先把提示拆成指令、原文、输出约束三段,再用同一段素材跑 200 字、500 字、1000 字三档输入,对比输出完整性、漏改和自行扩写。输出侧用固定字段名约束结构,逐条核对字段有没有被守住,守不住的样本单独存档,记下输入长度、任务类型、失败表现和复现次数。提示约束只能降低格式漂移的概率,不能保证每次命中,需要靠记录判断哪些长度必须拆开提交。

把一条中文改写需求拆成指令、原文、约束三段

把整段需求挤成一句话丢进去,模型很难分清哪部分是待改写的正文、哪部分是要求。三段式的做法是让每一段只承担一件事,出问题时也能定位到是哪一段引起的。

【指令】
把【原文】改写成更通顺的中文,不改变事实、数字、观点和人名,只调整句式、语序和重复用词。
风格:书面、简洁。

【原文】
<<<
(此处粘贴待改写的正文)
>>>

【输出约束】
只输出一个 JSON 对象,键名固定为 rewritten、changed、kept、uncertain,顺序不变,
不要输出 JSON 以外的任何文字,不要用代码块包裹。
rewritten:字符串,改写后的正文。
changed:字符串数组,每条不超过 30 字,最多 3 条。
kept:字符串数组,原样保留的术语、数字、专有名词,没有就填空数组。
uncertain:字符串数组,含义不明、无法确定改法的地方,没有就填空数组。

三段各自放什么、不放什么:

  • 指令段放角色、任务动作、改写范围和风格,不放开头的原文,避免模型在读到任务说明前先按猜测生成半句。
  • 原文段只放待改写文本,并用定界符包住;不放字数要求和字段说明,否则这些要求本身可能被当成待改写的句子一起改掉。
  • 输出约束段只放字段名、字段顺序、值类型、长度上限和禁止项;风格描述留在指令段,两处都写容易互相冲突。

风格、任务类型(改口语、改公文、压缩成摘要)和术语白名单属于可替换项,一次只动一处,否则结果变化时说不清是哪个变量造成的。

用同一段原文跑 200 字、500 字、1000 字三档输入

输入长度是第二个容易出问题的变量。准备同一主题的素材,截成 200 字、500 字、1000 字左右三份,用同一份提示模板跑,除长度以外不改任何东西。字数用 wc -m 粗略核对:

wc -m draft_200.txt draft_500.txt draft_1000.txt

用 -m 而不是 -c,是因为 -c 统计的是字节数,一个中文字符在 UTF-8 下通常占 3 个字节,看字节数容易判断错。截取时保持段落完整,别从句子中间切断,否则后面分不清漏改是长度造成的还是残句造成的。

三档按下表逐档记录,每格写具体现象和位置,不要只写「正常」「异常」:

输入档位输出完整性是否漏改是否自行扩写
200 字rewritten 是否覆盖原文全部句子指出未改动的句子在原第几段输出字数明显多于原文即记一次
500 字另看段落顺序有没有被打乱同上注意有没有新增的解释性句子
1000 字另看结尾段落是否被截断同上注意有没有补出原文没有的信息

三档连起来看,目的是找拐点:200 字和 500 字都完整、1000 字开始漏改或自行扩写,那么分界就在这两档之间,处理方式是拆成两段分别提交,或者把改写要求进一步收窄。具体从哪一档开始走样,取决于原文结构、段落长度和当时的模型行为,需要自己跑一遍看。

WeLM 上手做中文改写,先把输入长度和输出格式固定下来

在输出里固定字段名,逐条核对格式有没有被守住

命名约定越死,核对越省力。建议固定成几条:一律小写英文加下划线,不用驼峰;顺序为先正文、后改动说明、再保留项和存疑项;值类型固定,正文用字符串,说明类一律用数组;空值用空数组,不用 null,也不省略键。改模板时只改字段的值和说明,要改字段名就整体升一个版本号,比如在文件名里标 v2,别在同一套记录里混用两种命名。

跑完一轮按清单逐条核对:

  1. 输出里是否只有约定的四个键,开头有没有多出「以下是改写结果」这类说明。
  2. 键名是否逐字一致,有没有出现 rewritten_text、Rewrite、rewriteResult 之类的变体。
  3. 键的顺序是否和约定一致,部分解析逻辑对顺序敏感。
  4. 数组字段是否真的返回数组,有没有把三条改动压成一句话。
  5. 没有内容时是否返回空数组,而不是返回 null 或直接省略键。
  6. 整段输出有没有被代码块围栏包住,导致解析失败。

机械核对可以交给 jq。把模型原始回复存成 reply.json:

cat reply.json | jq -e 'has("rewritten") and has("changed") and has("kept") and has("uncertain")'
cat reply.json | jq -e '(.rewritten|type=="string") and (.changed|type=="array")'
cat reply.json | jq -e 'keys'

第一条只验证字段在不在,第二条验证值类型,第三条把实际键名打印出来对照。这三条都不检查语义,改写质量仍然要人看。格式被破坏时,把原始回复、当次提示词、输入字数和运行时间存在同一个文件里,例如 logs/format_break_001.md,不要只截一段贴到聊天记录,后面检索不到上下文。

把守不住格式的用例单独存档并标出输入特征

成功用例记一遍就够了,守不住格式的样本才值得单独留档。每条失败样本按固定列记录,表头不要中途改,攒起来才能横向比较。

列名记录内容
输入长度wc -m 得到的字符数,以及是否做了分段提交
任务类型改写、缩写、改成口语、改成公文等,一次只写一种
失败表现字段缺失、字段改名、多出说明文字、漏改、自行扩写,尽量抄一段原文片段
复现次数同一提示词、同一输入、不改参数重跑 N 次里出现几次,分母写清楚

复现次数这一列最容易记糊。分母是同一输入不改参数重跑的次数,比如 3 次里出现 2 次就写 2/3;中途调了温度、长度上限或提示词,那属于另一条记录,不能算进同一分母。

存档时再补一段输入特征,写明这段原文是否含列表、是否含表格、数字是否密集、是否含专有名词、段落数是多少,这几项常和格式被破坏同时出现。文件名带上长度和任务类型,例如 fail_input500_list_note.md,之后按文件名就能筛出同类样本。记录表一开始只有几条不必急着归纳,跑过一段时间再回看,更容易判断哪些长度需要拆开提交、哪些字段名总被模型改写。