大模型无限循环输出、重复生成文本:参数层面规避幻觉输出实战
摘要:面向大模型应用开发者的排障实战指南。全文以"现象 → 根因 → 参数 → 实战 → 方法论"为主线,系统讲解 12 个采样参数的作用机制、典型取值与风险,给出"复读机、无限死循环、幻觉编造"三大高频问题的可落地处方,并附 OpenAI、HuggingFace、vLLM 三套可直接复用的代码与 6 大平台的参数命名对照表。
一、引言:你迟早会遇到的三种"病"
把大模型接入生产环境后,最先翻车的往往不是"答错",而是"答得不像话"。在大量线上案例中,模型输出的故障形态可以归为三类,每一类都让工程师头疼:
1.1 复读机(局部重复)
同一句话、同一短语在回答里反复出现,像卡带的录音机,内容显得机械、低质,用户一眼就能看出"这是 AI 生成的"。
"这个方案的核心是降低成本,这个方案的核心是降低成本,这个方案的核心是降低成本......"
1.2 无限死循环(全局循环)
模型陷入生成循环,不断输出同一段文本,直到撞上 max_tokens 上限。在流式场景中,这种现象不仅让回答无法交付,还会持续消耗 token,账单不断攀升。
"用户您好,您的订单已发货。用户您好,您的订单已发货。用户您好,您的订单已发货......"
1.3 幻觉式重复(编造 + 自我强化)
模型在编造内容,而编出来的话又进入了下一轮生成的上下文,越编越自信,最终形成一套"自洽但错误"的文本。幻觉严格来说不是重复,但幻觉严重时往往伴随高频套话复读,二者常常同时出现。
**三种病病根相同:都发生在"概率分布"这一层。**这也是为什么参数治理是性价比最高的第一道防线------它直接作用于生成机制本身,而非事后补救。
二、根因:自回归解码为什么"刹不住车"
现代大模型(GPT、Claude、Llama、Qwen、DeepSeek......)本质上是自回归的:给定"用户输入 + 已生成文本",预测下一个 token 的概率分布,采样出一个 token 拼回序列,再重复这一过程。每一步都是一次赌博,赌错的代价会累积放大。
有四个机制性原因让模型容易"原地打转":
2.1 概率陷阱
当 temperature 过低时,softmax 分布极其尖锐,某个 token 的概率被推到接近 1。模型每次都选中它,于是复读。temperature=0 等价于贪心解码------它不采样,只取最高分,这是复读和死循环的最高发场景。
2.2 反馈回路
循环是自激的。模型输出"已发货",这个词进入上下文;下一步模型看到上下文里有"已发货",条件概率又把它推向"已发货"。循环一旦建立,就变成自我确认的闭环,越转越紧。
2.3 长上下文稀释
序列越长,注意力越分散,模型逐渐"忘掉"原始约束条件,退回最安全的低频/高频 token,开始灌水、重复。
2.4 训练与对齐的副作用
RLHF 阶段模型被训练得"温和、安全、爱总结",过度复述用户关键词成为常见的伪安全行为。这解释了为什么越"听话"的模型越容易复读。
核心认知:参数管的是"概率分布的形状",管不了"事实是否正确"。所以参数治"重复"立竿见影,治"幻觉"只能缓解------幻觉的根治必须靠工程手段(详见第六章)。
三、参数全景:12 个旋钮与它们的作用位点
所有采样参数可以分成三个家族,分别卡在解码循环的三个环节上:
-
惩罚与偏置族(作用于采样前的 logits):repetition_penalty、frequency_penalty、presence_penalty、no_repeat_ngram_size、logit_bias
-
随机性族(作用于采样):temperature、top_p、top_k、min_p、seed
-
硬约束族(作用于停止):max_new_tokens、stop
| 参数 | 家族 | 机制(一句话) | 典型值 | 主要风险 |
|---|---|---|---|---|
| temperature | 随机性 | 除以 T 再归一化,T 越低分布越尖锐 | 事实 0.3--0.7 / 通用 0.7--1.0 / 创意 0.9--1.3 | 过低→复读;过高→幻觉 |
| top_p | 随机性 | 只保留累积概率 ≥ p 的最小 token 集合 | 0.9--0.95 通用 / 0.7--0.85 事实 | 与 temperature 同调互相抵消 |
| top_k | 随机性 | 只保留概率最高的 K 个 token | 40--50 宽松 / 10--20 确定 | 过小→生硬复读 |
| min_p | 随机性 | 保留概率 ≥ max×min_p 的 token,动态裁剪 | 0.05--0.1 | 支持框架较少 |
| seed | 随机性 | 固定采样随机源,结果可复现 | 任意整数 | 服务端不保证复现 |
| repetition_penalty | 惩罚 | 对出现过的 token 的 logit 除以大于 1 的系数 | 1.05--1.2(1.0 = 关) | 误伤数字、代码、编号 |
| frequency_penalty | 惩罚 | 按出现次数成比例惩罚 | 0--2,常用 0.3--0.8 | 过高→回避主题词 |
| presence_penalty | 惩罚 | 出现过即一次性惩罚,与次数无关 | 0--2,常用 0.2--0.6 | 过高→话题跳跃 |
| no_repeat_ngram_size | 惩罚 | 硬禁止相同 n-gram 再次出现 | 3--4(0 = 关) | 打断合理结构重复 |
| logit_bias | 惩罚 | 对指定 token_id 加减偏置 | −2 ~ −5 压噪声 | 需查 token_id,维护成本高 |
| max_new_tokens | 硬约束 | 硬性截断新生成 token 数 | 按任务定 | 过短→回答被切 |
| stop / stop_strings | 硬约束 | 出现指定字符串立即停止 | 按任务定 | 误设→提前截断 |

