《用 Vibe Coding 解决 LLM 限制采样的面试题》之后,再分享我司(Pine AI)一道关于 LLM 基础原理的 Vibe Coding 面试题。

很多人对 Vibe Coding 有个误解,以为就是不断地问 AI “这个怎么做?那个怎么实现?”。这种方式注定会失败。真正的 Vibe Coding,你必须是架构师和产品经理,像老师指导学生一样去引导 AI,而不是反过来。

这道面试题考察候选人对 Transformer 基本原理的理解和 vibe coding 快速实现的工程能力。这就是我们需要的人:懂模型,并且工程能力强。

The Challenge: 基于注意力的 LLM 幻觉检测器

1. 背景与问题 (Background & Problem Statement)

在许多应用场景中,大语言模型(LLM)需要基于一份给定的上下文(Context)来回答问题或提取信息,这个过程通常被称为“上下文学习”(In-Context Learning)。然而,LLM 存在一个已知的、严重的安全隐患:当被问及一个上下文中不存在的信息时,它可能会“幻觉”(Hallucinate)出一个格式正确但事实错误的答案,而非承认信息的缺失。

一个典型的失败案例:

  • AI 个人助理的系统提示 (System Prompt as Context):
    1
    2
    3
    4
    5
    "你是张三的AI助理。你的任务是帮助用户处理日常事务,并根据用户授权的个人信息与外界沟通。
    授权信息:
    - 用户姓名:张三
    - 手机号:138-0000-1111
    - 会员号:VIP-8888"
  • 对话场景 (Dialogue Scene as Query):
    1
    客服: "您好,为了验证您的身份,需要您提供一下张三先生的身份证号码。"
  • AI 助理的危险幻觉输出 (Hallucinated Output):
    1
    AI助理: "好的,张三先生的身份证号码是:410522-1991-0303-9876。" // 这是一个纯粹捏造的数据,原始上下文中并未提供。

2. Transformer核心机制:数据库查询的视角

要解决这个问题,必须深入理解 Transformer 模型处理信息的核心——注意力机制。我们可以从一个数据库查询的视角来解构它:

  1. 上下文向量化(K & V)

    • Transformer首先将输入的上下文文本序列进行处理。对于序列中的每一个词元(Token),模型会通过线性投射,为其生成两个关键的高维向量:一个键向量(Key, K)和一个值向量(Value, V)
    • 由上下文中所有词元的 K-V 向量对组成的集合,构成了一个临时的、动态的“向量化知识库”。
  2. 查询的生成(Q)

    • 在生成输出序列的每一步,为了决定下一个最优的词元,Transformer会基于其当前状态(通常是上一个刚生成的词元的表示),生成一个查询向量(Query, Q)。这个Q向量编码了模型在这一步“希望查询什么信息”的意图。
  3. 查询的执行

    • 与传统数据库的根本区别:传统数据库执行的是基于哈希或索引的精确匹配。而Transformer的注意力机制,本质上是一次语义相似度搜索,其行为与现代的向量数据库高度相似。
    • 模型会用当前的Q向量,与“向量化知识库”中所有K向量计算相似度(通常通过点积运算)。
    • 这个过程的产出,不是一个单一的匹配结果,而是一个归一化的概率分布,即注意力权重(Attention Weights)。这个分布中的每一个值,都量化了当前的Q与某一个K之间的语义关联强度。
  4. 信息的聚合

    • 最后,模型使用这些注意力权重,来计算所有V向量的加权平均值。最终得到的聚合向量,就包含了模型认为与当前查询最相关的所有信息的“混合体”,并以此为基础来预测下一个词元。

3. 你的任务 (Your Mission)

你的任务,是基于对上述注意力机制的深刻理解,设计并实现一个基于注意力的幻觉检测器

这个校验器必须作为一个轻量级模块,在LLM生成过程中实时工作。当模型开始生成身份证号、电话号码这类关键信息序列时,你的模块必须通过分析其内部的注意力权重,来裁定:模型生成这个序列,是真的在知识库中找到了一个高相似度的 “强证据源”,还是 “自由创作”?

