滴滴 大模型算法开发 一面
1. 自我介绍
2. 多模态里的旋转位置编码是怎么落到二维视觉 token 上的
二维视觉 token 不像纯文本那样天然是一维顺序,所以多模态里的 RoPE 通常不会直接照搬文本侧。常见做法是把二维位置拆成行和列两个轴,分别做旋转位置编码,再把两个方向的信息组合到同一个视觉 token 表示里。这样模型在注意力里不仅能感知“前后”,还能保留一部分“上下左右”的相对结构。
真正难的不是公式本身,而是视觉 token 经过压缩、重采样、patch merge 之后,原始空间坐标已经不再一一对应。这个时候二维 RoPE 的设计就要和视觉编码器、projector 以及后续 token 压缩方式一起看,否则你只是给 token 挂了坐标,但空间关系其实已经被冲淡了。
3. preference dataset 一般怎么设计,才能让后训练真的学到偏好
偏好数据集不是简单收集两个答案让人选一个。真正有用的 preference dataset,首先要把任务切细,明确偏好的评价维度,比如正确性、完整性、拒答合理性、引用一致性、格式约束、安全性。其次要尽量控制变量,同一条 prompt 下 chosen 和 rejected 最好只在少数关键质量点上有差异,不然模型学到的会是风格噪声而不是偏好本身。
更进一步一点,偏好数据还要控制难度分布。如果全是特别容易区分的样本,模型学不到真正有价值的边界;如果全是非常模糊的样本,标注一致性又会很差。比较稳的做法是保留一部分 easy pair 保证基础方向,再加一部分 hard pair 提高边界质量,同时混入 bad case 回流样本,让偏好优化更贴近线上真实问题。
4. vLLM 的核心原理是什么,它为什么能把推理吞吐做高
vLLM 的核心不是单独某个算子快,而是它把推理阶段最稀缺的资源——KV cache——管理得更高效。传统推理服务里,KV cache 往往按请求整块预留,容易产生显存碎片和浪费;vLLM 引入类似分页的内存管理方式,把 cache 切成更小的块统一调度,这样不同请求之间可以更灵活地复用显存。
它吞吐高的原因也不只是显存利用率提升,还因为这套 cache 管理能让动态 batching 更激进。在线推理里,请求长度不一致、结束时间不同,如果 cache 管理粗糙,batch 很快就散了;而 vLLM 可以更稳地维持高并发,从系统层面把 GPU 压满。
5. Dense Retrieval 到底是怎么做检索的,和 BM25 的差异不只是“稠密向量 vs 稀疏词项”
Dense Retrieval 的基本思路是把 query 和文档分别编码成向量,然后在向量空间里做近邻搜索,常见是内积或者余弦相似度。它和 BM25 的根本差异不只是表示形式不同,而是匹配逻辑不同。BM25 更依赖词项重合和统计权重,所以关键词匹配能力强、可解释性好;Dense Retrieval 更擅长语义层面的近义和改写,但也更容易受到训练分布影响。
真正做深一点,要意识到 Dense Retrieval 的效果并不只取决于 encoder 本身,还取决于负样本构造、向量归一化、索引方式和 query 分布。很多人把 dense 检索理解成“算个 embedding 去搜就行”,实际上 hard negative 的质量往往比模型结构本身更决定上限。
import torch import torch.nn.functional as F query = torch.randn(1, 768) docs = torch.randn(5, 768) query = F.normalize(query, dim=-1) docs = F.normalize(docs, dim=-1) scores = query @ docs.t() topk = torch.topk(scores, k=3, dim=-1) print(topk.indices) print(topk.values)
6. RRF 为什么在检索系统里常被拿来做融合,它解决了什么问题
RRF,也就是 Reciprocal Rank Fusion,本质上是一种基于排序位置的融合方法。它不要求不同召回器的分数在同一标尺上可比,而是只看文档在各个排序列表里的名次,然后通过倒数形式加权汇总。这样做的好处是鲁棒,不容易被某一路召回器的分数分布失真拖偏。
它适合用在混合检索里,比如把 BM25、Dense Retrieval、规则召回甚至知识图谱召回的结果融合在一起。相比直接加权分数,RRF 对分数校准要求更低,更适合真实系统里“多路召回质量不错,但分数不可直接比较”的情况。
def rrf(rank_lists, k=60):
score = {}
for ranks in rank_lists:
for i, doc_id in enumerate(ranks, start=1):
score[doc_id] = score.get(doc_id, 0.0) + 1.0 / (k + i)
return sorted(score.items(), key=lambda x: x[1], reverse=True)
rank_a = ["d1", "d2", "d3", "d4"]
rank_b = ["d3", "d2", "d5", "d1"]
print(rrf([rank_a, rank_b]))
7. 当用户觉得 RAG 回答“毫不相关”时,整条链路该怎么排查
“毫不相关”通常先看检索链路,而不是先怪生成模型。首先查 query 是否被正确理解,比如是否有歧义、缩写、口语化表达没有被 query rewrite 处理;接着查索引侧,文档切分有没有把关键信息切碎,embedding 模型是否和语料领域匹配,召回 topk 里有没有真正相关的 chunk。如果 topk 本身就错了,生成阶段基本没有可救空间。
如果召回结果里其实有相关证据,但最后答案还是不相关,那问题就落到 rerank、context packing 或 prompt 约束上了。比如把太多噪声片段拼进 prompt,或者模型被模板诱导做泛泛总结而不是基于证据回答。排查时一定先区分“没召回到”和“召回到了没用好”,这两类问题修法完全不同。
8. 当用户觉得 RAG 回答“相关但错误”时,问题通常出在哪
“相关但错误”说明证据大概率进了上下文,只是模型利用错了。常见
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏聚焦 AI-Agent 面试高频考点,内容来自真实面试与项目实践。系统覆盖大模型基础、Prompt工程、RAG、Agent架构、工具调用、多Agent协作、记忆机制、评测、安全与部署优化等核心模块。以“原理+场景+实战”为主线,提供高频题解析、标准答题思路与工程落地方法,帮助你高效查漏补缺.