上图把"解码循环七步"与"参数干预点"画在了一起:惩罚族在采样前压低已经出现过的 token,随机性族决定分布的形状,硬约束族给循环装上"刹车"。图中数值为工程经验区间,不同服务商默认值与命名略有差异,请以官方文档为准。
四、实战一:治"复读机"(局部重复)
4.1 症状识别
同一短语/句子在回答中 2--3 处重复出现,但整体能正常结束。这是最常见的形态,也是参数治理收益最大的场景。
4.2 处方(按优先级)
-
repetition_penalty = 1.05--1.2 (HuggingFace / vLLM 系)或 frequency_penalty = 0.3--0.8(OpenAI 系):惩罚族直接压低已出现 token,见效最快;
-
temperature ≥ 0.7:打破尖锐分布的概率陷阱;
-
仍复读再上硬手段 no_repeat_ngram_size = 3;
-
若复读的是特定口头禅("哈哈""......"),用 logit_bias 定点压制。
4.3 代码示例:OpenAI 系
python
from openai import OpenAI
client = OpenAI()
resp = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "写一段 200 字的产品介绍,不要重复。"}],
temperature=0.7,
top_p=0.9,
frequency_penalty=0.5, # 治复读主力
presence_penalty=0.3, # 鼓励引入新词
max_completion_tokens=512,
seed=42, # 实验时固定,便于对照
)
print(resp.choices[0].message.content)
4.4 代码示例:HuggingFace 系
python
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
tok = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-7B-Instruct")
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen2.5-7B-Instruct", torch_dtype=torch.bfloat16
).to("cuda")
inputs = tok("写一段 200 字的产品介绍,不要重复。", return_tensors="pt").to("cuda")
out = model.generate(
**inputs,
max_new_tokens=512,
do_sample=True,
temperature=0.7,
top_p=0.9,
top_k=50,
repetition_penalty=1.15, # 治复读主力
no_repeat_ngram_size=0, # 默认关;顽固复读时设 3
pad_token_id=tok.eos_token_id,
)
print(tok.decode(out[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True))
翻车点(重要) :惩罚族会误伤合法重复------数字(把 "123" 写成 "124")、代码符号、列表编号、新闻里反复出现的关键词。务必从最小值起步(1.05 / 0.3),结构化输出场景慎用,宁可配合工程检测也不要拉满。
五、实战二:治"无限死循环"
死循环是复读的极端形态,处理顺序必须是"先兜底、后治本"。直接调参而不先加闸,循环期间每一秒都在烧 token。
5.1 第一步:兜底(立刻止血)
-
max_new_tokens:硬性截断,账单止损的底线;
-
stop / stop_strings:在语义完整处收尾(如 "\n\n"、<|endoftext|>、</s>);
-
流式场景做实时重复检测:输出流中一旦检测到高频重复即中断请求。
5.2 第二步:治本
repetition_penalty 1.1--1.2 + temperature 0.8--1.0,从概率上消除循环形成的条件。这两项组合能显著降低"原地打转"的概率。
5.3 流式循环检测器(可直接使用)
python
from collections import deque
class LoopDetector:
"""在流式输出中检测 n-gram 循环:同一 n-gram 重复次数超阈值即中断。"""
def __init__(self, n=4, threshold=3):
self.n = n
self.threshold = threshold
self.seen = {}
self.window = deque(maxlen=n)
def push(self, token_id: int) -> bool:
"""返回 True 表示检测到循环,应中断生成。"""
self.window.append(token_id)
if len(self.window) < self.n:
return False
key = tuple(self.window)
self.seen[key] = self.seen.get(key, 0) + 1
return self.seen[key] >= self.threshold
detector = LoopDetector(n=4, threshold=3)
for token_id in streaming_output: # 伪代码:逐 token 流式
if detector.push(token_id):
stream.abort() # 中断,返回已生成部分
break
5.4 更稳的信号:概率异常抬升
循环 token 的选择概率会异常升高(接近 1)。监测近窗口平均概率相对前期窗口的抬升幅度,超过阈值即判定循环。工程上建议把 n-gram 检测与概率抬升检测叠加使用,误报率更低。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RjFDeXze-1789139876943)(https://internal-api-drive-stream.larkoffice.com/space/api/box/stream/download/authcode/?code=YjJmOWU5NjA3YjA3MjRkZjlkN2ZmNTE2MjQxMzZmZjFfY2U3YjY5ZjY3MDY2MjVhYzVlZTgwNWZhNTI5MTk0ZTRfSUQ6NzY4MzkyMTA0MDc3MDQwMzUxOF8xNzg5MDUyNDUyOjE3ODkxMzg4NTJfVjM)
六、实战三:治"幻觉"
6.1 先说清边界
幻觉是"模型不知道答案却硬答"。参数只能改变分布的"确定性",不能注入"知识"。因此对幻觉要"参数缓解 + 工程根治"双管齐下。
6.2 参数能做什么
-
temperature 降到 0.2--0.5,top_p 收到 0.7--0.9,或直接贪心解码:让模型少"发散",只选最高置信度的词;
-
但注意跷跷板效应:温度降得过低,又诱发复读。事实任务推荐组合是 temperature=0.3、top_p=0.8,必要时叠加 frequency_penalty=0.2 平衡。
6.3 工程根治路径
-
RAG / 检索增强:让模型基于检索到的材料作答,而不是凭记忆编造;
-
self-consistency 自洽投票:同一问题用较高温度生成 N 个答案,提取答案投票取多数------编造的内容通常互不一致,会被多数票淘汰;
-
事后校验:对生成内容中的数字、引用、专名做检索/规则校验,不合格即重写或拒答。
七、不同平台的参数命名对照
同一概念各平台命名不同,下表为常用平台对照(支持度以各服务商最新文档为准):
| 概念 | OpenAI | Anthropic Claude | HuggingFace | vLLM | Ollama |
|---|---|---|---|---|---|
| 温度 | temperature | temperature | temperature | temperature | temperature |
| 核采样 | top_p | top_p | top_p | top_p | top_p |
| Top-K | ---(聊天模型) | top_k | top_k | top_k | top_k |
| 重复惩罚 | --- | --- | repetition_penalty | repetition_penalty | repeat_penalty |
| 频率惩罚 | frequency_penalty | --- | --- | frequency_penalty | frequency_penalty |
| 存在惩罚 | presence_penalty | --- | --- | presence_penalty | presence_penalty |
| 禁 N-gram | --- | --- | no_repeat_ngram_size | --- | --- |
| logit 偏置 | logit_bias | --- | --- | logit_bias | --- |
| 停止序列 | stop | stop_sequences | stop_strings | stop | stop |
| 长度上限 | max_completion_tokens | max_tokens | max_new_tokens | max_tokens | num_predict |
| 随机种子 | seed(best-effort) | --- | seed | seed | seed |
| 相对阈值 | --- | --- | min_p | min_p | min_p |
注意细节:OpenAI 新一代模型用 max_completion_tokens 取代了 max_tokens;DeepSeek、Qwen 等国产模型 API 基本走 OpenAI 兼容协议,可直接套用 OpenAI 列的参数名。
八、调参方法论:别靠玄学
参数调优最怕"一顿乱调,效果靠运气"。以下六步流程可复用到任何模型与框架:
8.1 调参六步流程
-
先定性症状:是局部复读、死循环、幻觉还是贫乏?不同症状处方完全不同,用错参数会互相打架;
-
一次只动一个参数:记录改动前后的输出对比;
-
固定 seed 做对照:不固定种子,你无法区分"参数生效"和"随机波动";
-
小步回归测试:用一个覆盖典型输入的评测集(20--50 条)跑回归,别拿单条输出下结论;
-
自动化搜索:把参数交给 Optuna / 网格搜索在评测集上寻优,人只负责定义评分;
-
认清参数边界:重复可以靠参数解决 80%,幻觉靠参数只能缓解------参数解决不了的问题,交给 RAG、校验、投票这些工程手段。
8.2 vLLM 落地示例
python
from vllm import SamplingParams
params = SamplingParams(
temperature=0.7,
top_p=0.9,
top_k=50,
repetition_penalty=1.15, # 治复读主力
frequency_penalty=0.2, # 可选,进一步压制高频
presence_penalty=0.2, # 可选,鼓励新话题
min_p=0.05, # 动态裁剪长尾
max_tokens=512,
stop=["\n\n"],
)
8.3 症状速查表
| 症状 | 首选动作 |
|---|---|
| 局部复读 | repetition_penalty 1.1 或 frequency_penalty 0.5;temperature 提到 0.7 以上 |
| 无限死循环 | max_new_tokens + stop + 流式检测先兜底,再 repetition_penalty 1.1--1.2 |
| 幻觉编造 | temperature 0.3 + top_p 0.8;工程侧 RAG / 自洽投票 |
| 内容贫乏 | presence_penalty 0.3--0.6;temperature 略升到 0.9--1.0 |
九、总结:最佳实践清单
复读、死循环、幻觉,本质都是"概率分布"的病。参数是你手里最便宜的药。上线前请对照以下清单逐项检查:
* [ ] 所有生成接口都设置了 max\_new\_tokens 上限与 stop 序列
* [ ] 流式场景接入了 n\-gram / 概率抬升双重循环检测
* [ ] 事实类任务使用低温度(0\.2--0\.5)与收紧的 top\_p(0\.7--0\.9)
* [ ] 结构化输出(JSON / 代码)场景避免了过强的重复惩罚
* [ ] 调参时固定 seed,一次只动一个参数,并用评测集回归
* [ ] 涉及事实、数字、引用的场景,接入了 RAG 或事后校验
请记住两条底线:惩罚会误伤结构,低温度会诱发复读;参数的尽头是工程,幻觉的根治在检索与校验。调参如同调琴------一次动一根弦,用 seed 做节拍器,用评测集当耳朵。