4. 核心挑战与约束 (Core Challenge & Constraints)

  1. 必须基于注意力机制:你的解决方案的唯一信息来源,必须是模型内部的注意力权重。严禁仅通过分析模型最终输出的文本字符串来做判断。
  2. 禁止外部依赖禁止调用任何语言模型来进行二次验证。校验器必须是自包含的,仅利用被监控模型自身在生成过程中产生的内部状态。
  3. 禁止修改输入禁止通过预处理或修改输入上下文来规避问题。你的方案必须能在原始、未修改的输入上稳健工作。

一句话总结你的挑战: 在不修改模型权重、不依赖外援的情况下,仅通过 “审阅” 其内部的注意力权重分布,来实时判断其生成内容的上下文一致性。

5. 可视化要求 (Visualization Requirements)

为了直观理解和验证你的检测器工作原理,你需要实现注意力权重的可视化:

  1. 注意力热力图:展示模型在生成每个 token 时对上下文各部分的注意力分布
  2. 判决指标:可视化展示你的检测算法使用的关键指标和判决过程

The Journey: 可视化驱动的发现之旅

第一步:创建测试用例,明确实现框架

在深入研究注意力机制之前,首要任务是搭建一个可复现、可调试的实验环境。

我(架构师角色): (把题目完整的粘贴进来)我准备解决上面的编程题,使用 Qwen 2.5 0.5B Instruct,本地运行,使用 Transformers 库。把指定 Transformer layer 的注意力矩阵(各个 attention heads 取平均)保存到 JSON,但不要做任何幻觉判断。然后创建几个幻觉和非幻觉场景的测试用例。

这个准备步骤至关重要。它将一个模糊的”幻觉检测”问题,转化为一个具体的、有明确输入和预期输出的工程任务。没有这个基础,后续的可视化和算法设计都将是无的放矢。

第二步:先建立”眼睛”——可视化系统

与很多人想象的不同,我没有一上来就设计算法。相反,我的 Vibe 是:

我(架构师角色): “我们需要先看见注意力是什么样的。给我用 React 实现一个注意力热力图,从后端输出的 JSON 中读取测试用例和注意力矩阵。要求:

  • Y 轴是生成的 token
  • X 轴是输入序列
  • 用颜色深浅表示注意力强度
  • 最重要的是:用垂直线清晰标出’系统提示’、’用户提示’和’生成内容’三个区域”

注意,我没有问”怎么画热力图”,而是明确告诉 AI 我要什么。Cursor 迅速实现了这个可视化组件。

第三步:观察模式——让数据自己说话

有了可视化,我开始运行不同的测试用例,观察 Transformer 每一层的注意力模式。这时候出现了第一个 “Aha Moment”:

在非幻觉场景中(系统提示中包含要输出的信息):

  • 当模型生成 ID 时,Transformer 最后一层的热力图在系统提示区域出现了明显的亮点
  • 这些亮点对应的正是系统提示中包含 ID 的位置

非幻觉场景 1: 测试用例,输出事实非幻觉场景 1: 测试用例,输出事实
非幻觉场景 1: 热力图左侧部分,system prompt 部分有明显的注意力峰值非幻觉场景 1: 热力图左侧部分,system prompt 部分有明显的注意力峰值

在幻觉场景中(编造了系统提示中不存在的信息):

  • 模型生成虚假身份证号时,Transformer 最后一层的热力图,在系统提示区域几乎没有亮点
  • 注意力主要集中在用户提问的位置

幻觉场景 1: 测试用例,输出幻觉幻觉场景 1: 测试用例,输出幻觉
幻觉场景 1: 热力图左侧部分,除了 system prompt 开头,注意力都很低幻觉场景 1: 热力图左侧部分,除了 system prompt 开头,注意力都很低
幻觉场景 1: 热力图右侧部分,user prompt 部分有一些不算高的注意力峰值幻觉场景 1: 热力图右侧部分,user prompt 部分有一些不算高的注意力峰值

