登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

Transformers 怎样用 no_repeat_ngram_size 减少重复片段

来源:17golang原创

时间:2026-11-15 12:50:16 493浏览 收藏

模型生成的文本如果反复出现同一小段,先别急着提高 repetition_penalty。在 Transformers 里,更直接的办法是设置 GenerationConfig.no_repeat_ngram_size:它大于 0 时,会限制同样大小的 n-gram 在生成序列中再次出现。可以把 3 作为起点,再根据文本长度和可读性调整。

官方地址:https://huggingface.co/docs/transformers/main/en/main_classes/text_generation

如果问题是连续词片段原样重复,优先尝试 no_repeat_ngram_size=3;如果问题是单词或词片段到处被偏爱,再考虑温和的 repetition_penalty。两者不是同一种约束。

重复片段为什么会再次出现

生成过程每一步都在候选 token 中选择下一个 token。模型可能因为上下文、采样概率或解码策略,多次走回已经出现过的短片段。这里的“重复”不是语义相似,也不是字符级查重,而是按 tokenizer 切出来的 token 序列观察固定长度窗口。

例如,假设 token 序列抽象成 [A, B, C, D, A, B, C],当窗口大小是 3 时,[A, B, C] 已经出现过,后面再次形成相同三元窗口就会被约束。中文一个词不一定对应一个 token,所以不要把 n 直接理解成“几个汉字”。

输入token序列、n-gram窗口、GenerationConfig和禁止候选token之间的关系说明图
图1:no_repeat_ngram_size 把生成序列划分为固定 token 窗口的静态说明图,不是模型运行截图。

先用 GenerationConfig 加上硬约束

参数可以直接传给 generate,也可以放进 GenerationConfig 统一保存。下面示例只展示配置关系;其中 no_repeat_ngram_size=3 表示同样的三 token 组合不能在输出中重复出现,max_new_tokens 仍然只负责长度上限。

from transformers import GenerationConfig

# 用生成配置集中保存长度与重复约束,便于不同请求复用
generation_config = GenerationConfig(
    max_new_tokens=96,
    no_repeat_ngram_size=3,
    do_sample=True,
    temperature=0.8,
)

# 将配置交给模型生成;输入张量应与当前 tokenizer 和模型匹配
output_ids = model.generate(
    **inputs,
    generation_config=generation_config,
)

# 只解码新生成的 token,避免把输入提示词误认为重复输出
new_ids = output_ids[:, inputs["input_ids"].shape[1]:]
text = tokenizer.batch_decode(new_ids, skip_special_tokens=True)

配置默认值通常来自模型配置;文档中 no_repeat_ngram_size 为 0 时表示不启用这条限制。把配置单独保存还有一个好处:出现重复时可以只改推理参数,不必重新训练或改动权重。

2、3、4 应该怎么选

参数越小,限制越硬。2 会禁止重复二元窗口,短文本也更容易触发,可能让句式显得不自然;3 通常能挡住连续短语回环,同时给常见搭配留出空间;4 更宽松,适合需要重复固定术语但又想抑制长片段复现的文本。

选择时要结合三件事:

  • 输出很短时,窗口太小会占用更多候选,先试 3 或不启用。
  • 输出很长且重复段落明显时,可以从 3 调到 4,再观察是否仍然回环。
  • 领域文本需要反复出现同一产品名、字段名或公式时,不要把“合法术语重复”误判为故障。
no_repeat_ngram_size、repetition_penalty、输出长度和可读性之间的参数边界说明图
图2:n-gram 硬约束与 repetition_penalty 的参数边界关系图,帮助理解调参代价。

它和 repetition_penalty 不是一回事

no_repeat_ngram_size 是离散的硬限制:达到重复窗口时,相关候选会被屏蔽。repetition_penalty 更像对已经出现过的 token 调整分数,参数为 1.0 时不产生惩罚。前者关心“这个固定组合还能不能出现”,后者关心“已经出现过的 token 还要不要继续偏爱”。

因此不要一开始同时把两个参数调得很重。更容易定位问题的顺序是:

  1. 先保持采样参数不变,只设置 no_repeat_ngram_size=3。
  2. 如果固定短片段消失但整体仍然绕圈,再小幅调整 repetition_penalty。
  3. 如果输出变得支离破碎,优先减小惩罚或把 n 从 2 调回 3/4。

约束过强时如何回退

常见症状是:输出突然提前结束、句子连接生硬、领域术语被刻意避开,或者短文本几乎无法继续生成。这不一定是模型坏了,而可能是当前上下文中可用候选被硬约束得太少。

可以按下面顺序回退:

# 先用较宽松的配置回退,避免同时改变多个因素
generation_config.no_repeat_ngram_size = 4
generation_config.repetition_penalty = 1.0

# 如果业务允许更长的自然表达,再重新设置长度上限
generation_config.max_new_tokens = 128

# 记录最终配置,方便把一次调参结果复用于同类请求
generation_config.save_pretrained("./generation-config")

如果仍然重复,说明问题可能不只是 n-gram 级别:提示词、上下文拼接、模型本身的生成能力和采样策略都值得单独排查。不要用这个参数替代事实一致性、格式校验或业务去重。

一张表记住调参边界

现象先看什么建议起点
连续短语原样回环固定 token n-gram 是否重复no_repeat_ngram_size=3
单个高频 token 到处出现是否需要降低某些 token 的偏好保持 n=3,再小幅尝试 penalty
术语被强行避开窗口是否过小、文本是否过短从 2 调到 3 或 4
输出提前结束或很碎硬约束是否挤压候选空间降低约束,单变量复查

相关问题

no_repeat_ngram_size=1 会怎样?

它会把单 token 重复也纳入限制,通常过于激进,除非你明确需要避免任何 token 再次出现,否则不建议作为通用配置。

它能保证段落语义不重复吗?

不能。它只针对 token n-gram 的重复,不能识别同义改写、相似句意或跨段落的主题回环。

为什么中文里 n=3 不等于三个汉字?

因为约束作用在 tokenizer 输出的 token 上,中文词、标点和特殊 token 的切分方式取决于所用模型。

结论可以收敛成一句话:先用 no_repeat_ngram_size=3 处理固定短片段回环,再根据文本长度、术语重复需求和可读性调整到 4 或关闭;只有在 token 偏好仍然失衡时,才把 repetition_penalty 作为第二个变量。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>