2389 字
约 7 分钟
18
S22-A15 · 输出的长度控制:为什么它总写得太长

一份"帮我总结这段会议记录"的输出,模型给了八百字,而需要的是一句话结论加三条待办。反复要求"简短一点"之后,它变成六百字——因为"简短"是一个相对词,而模型对它没有绝对刻度。

这背后是一个更普遍的规律:凡是"程度"类要求都难以执行,凡是"形状"类要求都可以执行。"更专业些"、"更简洁些"属于前者,而"三段、每段一句、必含结论"属于后者。

长度控制的难点不在"要求它短",而在给它一个可判定的形状:几段、每段几行、要不要列表、必含哪几项。形状是可检查的,相对词不是。


1. 三种长度约束

约束 效果
相对词("简短") 弱,几乎无约束力
结构约束("三段,每段一句") 强,可检查
硬限制(max_tokens) 最强,但会截断

第一项之所以弱,是因为它把判断权交给了模型:而模型的训练数据里"简短"的样本本身就长短不一。

第二项的原理是"给模板":填一个三行模板比"写短一点"容易得多,因为它把"多长"变成了"填几个格子"。

// 可判定的形状 vs 不可判定的要求
弱:请简短总结,不要长篇大论
强:按以下格式输出,共三行:
    结论:一句话(≤40 字)
    依据:两到三条,每条一句话
    待办:谁在何时做什么(可为空)
// 强约束可以直接用正则/脚本校验,弱约束不能

2. 为什么模型倾向写长

原因 说明
训练偏好完整性 覆盖更多要点 = 更好的回答
缺少长度锚点 不知道"这段该多长"
结构未定 先写再组织,自然变长
回避取舍 都写上就不用决定哪个重要

第二项(缺锚点)有个直接的解法:给一个示例输出。示例的价值不在内容,而在它同时提供了长度、语气与结构三个锚点——比任何形容词描述都准确。

第四项最关键:写长常常是为了回避"哪个更重要"这个判断。所以要求"只保留一条最重要的",比要求"写短"更能压缩长度。

第三项也有解释力:没有预设结构时,模型边写边组织,而组织过程本身会产生冗余。

// 让模型做取舍,而不是做删减
弱:请精简到 100 字以内
强:只保留最需要管理层决策的那一个问题,其余全部省略
// 前者是压缩,后者是先选后写

3. 结构模板的四种粒度

粒度 例子
段落级 "分三段:现状、原因、建议"
句子级 "每段一句,不超过 40 字"
字段级 "输出 JSON,字段 fixed/why/next"
逐项级 "最多三条,每条一句话"

第三项最容易被机器消费:结构化输出天然控制长度,因为字段数量是固定的,每个字段的长度可以单独约束。

第二项(句子级)有一个实用尺度:中文一句话超过 40 字时,读者开始需要回看。所以"每句不超过 40 字"不只是风格要求,它是可读性的门槛。

第四项在"待办清单"这类场景里最有效:条数上限比字数上限更好执行,因为模型能数条数,不能精确数字数。

4. 硬限制与截断

手段 风险
max_tokens 截断在句中,输出不完整
提示里写"不要超过 N 字" 经常超
生成后裁剪 可能裁掉关键结论
分级生成(先要点后展开) 实现复杂

第三项(生成后裁剪)在实践中容易犯一个错:按字符数裁剪会把一个 JSON 或一段代码切成非法结构。所以裁剪只适用于自然语言,且应当按"句"而不是按"字"。

第一项最危险:截断的输出看起来"说完了",实际少了最后一句结论。而很多客户端不会提示"被截断"。

第四项是可靠做法:先让模型输出三条要点(短),再按需展开其中一条。这样长度控制发生在生成之前,而不是事后裁剪。

// 两段式生成:先短后长,长度可控
第一轮:只输出三条要点,每条 ≤ 20 字,不要展开
第二轮:针对"第 2 条"展开,限 150 字
// 好处:总量可控;坏处:多一次调用

5. 长度与质量的取舍

场景 长度倾向
决策支持 短(结论优先)
学习材料 长(有推导)
代码注释 短(说明为什么)
排障步骤 中(每步一句)

第三项(代码注释)常被写反:注释写成了"做了什么",而读者需要的是"为什么这么做"。这类注释越长越无用,因为它重复了代码本身。

第一项与第二项的差别不在"写多少",而在读者要什么:决策者要结论与依据,学习者要过程与推导。用同一种长度应付两类读者,两边都不满意。

长度控制还有一层"分层输出"的策略:给人看的摘要压短,给机器读的结构给字段。同一份内容两种形态,各自有各自的长度约束——用一份输出去满足两种读者,通常两边都不合适。

// 一份内容,两种输出
[摘要] 限三行,每行 ≤ 40 字,供人判断要不要细看
[结构化] JSON,字段固定,供下游程序消费
// 混在一起 → 人嫌长、机器解析不了

6. 排错:五种"控制不住长度"

现象 成因 处理方向
说"简短"后仍很长 相对词无刻度 给结构模板
每次都差不多长 无长度锚点 给示例输出
输出被截断 max_tokens 太小 分级生成
结构对了但内容空 模板过松 收紧字段要求
上一轮短这轮长 温度/采样波动 固定参数 + 校验

除了采样,上下文长度也会影响输出长度:上下文里塞了很多材料时,模型倾向于"多覆盖一点",因为它们看起来都相关。所以"短输出"往往要先"少给材料"。

第五项要说明:长度本身受采样影响,同一提示的两次输出长度可能差 30%。所以验收不能看一次,要看多次的分布。

// 长度验收:看分布而不是单次
跑 10 次同一提示,统计输出长度:
  若 P90 超过目标 1.5 倍 → 模板不够紧
  若长度方差很大 → 采样参数或提示有歧义
// 单次"看起来合适"不算通过

7. 边界:什么情况不该压长度

场景 为什么 做法
教学与解释 需要推导 允许长
复杂分析(多因素) 压缩会丢条件 用结构而不限字
代码生成 完整性优先 不限长度,限结构
用户明确要详细 需求就是长 不压

最后一条与"验收"有关的边界:长度约束应当写进自动化检查,而不是靠人看。一条正则(行数、字段数、字数上限)就能把"这次有点长"变成"这次不合格",而后者才会被修。

// 长度验收:把"看起来合适"变成可执行检查
def check(text: str) -> list[str]:
    errs = []
    lines = [l for l in text.splitlines() if l.strip()]
    if len(lines) > 8: errs.append(f"行数 {len(lines)} > 8")
    if any(len(l) > 60 for l in lines): errs.append("存在超长行")
    if "结论" not in text: errs.append("缺少结论")
    return errs

判断口径一句话:读者会拿这份输出去做什么。要"做决定",压到结论与依据;要"学东西",长度由推导决定,用结构控制而不是字数。


8. 自测

  1. 为什么"简短"这类相对词几乎无约束力?结构模板为什么更有效?
  2. 模型倾向写长的四个原因里,哪一个最关键?为什么"只保留一条最重要的"比"写短"有效?
  3. 四种结构粒度中,哪一种最容易被机器消费?为什么条数上限比字数上限更好执行?
  4. 为什么 max_tokens 截断最危险?"分级生成"如何避免这个问题?
  5. 为什么长度验收要看多次输出的分布而不是单次?
  6. 判断"该不该压长度"的那个问题是什么?
S22-A15 · 输出的长度控制:为什么它总写得太长
https://www.clxhxhhr.top/posts/6474/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。