我的洞察: “看到了吗?当模型说真话时,它会’回头看’系统提示;当它说谎时,它无处可看!”

第四步:从观察到算法——提炼核心信号

基于可视化的观察,我开始设计算法:

我(产品经理角色): “基于我们看到的模式,算法应该这样:

  1. 不需要分析所有 token,只在检测到数字序列时触发
  2. 不需要复杂的统计,只看一个指标:系统提示区域的最大注意力
  3. 设置一个简单阈值:10%”

注意我的表达方式:不是 “你觉得该怎么做”,而是 “应该这样做”。这种明确的指导让 AI 能够专注于实现,而不是在各种可能性中迷失。

第五步:调试和优化——像老师一样纠错

第一版实现后,我发现了一些问题:

我(老师角色): “你保存注意力矩阵的时候,只保存了生成的 token 相对 prefill 的时候上下文的 attention,但没有保存生成的 token 相对它前面所生成 token 的 attention,因此热力图的右侧缺失了一个三角”

这种纠错方式很重要:

  • 指出具体的错误
  • 解释背后的原理
  • 给出明确的修正方向

如果我问”为什么每行的注意力加起来不是 100%?”,AI 可能会给出各种猜测,越改越乱。

非幻觉场景 1: 热力图右侧部分,生成一个 token 时总是对它的上一个 token 有较强的注意力非幻觉场景 1: 热力图右侧部分,生成一个 token 时总是对它的上一个 token 有较强的注意力
幻觉场景 1: 热力图右侧部分,生成一个 token 时总是对它的上一个 token 有较强的注意力幻觉场景 1: 热力图右侧部分,生成一个 token 时总是对它的上一个 token 有较强的注意力

比较上述幻觉和非幻觉场景,可以发现,注意力热力图的右侧部分(自回归生成的 token 跟它之前生成的 token 之间)总是有较强的注意力。因此,在检测幻觉时,必须排除生成部分的自注意力,而要关注生成部分与输入上下文的交叉注意力。

第六步:完善可视化——让洞察更清晰

有了可靠的算法后,我进一步完善可视化:

我(产品经理角色): “添加一个调试图表:

  • 横轴是生成的 token 位置
  • 纵轴是我们的核心指标:最大系统注意力
  • 画一条红色虚线表示 10% 阈值
  • 用不同颜色标记超过和低于阈值的点”

这个可视化让算法的工作过程一目了然,任何人都能在几秒内理解判断逻辑。

非幻觉场景 1: 每个生成 token 在 system prompt 区域的注意力曲线非幻觉场景 1: 每个生成 token 在 system prompt 区域的注意力曲线
幻觉场景 1: 每个生成 token 在 system prompt 区域的注意力曲线幻觉场景 1: 每个生成 token 在 system prompt 区域的注意力曲线

关键洞察:可视化是发现的眼睛

回顾整个过程,如果没有先建立可视化系统,除非我们在这方面有经验,永远无法发现那个简单有效的 “峰值检测” 方案。可视化不仅是展示结果的工具,更是:

  1. 发现模式的眼睛:让隐藏的规律浮现
  2. 验证假设的工具:快速验证想法是否正确
  3. 沟通的桥梁:让复杂的概念变得直观

最终成果:基于注意力峰值的简化检测系统

这里是完成的参考代码:基于注意力峰值的简化检测系统(注意:代码仅供 demo 用途,真正在生产环境中可用的幻觉检测比它复杂很多)

核心洞察与设计理念

通过深入分析注意力模式,我们发现了一个极其简单但在很多场景下有效的规律:

关键发现:当模型需要引用具体的事实信息时,如果这些信息真实存在于系统提示中,模型必然会在某个时刻强烈关注该信息所在的位置,形成明显的注意力峰值。

