Skip to content
🔗 分享本题
查看我的学习进度 →

岗位特点

  • 强调文心一言应用
  • 深入考察AI基础理论
  • 重视Agent架构设计
  • 三轮面试层层深入

高频面试题

百度 Q1:大模型为什么会重复生成?如何治理?

大模型重复生成概率回路原因与提示解码运行时分层治理图解

🧠 图解记忆: 重复是概率回路越滚越强;提示定边界、解码加约束、运行时检测,且要防止惩罚过强。

💡 答案要点

题目: 为什么LLM会出现复读机现象(重复生成相同内容)?如何从模型原理和工程实践两方面解决?

答案要点:

复读机现象:

用户: 介绍一下北京
模型: 北京是中国的首都,北京是中国的首都,北京是中国的首都...

产生机制:

  1. 自回归特性

    P(w_t | w_1, w_2, ..., w_{t-1})
    
    当前词只依赖历史,如果历史包含重复模式
    → 模型倾向于继续重复
  2. 注意力坍塌

    python
    # Attention权重高度集中在某几个token
    attention_weights = [
        [0.01, 0.01, 0.95, 0.01, 0.01, 0.01],  # 第3个token权重0.95
        [0.01, 0.01, 0.01, 0.94, 0.01, 0.01],  # 第4个token权重0.94
        ...
    ]
    # 导致模型陷入局部最优,不断重复高权重token
  3. Temperature过低

    python
    # Temperature → 0
    probs = softmax(logits / temperature)
    # 分布极度尖锐,总选概率最高的词
    # "北京" → "是" → "中国" → "的" → "首都" (循环)

解决方案:

方案1: Repetition Penalty (最常用)

python
def apply_repetition_penalty(logits, input_ids, penalty=1.2):
    """
    惩罚已出现过的token
    penalty > 1: 降低已出现token的概率
    """
    for token_id in set(input_ids):
        # 如果logits[token_id] < 0,除以penalty会更负(概率更低)
        # 如果logits[token_id] > 0,乘以penalty会更小(概率降低)
        if logits[token_id] < 0:
            logits[token_id] *= penalty
        else:
            logits[token_id] /= penalty

    return logits

# 使用
from transformers import GenerationConfig

config = GenerationConfig(
    repetition_penalty=1.2,  # 推荐1.1-1.5
    temperature=0.7,
    top_p=0.9
)

output = model.generate(input_ids, generation_config=config)

方案2: No Repeat N-gram

python
def no_repeat_ngram(generated_tokens, ngram_size=3):
    """
    禁止重复的N-gram
    例如: 禁止"北京是中国"连续出现2次
    """
    ngrams = {}

    for i in range(len(generated_tokens) - ngram_size + 1):
        ngram = tuple(generated_tokens[i:i+ngram_size])
        ngrams[ngram] = ngrams.get(ngram, 0) + 1

    # 如果某个3-gram出现>1次,下次生成时禁止
    return ngrams

# Hugging Face实现
output = model.generate(
    input_ids,
    no_repeat_ngram_size=3  # 禁止3-gram重复
)

方案3: Diversity Penalty

python
# Beam Search + Diversity
output = model.generate(
    input_ids,
    num_beams=5,
    num_beam_groups=5,  # 分5组
    diversity_penalty=1.0,  # 组间差异性惩罚
    temperature=0.7
)

# 原理: 强制不同beam组探索不同路径
# Group 1: "北京是..."
# Group 2: "作为首都..."
# Group 3: "位于华北..."

方案4: 修改Attention机制

python
class AntiRepetitionAttention(nn.Module):
    def __init__(self):
        super().__init__()
        self.attention = MultiHeadAttention()

    def forward(self, q, k, v, generated_tokens):
        # 标准attention
        attn_weights = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(d_k)

        # 对已生成token的attention降权
        for pos in generated_tokens:
            attn_weights[:, :, pos] *= 0.5  # 降低50%

        attn_weights = F.softmax(attn_weights, dim=-1)
        output = torch.matmul(attn_weights, v)

        return output

方案5: 后处理检测与重试

python
def detect_and_retry(text, model, prompt, max_retries=3):
    """检测重复,重新生成"""

    # 检测连续重复
    words = text.split()
    repetition_rate = count_repetitions(words) / len(words)

    if repetition_rate > 0.3 and max_retries > 0:
        # 重复率>30%,提高temperature重新生成
        new_text = model.generate(
            prompt,
            temperature=0.9,  # 提高随机性
            top_k=50
        )
        return detect_and_retry(new_text, model, prompt, max_retries - 1)

    return text

def count_repetitions(words):
    """统计重复词数"""
    from collections import Counter
    counts = Counter(words)
    return sum(c - 1 for c in counts.values() if c > 1)

综合实战方案:

展开 Python 代码示例(61 行)
python
class AntiRepetitionGenerator:
    def __init__(self, model):
        self.model = model

    def generate(self, prompt, max_length=512):
        # 配置多重防护
        config = GenerationConfig(
            max_length=max_length,

            # 防重复参数
            repetition_penalty=1.2,      # 惩罚重复token
            no_repeat_ngram_size=3,      # 禁止3-gram重复

            # 采样策略
            do_sample=True,
            temperature=0.7,
            top_p=0.9,
            top_k=50,

            # Beam Search多样性
            num_beams=5,
            num_beam_groups=5,
            diversity_penalty=1.0,

            # 长度惩罚(防止过短或过长)
            length_penalty=1.0,
            min_length=20,
        )

        # 生成
        output = self.model.generate(
            self.tokenizer.encode(prompt, return_tensors="pt"),
            generation_config=config
        )

        text = self.tokenizer.decode(output[0], skip_special_tokens=True)

        # 后处理检测
        if self.has_severe_repetition(text):
            # 重试,提高temperature
            config.temperature = 0.9
            output = self.model.generate(...)
            text = self.tokenizer.decode(output[0])

        return text

    def has_severe_repetition(self, text):
        """检测严重重复"""
        words = text.split()

        # 检查连续重复
        for i in range(len(words) - 5):
            if words[i:i+5] == words[i+5:i+10]:
                return True

        # 检查整体重复率
        unique_ratio = len(set(words)) / len(words)
        if unique_ratio < 0.5:  # 独特词<50%
            return True

        return False

效果对比:

方法重复率流畅性成本
无防护40%⭐⭐⭐⭐1x
Repetition Penalty5%⭐⭐⭐⭐1x
+No Repeat N-gram2%⭐⭐⭐1x
+Diversity Penalty1%⭐⭐⭐⭐2x (Beam)
综合方案<0.5%⭐⭐⭐⭐1.5x

面试话术:

示例表达(仅在能用本人经历或可复现实验佐证时使用): "LLM复读机源于3点:1)自回归特性导致重复模式自我强化2)Attention坍塌到少数token 3)低温采样陷入局部最优。解决用5层防护:1)Repetition Penalty=1.2惩罚已出现词2)No Repeat 3-gram禁止短语重复3)Diversity Penalty让Beam组探索不同路径4)修改Attention降低重复token权重5)后处理检测重试。实测重复率从40%→<0.5%,几乎消除。百度面试必问这个,要能讲清原理和工程方案。"