LLM 应用开发面试题 & 参考答案(第二场)
面试官:严察
日期:2026-06-02
面试阶段:基础知识 → 工程实战 → 开放场景
目录
阶段一:基础知识与核心概念
问题一:Self-Attention 机制与 QKV 角色
题目: 解释 Transformer 中的 Self-Attention 核心计算公式(Q、K、V 的角色与点积缩放),以及它为什么会成为 LLM 的基础组件?
参考回答
核心公式
$$
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V
$$
Q、K、V 的角色
| 角色 | 符号 | 形象比喻 | 实际作用 |
|---|---|---|---|
| 查询(Query) | Q | 你在问"谁跟我有关系?" | 当前 token 去"问"其他 token |
| 键(Key) | K | 每个 token 的"标签牌" | 告诉别人"我是什么" |
| 值(Value) | V | 每个 token 的"内容本体" | 被加权求和的实际信息 |
计算流程
Q × K^T→ 得到注意力矩阵,表示每对 token 之间的相关性÷ √d_k→ 缩放,防止 d_k 很大时点积值过大导致 softmax 梯度消失softmax→ 归一化为概率分布× V→ 按注意力权重加权求和,得到输出
为什么 ÷ √d_k 是必须的?
d_k(Key 的维度)增大时,点积的方差也随之增大(正比于 √d_k)。如果不缩放,极端值在 softmax 后产生接近 one-hot 的分布,梯度趋近于 0,模型学不动。这是数学上的必然,不是工程调参的选择。
为什么 Self-Attention 成为 LLM 基础?
| 对比 RNN | Self-Attention |
|---|---|
| 串行计算,无法并行 | 所有位置同时计算,完全可并行 |
| 长程依赖需经 N 步传递,信号衰减 | 任意两个 token 之间一步直达,O(1) 路径长度 |
| BPTT 梯度消失 / 爆炸 | 无时序反向传播,训练更稳定 |
| 信息瓶颈(固定隐藏状态) | 所有位置互相可见,信息无损传递 |
一句话: Self-Attention 用 O(n²) 的计算量换来了全局感知 + 完全并行,这两项能力是 GPT 等大模型能 Scale Up 的根本前提。
深挖点 Q&A
Q:为什么是缩放点积而不是其他运算?比如加性注意力?
点积注意力在 GPU 上可以用高度优化的矩阵乘(GEMM)实现,计算效率远高于加性注意力。加性注意力虽然理论上表达能力略强,但在实际大规模训练中,速度差距让点积成为事实标准。
Q:多头注意力(Multi-Head Attention)为什么比单头效果好?
每个头关注不同的子空间模式。比如一个头关注语法关系(主谓宾),另一个头关注语义相似性,第三个头关注位置距离。多个头的输出拼接后,模型看到的是对同一序列的多视角表示,比单头的表达能力更强。
Q:如果不除以 √d_k,定量描述会怎样?
假设 d_k=512,点积的方差约为 512,标准差 ≈ 22.6。这意味着点积值分布在 [-67, 67] 范围(3σ)。softmax(67) ≈ 1,softmax(-67) ≈ 0,softmax 输出接近 one-hot,梯度极小,模型几乎无法更新。除 √d_k 后,方差缩回 1,softmax 落在梯度最大的区域,训练效率大幅提升。
问题二:Temperature 与 Top-p 采样策略
题目: Temperature 和 Top-p(Nucleus Sampling)各自控制什么?分别适合什么场景?两者同时设置时采样策略如何执行?
参考回答
Temperature(温度系数)
控制概率分布的"尖锐程度"。计算在 softmax 之前执行:
$$
\text{logits}’ = \frac{\text{logits}}{T}
$$
| T 值 | 效果 | 适用场景 |
|---|---|---|
| T → 0 | 分布趋近 one-hot,几乎每次都选最高分 token(实际实现为 argmax) | 代码生成、事实问答、客服等确定性任务 |
| T = 1 | 保持原始分布 | 常规对话 |
| T > 1 | 分布变平缓,低分 token 也有机会被选 | 创意写作、故事生成、头脑风暴 |
Top-p(Nucleus Sampling)
从累积概率达到 p 的最小 token 集合中采样。这些 token 的概率之和至少为 p,然后在这个集合内重新归一化后采样。
| p 值 | 效果 | 适用场景 |
|---|---|---|
| p = 0.1 | 几乎只从最高概率的几个 token 中选 | 高确定性任务 |
| p = 0.9 | 保留大多数合理选项 | 通用生成 |
| p = 1.0 | 退化为完整分布采样(等同只设 T) | 极少使用 |
两者同时设置时的执行顺序
原始 logits
→ ① 除以 Temperature(softmax 前)
→ ② softmax 归一化
→ ③ Top-p 过滤(只保留累积概率 ≤ p 的 token 集合)
→ ④ 核内 token 重新归一化
→ ⑤ 采样
关键理解: Temperature 先影响整个分布的形态,Top-p 再截断尾部低概率 token。
- 如果 T 很高 → 所有 token 概率趋近均匀 → Top-p 留下几乎所有 token → 高度随机
- 如果 T → 0 → Top-p 基本只剩一个 token → p 值几乎失效
生产实践:
| 场景 | 推荐配置 |
|---|---|
| 确定性任务 | T=0(此时 Top-p 不生效) |
| 创意写作 | T=0.7 + p=0.9 |
| 专业文档生成 | T=0.8 + p=0.9 + k=50 + repetition_penalty |
深挖点 Q&A
Q:T=0 时采样策略具体怎么实现的?
绝大多数实现直接取 logits 最大的 token(argmax),并不实际走 softmax + 采样流程。这不仅保证了确定性,也省去了 softmax 的计算开销,对推理速度有细微提升。
Q:Top-k 和 Top-p 可以一起用吗?哪个优先?
可以。常见实现是先 Top-k 剪枝到 k 个 token,再对剩余集合做 Top-p 过滤。两者结合能更精细地控制生成质量:先用量化指标(k 个)砍掉明显不合理的 token,再用动态比例(p)做微调。
问题三:语义歧义文档的检索策略
题目: 知识库中存在大量语义相似但含义不同的文档(如"苹果水果的种植技术"和"苹果公司的财报分析"),如何设计检索策略减少误召回?
参考回答
问题本质
"苹果"这个词在向量空间中语义非常接近,但意图完全不同。纯向量检索无法区分这种歧义。
生产级检索链路(完整 8 步流程)
Query 入口
→ ① Query 意图消歧 & 领域分类 ← 在检索前就把问题框定到正确领域
→ ② Query 扩充 / 改写 ← 用 LLM 补充领域限定词
→ ③ 知识库分库路由(可选) ← 物理隔离不同领域数据源
→ ④ BM25 + 稠密向量多路召回 + 元数据前置过滤
→ ⑤ 规则关键词过滤 ← 正则/黑白名单,便宜但有效
→ ⑥ Cross-Encoder 重排序 ← 二次精排
→ ⑦ 分数阈值截断输出 ← 低分宁可不要
→ ⑧ 线上误召样本迭代优化 ← 将 bad case 沉淀为标注数据反哺
各环节详解
① Query 意图消歧 & 领域分类
在检索入口判断 query 所属领域,后续只在该领域内检索。
# 轻量分类器或 LLM 分类
query = "苹果怎么种"
domain_classifier(query)
# → {"agriculture": 0.92, "finance": 0.05, "tech": 0.03}
# → 路由到 agriculture 子库
② Query 改写
让 LLM 在检索前扩充用户 query,增加领域限定词。
"苹果怎么种" → "苹果(水果)的种植技术、栽培方法"
"苹果公司财报" → "苹果(Apple Inc.)最新季度财务报告"
③ 知识库分库路由
物理隔离不同领域的数据源,比元数据过滤更彻底:
检索前先确定 domain,只查对应索引
domain="agriculture" → 查 agriculture 索引库
domain="finance" → 查 finance 索引库
④ 多路召回 + 元数据过滤
BM25 检索(命中含"种植""技术"的文档) + 稠密向量检索(命中含"苹果"的文档)
+
元数据过滤:WHERE category = "agriculture"
⑤ 规则关键词过滤
用正则或黑白名单做快速筛除:
# 如果 query 含"种植"、"栽培",过滤掉含"财报"、"股票"、"市值"的文档
if "种植" in query:
filtered = [doc for doc in results if "财报" not in doc.tags]
⑥ Cross-Encoder 重排序
用 Cross-Encoder 对 query 与每个候选文档做精确匹配打分,大幅提升精度。
⑦ 分数阈值截断
低于阈值的文档宁可不要,也不塞进上下文。
⑧ 线上误召样本迭代
将线上 bad case 沉淀为标注数据,周期性反哺 Embedding 微调或重排序模型。
根本解法:领域微调 Embedding
通用 Embedding 模型中"苹果水果"和"苹果公司"可能只差 0.2 余弦距离。用对比学习微调后,距离被拉开到 0.7+:
正样本对: "苹果怎么种" ↔ "苹果树的修剪技巧"
负样本对: "苹果怎么种" ↔ "苹果公司财报分析"
深挖点 Q&A
Q:元数据中的 category 怎么自动标注?不可能为百万文档人工打标签。
用 LLM 或 BERT-based 分类模型自动分类。分类体系需要和搜索意图的粒度对齐。如果分类粒度太粗(只有"农业"和"科技"),歧义无法消除;如果太细(几百个子类),标注成本和误分类率都会上升。
Q:Query 改写引入 LLM 调用,延迟和成本怎么权衡?
非实时场景(定时报表、离线生成)放心用。实时场景有两种替代方案:
- 条件触发: 只在检索结果的置信度低于阈值时才触发 rewrite
- 轻量扩展: 用 N-gram 模型或同义词表做 query 扩展,不走 LLM
Q:元数据过滤太严格导致漏召回怎么办?
设两路检索:一路精确过滤(高精度低召回),一路不过滤(高召回低精度),用 RRF 融合结果。既不错过模糊匹配,也不被噪音淹没。
阶段二:工程实战与架构设计
问题四:AI 客服 Agent — 单 Prompt vs 多 Agent
题目: 设计 AI 客服 Agent,需要串联:意图判断 → 知识库检索 → 订单 API 调用 → 回复生成。用一个大 Prompt + Function Calling,还是拆成多个专用子 Agent 串联?
参考回答
选型原则
小体量(工具 < 5、决策分支 < 3、规则 < 500 字)→ 单 Prompt + FC
大体量(工具 > 10、多轮跨系统交互、不同子系统有不同权限)→ 多 Agent
方案对比
| 维度 | 单 Prompt + FC | 多 Agent 串联 |
|---|---|---|
| Prompt 长度 | 随业务膨胀,易 Lost in the Middle | 每个 Agent 仅 100-200 字 |
| 上下文干扰 | 意图判断和 API 调用在同一窗口,互相争注意力 | 隔离,各管各的 |
| 单次延迟 | 低(1 次 LLM 调用) | 高(N 次 LLM 调用) |
| 可调试性 | 黑盒,出错难定位是哪一步 | 每一步可单独打日志、设断点 |
| 错误隔离 | 工具调用出错可能污染整个上下文 | 子 Agent 出错不影响其他模块 |
| 扩展性 | 加新能力 = 改 Prompt,可能影响已有逻辑 | 加新 Agent = 新增节点,不影响已有链路 |
生产最佳实践:混合架构
[Router Agent] → 判断意图:退换货 / 查物流 / 投诉
↓
退换货 → [Returns Agent] ← 单 Prompt + FC,只管退换货全套
查物流 → [Logistics Agent] ← 单 Prompt + FC,只管物流
投诉 → [Complaint Agent] ← 单 Prompt + FC,只管投诉
为什么这样折中?
- Router Agent 只做一件事(意图分类),Prompt 极短(< 200 字),精度高
- 子 Agent 各自只维护自己领域的规则,不会互相干扰
- 新增业务类型 ≈ 新增一个子 Agent + 改 Router 的路由表,不改已有逻辑
深挖点 Q&A
Q:多 Agent 之间的上下文怎么传递?如果用户说"那个订单",子 Agent 怎么知道是哪个?
- Shared Context(全局黑板): 每个 Agent 将关键信息写入共享 KV 存储(如 Redis),后续 Agent 按需读取
- 消息传递 + 摘要: 上一 Agent 的输出中提取关键实体(订单号、用户 ID)传给下一 Agent,不传完整对话历史
- 问清楚再执行: 信息不足时子 Agent 可以反问 Router 追问用户,而不是猜测
Q:Router 分错类了(退换货走到查物流),怎么兜底?
在每个子 Agent 入口做二次验证。如果 Returns Agent 发现用户表达的不是退换货意图,返回特定信号给 Router 重新路由,而不是强行处理。
问题五:百万 QPS RAG 系统的缓存策略
题目: 一个 RAG 系统每天处理 100 万次查询,设计缓存策略。缓存什么?缓存多久?何时失效?
参考回答
1. 缓存分层(L1~L4)
| 层级 | 存储 | 速度 | 容量 | TTL 建议 |
|---|---|---|---|---|
| L1 | 进程本地 LRU | 纳秒级 | 小(MB) | 5-30 min |
| L2 | Redis 分布式 | 毫秒级 | 中(GB) | 2-24 h |
| L3 | 向量库索引缓存 | 毫秒级 | 大 | 3-30 天 |
| L4 | 文档磁盘缓存 | 毫秒级 | 大(TB) | 按文档更新周期 |
2. 按处理阶段分粒度
Query 入口
↓
缓存①:归一化 Query → 完整答案(命中直接返回,延迟 ≈ 1ms)← 最高价值
↓
Query 改写(LLM 调用,200-500ms)
↓
缓存②:改写后 Query → 检索结果(命中省掉检索 + 重排)
↓
向量检索(50-100ms)
↓
缓存③:Query 向量(省掉 embedding 调用)
↓
Reranker(50-100ms)
↓
LLM 生成(500-2000ms,最贵的一步) ← 第二高价值
↓
缓存① 写入
3. 可缓存 vs 不可缓存
| 可缓存 | 不可缓存 |
|---|---|
| 归一化 Query → 完整答案 | 实时订单 / 库存数据 |
| Query 向量 | 用户私有个性化数据 |
| 改写后 Query | 含 PII(个人身份信息)的请求 |
| 检索 / 重排结果 | 随时间严格变化的敏感数据 |
| 稳定的 FAQ / 知识文档 | — |
4. TTL 策略
| 内容类型 | TTL |
|---|---|
| 稳定 FAQ / 向量 | 3-30 天 |
| 普通问答 / 检索结果 | 2-24 小时 |
| 临时活动内容 | 5-30 分钟 |
| 本地内存 | 5-30 分钟短过期 |
5. 失效机制
| 方式 | 说明 |
|---|---|
| 被动过期 | TTL 自动淘汰 |
| 主动精准失效 | 知识库文档变更时,按 Key 单点删除缓存 |
| 批量失效 | 模型 / Prompt 改版时,清理对应分类缓存 |
| 关联失效 | 维护"文档 ID → 相关 query"的倒排映射,文档更新时精确失效关联 query |
6. 缓存三灾防护
| 灾难 | 场景 | 防护方案 |
|---|---|---|
| 穿透 | 查询不存在的数据,每次都穿透到后端 | 空值也缓存(短 TTL,如 1-2 分钟) |
| 击穿 | 热点 Key 过期,高并发同时回源 | 互斥锁(同一 key 只有一个线程回源)+ 热点数据主动预热 |
| 雪崩 | 大量 Key 同时过期,回源打垮后端 | TTL 随机打散(基础 TTL + random(0, TTL/2)) |
缓存 Key 设计(含权限隔离)
# 错误做法:不同部门的相同 query 共享缓存
cache_key = md5(query)
# 正确做法:key 带上权限上下文
cache_key = md5(query + department_id + user_role)
深挖点 Q&A
Q:L3 向量库索引缓存具体怎么实现?向量索引本身已经在内存里了。
L3 缓存的是检索结果而非索引本身。同一 query 向量命中缓存后直接返回 Top-K 文档 ID,跳过向量检索的 ANN 搜索过程。本质是"检索结果缓存"而非"索引缓存"。
Q:知识库更新后,怎么找到受影响的 query 进行精确失效?
建立倒排映射表(Redis Set):document_id → Set[related_query_md5]。文档更新时查出所有关联 query 逐个失效。这个映射表需要在每次检索时同步更新。
Q:缓存 Key 加了 department_id 后命中率下降,怎么补救?
分析部门间 query 的重叠度。如果 A 和 B 的 query 分布高度相似,考虑按部门组(如"技术线"含 A/B/C 三个子部门)共享缓存,而不是按单个部门完全隔离。
问题六:端到端延迟 P99 从 3s 降到 1s
题目: 对 LLM 应用做性能优化,目标是把端到端 P99 延迟从 3s 降到 1s 以内。按收益从高到低排序,说明每个环节的预期优化幅度。
参考回答
原始链路延迟分布(P99 ≈ 3s)
LLM 推理: 2200ms (73%) ← 绝对大头
网络 / 序列化: 320ms (11%)
Embedding 调用: 200ms (7%)
Reranker: 150ms (5%)
向量检索 (ANN): 100ms (3%)
Prompt 拼接: 30ms (1%)
优化方案及预期效果
| 优先级 | 环节 | 方案 | 预期 P99 降低 |
|---|---|---|---|
| P0 | LLM 推理 | ① vLLM / TensorRT-LLM(PagedAttention + continuous batching) ② 减少输出 token 数 ③ FP16 → INT8 / INT4 量化 |
2200ms → 600-800ms ✅ |
| P1 | 缓存 | 多级缓存命中 → 跳过全链路 | 命中时 3s → 10-50ms |
| P2 | Embedding | 结果缓存 + 批处理 | 200ms → 20-50ms |
| P3 | Reranker | 换轻量模型 + 缩小候选数 | 150ms → 50ms |
| P4 | 网络 / 序列化 | 连接池复用 + gRPC + 减少不必要字段 | 320ms → 100ms |
优化后预期结果(未命中缓存)
LLM 推理: 700ms (vLLM + 量化)
Embedding: 30ms (缓存 + 批处理)
向量检索: 80ms
Reranker: 50ms
Prompt: 20ms
网络: 80ms
──────────────────
P99 ≈ 960ms ✅ (达标)
关键认知
- 缓存压 P50,推理加速压 P99 — 缓存命中时极快但非每次命中;推理加速让每一次请求都受益
- vLLM 的核心价值: PagedAttention 将 KV Cache 分页管理,消除显存碎片,允许更大 batch size → 更高 GPU 利用率 → 单次推理延迟降低
- 量化收益: FP16 → INT8 延迟降低约 40-50%,INT8 → INT4 再降低约 20%,但精度损失非线性增加,需做校准测试
- Continuous Batching: 高并发下吞吐提升 2-5x,但单次请求的 P99 也会因为排队而上升,需要在吞吐和延迟之间做权衡
深挖点 Q&A
Q:vLLM 的 PagedAttention 降低延迟的原理是什么?
传统推理引擎需要预分配最大长度的 KV Cache 空间,造成大量碎片和浪费。PagedAttention 将 KV Cache 分页管理(类似操作系统的虚拟内存),按需分配、按页管理,消除了碎片。同一 GPU 上能同时运行更多请求,batch size 更大 → GPU 利用率更高 → 单次推理等待时间更短。
Q:FP16 → INT4 的精度损失有多大?
取决于任务类型。对事实问答类任务,INT4 通常可接受(准确率下降 < 1-2%)。对需要数值精确计算或长链推理的任务,INT4 的损失可能达到 5-10%。必须针对自己的业务数据集做校准测试,不能凭感觉选量化等级。
Q:公司没有 GPU 做推理加速,纯 CPU 推理怎么压到 1s?
退路方案(从易到难):
- 用更小的模型(Qwen2.5-1.5B 替代 7B)
- ONNX Runtime 优化 + Intel OpenVINO
- 更激进的缓存策略(提高缓存命中率)
- 如果以上都做不到,需要承认硬件上限,给业务方做预期管理
阶段三:开放场景题与故障排查
问题七:AI 周报出现跨部门数据泄露
题目: "AI 写周报"功能上线后,A 部门的周报里出现了 B 部门的项目数据。数据权限设计应该保证了每个人只能看到自己的数据。可能原因?排查路径?
参考回答
根因归类(按高发概率排序)
| 概率 | 根因 | 说明 |
|---|---|---|
| 🔴 最高 | RAG 检索未做权限过滤 | 文档入库未按部门标签隔离,检索时没带部门过滤条件 |
| 🔴 高 | 共享 Embedding 缓存 | 不同部门同一 query 命中同一个缓存槽,返回的是公共结果 |
| 🟡 中 | 数据入库标注错误 | B 部门文档打标成 A 部门,权限过滤失效 |
| 🟡 中 | Prompt 拼接遗漏过滤 | 全局知识库全部灌入上下文,未按权限过滤 |
| 🟢 低 | Agent 记忆池跨租户污染 | A 员工历史数据存入全局记忆,B 生成时被混入 |
最容易被忽视的根因:共享 Embedding 缓存
不同部门的员工搜"本季度重点项目",embedding 结果完全一样(因为 query 文本相同),缓存命中后返回的 Top-K 文档只按语义排序,没有部门过滤。即使检索入口带了 department_id,但缓存层存的是「query → 文档 ID 列表」,不带权限上下文,从缓存读出来的结果天然是公共的。
修复方案:缓存 Key = md5(query + department_id),不同部门的同一 query 走不同的缓存槽。
排查步骤
① 复现问题
拿报错员工账号,记录 Query + 召回原文 + Prompt 全文 + 输出周报
确认跨部门内容来自哪一段检索文档
② 溯源文档
查违规文档的部门标签、入库来源
确认标签是否错误
③ 校验检索逻辑
打印检索入参,检查是否带 department_id 过滤字段
④ 核查缓存
查看该 Query 是否命中跨部门缓存的检索结果
⑤ 拆解 Prompt
确认送入 LLM 的上下文有没有混入无权限文档
⑥ 排查多租户记忆
关闭会话记忆重试生成,验证是否记忆串数据
紧急修复方案
| 动作 | 说明 |
|---|---|
| 检索强制增加部门 ID 过滤 | 全量重刷错误标签文档 |
| 缓存 Key 追加用户 + 部门标识 | 隔离跨部门缓存 |
| Prompt 前置过滤 | 剔除无权限文档片段再送入 LLM |
权限过滤的正确位置:两层都要做
检索层过滤(必须):
SELECT * FROM vector_index
WHERE department_id = ? ← 入库时写入
ORDER BY vector_distance(...)
LIMIT K
生成层兜底(以防万一):
Prompt 拼接前,对召回文档做二次权限校验
如果发现某文档用户无权限 → 剔除,从候补列表补一个
终极解法:向量库原生属性过滤
权限过滤下推到存储层,不走应用层遍历:
Milvus: search(..., expr="department_id == 'A'")
Pinecone: query(..., filter={"department_id": "A"})
Qdrant: search(..., query_filter=...)
深挖点 Q&A
Q:如果一个人有多个部门的权限(跨部门协作),过滤条件怎么写?
department_id IN ('A', 'B', 'C'),外加最小权限原则:只有明确授权的部门才纳入 IN 条件,不含糊。不要因为用户属于 A 部门就自动给他 B 部门的数据权限。
Q:缓存 Key 加了 department_id 后命中率下降,怎么补救?
分析部门间 query 的重叠度。如果 A 和 B 的 query 分布高度相似,考虑按部门组(如"技术线"含 A/B/C 三个子部门)共享缓存,而不是按单个部门隔离。
Q:文档在入库时没有标注部门,历史数据怎么补?
用 LLM 批量分类:拿文档内容让 LLM 判断属于哪个部门,人工抽检后全量更新标签。风险是 LLM 分类可能有误,所以补标后要保留人工复核通道和纠错入口。
问题八:同问异答 — 答案不一致排查
题目: 同样的问题,模型有时候能答对,有时候答错,没有任何规律。怎么向非技术背景的老板解释?实际从哪些维度排查?
参考回答
对老板的解释(三句话)
"同样的问题,AI 每次答题有三处不受控:
- 它天生带随机性,不开约束就会时而想偏;
- 它每次查到的资料可能不一样,有时查到对的、有时查到错的;
- 高峰期后台模型实例可能会切换,底层的模型版本不同。
用户输入没变,但 AI 的参考素材和随机性在变,答案就会忽对忽错。
我们把随机性关掉,再把查资料的路径固定下来,就能稳定。"
技术排查框架:答案一致性的三要素
$$
\text{Answer Stability} = F(\text{Input}, \text{Context}, \text{Model})
$$
| 要素 | 变量 | 可控? | 修复方向 |
|---|---|---|---|
| Input(用户输入) | 用户的措辞 | ❌ 不可控 | 但可做 query 归一化 |
| Context(模型看到的上下文) | 检索文档、System Prompt、历史对话 | ✅ 可控 | 固定检索结果 + 固定 Prompt |
| Model(模型本身) | 版本、参数、推理引擎 | ✅ 可控 | 锁定版本 + T=0 |
排查 & 修复(按优先级)
| 优先级 | 环节 | 根因 | 修复方案 |
|---|---|---|---|
| P0 | 生成随机性 | temperature > 0 是核心元凶 |
固定 T=0, top_p=1。同入参同素材,输出固定 |
| P1 | RAG 检索不稳定 | 向量库浮点近邻抖动、每次召回文档不同、混入无效文档 | Query 归一化 + 固定 topK + 去重过滤 + 缓存检索片段 |
| P2 | System Prompt 不固定 | 动态拼接冗余内容、上下文长度忽长忽短 | System Prompt 写死不变,只替换用户问题 + 检索资料 |
| P3 | 模型服务波动 | 服务商负载高自动切小模型 / 降级算力,不同时段底层模型版本不同 | 锁定指定模型版本,异常熔断降级走兜底缓存 |
| P4 | 缓存 / 链路异常 | 偶发缓存 miss 回源 LLM、接口重试带来上下文变化 | 高频问题开启答案缓存,归一化 query 做缓存 key |
T=0 后仍不一致的进阶排查
如果 T=0 后同一 Prompt 仍输出不同,排查方向:
| 可能原因 | 说明 |
|---|---|
| GPU 计算精度 | float16 vs float32 导致 logits 微小差异 |
| vLLM prefix caching | 缓存命中状态不同影响计算图 |
| 服务商负载均衡 | 不同节点的权重文件有微小差异 |
| 输入 padding 长度 | batch 内其他请求的长度影响当前推理路径 |
生产应对: 对确定性要求极高的回答,不走 LLM,走缓存 + 模板匹配。
深挖点 Q&A
Q:模型服务商切小模型,你这边怎么感知到?有没有主动检测手段?
用探测请求(Probe)定期向服务商发固定 query,检查返回的模型版本标识(如有)或输出分布的熵值。熵值突变 → 告警 → 自动切换备用 provider。
Q:T=0 之后 P99 延迟可能因为 batch size 变化而波动,怎么解释?
T=0 不改变推理速度,它只改变采样策略。延迟波动更可能是推理引擎的 batching 策略导致的,跟 T 值无关。但老板可能会把两者关联起来,需要提前打预防针。
Q:你说缓存高频问题,怎么定义"高频"?Top 100?
用线上 query 日志做 Pareto 分析,找到贡献 80% 请求量的 query 集合(通常只占全部 query 种类的 5%-10%),缓存这个集合即可。不需要缓存所有 query。
面试总结
评分矩阵
| 维度 | 评分 | 说明 |
|---|---|---|
| 理论基础 | 🟢 优秀 | Attention、采样策略、Embedding 选型,概念清晰 |
| 工程实战 | 🟢 优秀 | 缓存分层、容错降级、权限隔离,有生产深度 |
| 排查能力 | 🟢 优秀 | 路径完整、逻辑清晰、有止血意识 |
| 架构思维 | 🟢 良好 | 选型有判断力,多 Agent 和单体的取舍合理 |
| 非技术沟通 | 🟢 优秀 | 能用老板听得懂的话解释技术问题 |
可加强的方向
- 定量思维: 回答中有"缓存"、"加速"等概念,如果能带上具体数字(命中率预期、延迟缩减比例、成本节省金额),会更有说服力
- 量化阈值: 比如"多少工具切多 Agent"、"多少 QPS 需要多级缓存"等,给出具体临界值的经验判断
一句话总结
Senior 级别,有实战深度,有架构视野,有非技术沟通能力。
评论区