基于这个洞察,我们设计了一个极简的单一指标检测算法:

  1. 非幻觉情况:当系统提示中存在真实信息时,模型在生成过程中会对系统提示产生高注意力峰值(通常>10%)。
  2. 幻觉情况:当系统提示中没有相应信息时,模型对系统提示的注意力始终保持在较低水平(通常<10%),因为没有可以”查找”的信息源。

这个方法的优雅之处在于:它直接利用了注意力机制作为”信息检索”的本质——如果模型在”查找”真实信息,它必然会在信息所在位置产生强注意力峰值。

极简的峰值检测算法

需要强调的是,我们这里使用的 attention_weights 是指 Transformer 模型最后一层中,所有 attention heads 注意力值(即 QK 乘积经过 Softmax 归一化到 0-1 之后的值)的平均值。

核心原理:注意力峰值检测

1
输入序列 = [系统提示(事实)] + [用户提示(问题)] + [生成的内容]

单一核心指标:最大系统注意力(Max System Attention)

1
2
最大系统注意力 = max(attention_weights[5:system_prompt_end])
# 注:跳过前4个token,因为它们通常有异常高的注意力

判定规则

  • 最大注意力 > 10%:验证通过 - 模型在系统提示中找到了信息源
  • 最大注意力 ≤ 10%:检测到幻觉 - 模型在系统提示中没有找到信息源

为什么这样有效

  • 当系统提示包含”身份证号:123456…”时,模型生成这些数字时必然会关注这个位置
  • 当系统提示中没有身份证号,模型只能关注用户的提问”请提供身份证号”,然后编造答案
  • 这种方法直接利用了注意力机制的本质——作为信息检索的工具

极简版 LogitsProcessor 实现

初始化参数

  • context_length (int): 总上下文长度
  • system_prompt_length (int): 系统提示的长度
  • max_attention_threshold (float): 最大注意力阈值,默认0.1(10%)
  • min_sequence_length (int): 触发检测的最短序列长度,默认6

核心处理逻辑

  1. 实时监控阶段(每个token生成后):

    • 检测数字序列的开始(第一个包含数字的token)
    • 当检测到数字序列开始时,触发注意力分析
  2. 峰值检测逻辑

    1
    2
    3
    4
    5
    6
    7
    # 获取所有生成token的注意力权重
    for position in generated_positions:
    attention = get_attention_weights(position)
    # 检查系统提示区域的最大注意力(跳过前5个token)
    max_system_attention = max(attention[5:system_prompt_length])
    # 更新全局最大值
    global_max = max(global_max, max_system_attention)
  3. 幻觉判定

    • 最大系统注意力 > 10%:非幻觉(VERIFIED)
    • 最大系统注意力 ≤ 10%:幻觉(HALLUCINATION_DETECTED)

可视化方案:注意力峰值检测看板

为了直观展示峰值检测系统的工作过程,我们设计了一个清晰的可视化看板,重点展示系统提示区域的注意力峰值。

1. 注意力热力图 (Attention Heatmap)

核心改进:明确区分三个关键区域

图表设计

  • 类型:分区热力图,带有清晰的区域标记
  • Y轴:生成的token序列
  • X轴:完整输入序列,通过垂直分割线划分为三个区域:
    • 系统提示区:包含事实信息
    • 用户提示区:包含用户问题
    • 生成内容区:模型生成的内容
  • 颜色编码:使用 viridis 色系表示注意力强度

关键模式识别

  • 真实引用模式:生成数字时,亮点主要集中在系统提示区
  • 幻觉生成模式:生成数字时,亮点主要集中在用户提示区
  • 混合模式:注意力在系统和用户提示之间分散,表示不确定性

2. 注意力调试图表

核心功能:展示每个生成token的最大系统注意力

  • 类型:折线图,带阈值标记
  • X轴:生成的token位置
  • Y轴:最大系统注意力(0-20%)
  • 关键元素
    • 绿色实线:每个token位置的最大系统注意力
    • 红色虚线:10%阈值线
    • 蓝色虚线:数字序列开始位置(如果检测到)
  • 数据点颜色
    • 绿色点:注意力 > 10%(非幻觉)
    • 红色点:注意力 ≤ 10%(可能是幻觉)

