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 直接理解成“几个汉字”。

先用 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,再观察是否仍然回环。
- 领域文本需要反复出现同一产品名、字段名或公式时,不要把“合法术语重复”误判为故障。

它和 repetition_penalty 不是一回事
no_repeat_ngram_size 是离散的硬限制:达到重复窗口时,相关候选会被屏蔽。repetition_penalty 更像对已经出现过的 token 调整分数,参数为 1.0 时不产生惩罚。前者关心“这个固定组合还能不能出现”,后者关心“已经出现过的 token 还要不要继续偏爱”。
因此不要一开始同时把两个参数调得很重。更容易定位问题的顺序是:
- 先保持采样参数不变,只设置
no_repeat_ngram_size=3。 - 如果固定短片段消失但整体仍然绕圈,再小幅调整
repetition_penalty。 - 如果输出变得支离破碎,优先减小惩罚或把 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 作为第二个变量。
-
332 收藏
-
Golang · Go问答 | 2天前 | 连接池 · 性能排查 · database/sql · Go问答 · Go 连接池 MaxOpenConns MaxIdleConns database/sql sql.DB DB.Stats476 收藏
-
284 收藏
-
387 收藏
-
328 收藏
-
470 收藏
-
417 收藏
-
414 收藏
-
122 收藏
-
275 收藏
-
207 收藏
-
317 收藏
-
306 收藏
-
460 收藏
-
340 收藏
-
210 收藏
-
211 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习