3. 验证结果分析面板

峰值检测结果

  • 最大系统注意力:以大字体百分比形式显示
  • 阈值比较:清晰显示是否超过10%阈值
  • 检测状态
    • ✓ 已验证:最大注意力 > 10%
    • ✗ 检测到幻觉:最大注意力 ≤ 10%

算法说明

  • 简洁解释检测原理:
    • “检测数字序列开始后的注意力峰值”
    • “峰值 > 10% = 在系统提示中找到信息源”
    • “峰值 ≤ 10% = 未找到信息源,可能是幻觉”

这个极简的可视化方案让幻觉检测变得直观易懂。通过聚焦于单一核心指标——系统提示区域的最大注意力,我们能够清晰地判断模型是否在系统提示中找到了信息源。

其他测试用例

除了前面图中的测试用例,我又用了另外一组幻觉和非幻觉测试用例。两组测试用例中,幻觉检测的效果都是比较稳定的。

当然,幻觉不只是无中生有,更常见的是张冠李戴(把小王的信息搞成了小李的信息),因此真正生产环境中可用的幻觉检测机制远比本文复杂。这里仅是作为一个区分度较强的面试题,考察候选人对 Transformer 基本原理的理解和 vibe coding 快速实现的工程能力。

非幻觉场景

非幻觉场景 2: 测试用例,输出事实非幻觉场景 2: 测试用例,输出事实
非幻觉场景 2: 热力图左侧部分,system prompt 区域有明显的注意力峰值非幻觉场景 2: 热力图左侧部分,system prompt 区域有明显的注意力峰值
非幻觉场景 2: 热力图右侧部分,生成一个 token 时总是对它的上一个 token 有较强的注意力非幻觉场景 2: 热力图右侧部分,生成一个 token 时总是对它的上一个 token 有较强的注意力
非幻觉场景 2: 每个生成 token 在 system prompt 区域的注意力曲线非幻觉场景 2: 每个生成 token 在 system prompt 区域的注意力曲线

幻觉场景

幻觉场景 2: 测试用例,输出幻觉幻觉场景 2: 测试用例,输出幻觉
幻觉场景 2: 热力图,system prompt 区域没有明显的注意力峰值幻觉场景 2: 热力图,system prompt 区域没有明显的注意力峰值
幻觉场景 2: 每个生成 token 在 system prompt 区域的注意力曲线幻觉场景 2: 每个生成 token 在 system prompt 区域的注意力曲线

Vibe Coding 的正确姿态:要当老师,而不是学生

Vibe Coding 代表着软件开发的未来,但它需要我们转变思维:

  1. 从编码者到设计者:重点不是写代码,而是设计方案
  2. 从提问者到指导者:不是问 AI 怎么做,而是告诉 AI 该做什么
  3. 从盲目尝试到数据驱动:先建立观察工具,让数据引导发现

记住:你是架构师、产品经理和老师,AI 是你的高级实习生。 它执行力超强,但需要你的指导和纠正。如果你自己都不清楚要什么,AI 只会在迷宫中打转。

❌ 错误的方式(学生心态):

  • “这个幻觉检测该怎么做?”
  • “为什么结果不对?你帮我看看”
  • “我也不知道这方法行不行,先这么干试试吧”

✅ 正确的方式(老师心态):

  • “实现一个热力图,要求是…”(明确的需求)
  • “你的理解有误,正确的是…”(具体的纠正)
  • “基于观察,算法应该是…”(清晰的设计)

这就是 Vibe Coding 的真谛——不是让 AI 替你思考,而是让 AI 助你实现。


整个探索过程,从建立可视化到编码实现整个方案,只用了 2 个小时。这就是正确的 Vibe Coding 方式带来的效率提升。我司的面试题给候选人的时限也是 2 个小时。

Comments