好未来 大模型算法 二面
1. 自我介绍 简单聊聊你写的这个项目
2. bge-m3 的预训练过程是什么,为什么它可以高效检索
bge-m3 的核心不只是“做 embedding”,而是把多种检索信号统一进同一个模型框架里。它同时支持 dense、sparse 和 multi-vector 三种表示。dense 负责语义层面的相似性,sparse 更接近词项权重匹配,multi-vector 则适合处理长文档、多粒度语义对齐。这样一个 query 不再只依赖单一路径召回,所以在复杂检索场景里更稳。
从训练角度看,它一般不是只靠单一对比学习目标,而是会结合多任务数据,让模型既学语义匹配,也学词面相关性和局部对齐能力。高效检索的原因有几个。第一,向量化之后 ANN 检索本身就比全量精匹配快。第二,它把单向量和多向量能力都建好了,减少了传统系统里多个模型串联的损耗。第三,多语言和多功能统一建模后,线上可以共享一个编码框架,工程上更容易落地。
3. 如果用 bge-m3 做检索系统,dense、sparse、multi-vector 三路怎么融合
最常见的方式不是三路简单拼起来,而是先分别建立候选集合,再做分数归一化和融合。dense 路径适合召回语义相近但字面差异大的样本,sparse 路径适合强关键词约束和实体词检索,multi-vector 路径更适合长文档内部的细粒度片段匹配。三路结合的关键不是“多”,而是不同路径解决不同错误类型。
在线上通常会先分别取 top-k,再把候选做去重合并,然后根据 query 类型动态分配权重。比如题目检索更依赖 sparse 和 multi-vector,开放问答更依赖 dense。融合分数一般不能直接相加,要先做归一化,否则不同检索器的分数尺度不一致,后面排序会失真。再往后可以加一个轻量重排器,用 query 和候选文本重新打分。
def fuse_scores(dense_hits, sparse_hits, mv_hits, wd=0.4, ws=0.3, wm=0.3):
pool = {}
def add_hits(hits, w, key):
if not hits:
return
scores = [x["score"] for x in hits]
mn, mx = min(scores), max(scores)
for item in hits:
s = item["score"]
norm_s = 0.0 if mx == mn else (s - mn) / (mx - mn)
doc_id = item["doc_id"]
if doc_id not in pool:
pool[doc_id] = {"doc_id": doc_id, "score": 0.0, "source": []}
pool[doc_id]["score"] += w * norm_s
pool[doc_id]["source"].append(key)
add_hits(dense_hits, wd, "dense")
add_hits(sparse_hits, ws, "sparse")
add_hits(mv_hits, wm, "multi_vector")
return sorted(pool.values(), key=lambda x: x["score"], reverse=True)
4. 为什么选择 DBSCAN,在百万级数据里效率会不会太低
如果任务目标是做 query 聚类、异常样本识别或者伪标签发现,DBSCAN 的一个优势是它不需要预先指定簇数,而且天然能识别噪声点。对真实业务数据来说,噪声往往很多,很多 query 其实不应该硬归进某个簇里,DBSCAN 在这方面比 KMeans 更自然。它也能识别非球形簇,这在向量分布复杂时是有意义的。
在百万级数据上,朴素 DBSCAN 的确会慢,因为邻域搜索开销很大。但工程上一般不会直接拿 CPU 暴力跑。常见做法有三种:一是先降维再聚类,比如 PCA;二是用近邻索引加速半径查询;三是直接用 GPU 版本,比如 cuML 的 DBSCAN。这样它就不是完全不可用的问题,而是要结合数据维度、邻域搜索实现和硬件环境来看。如果向量维度太高且局部密度差异很大,HDBSCAN 有时反而更稳。
from cuml.cluster import DBSCAN import cupy as cp # 假设 x 已经是 GPU 上的向量 x = cp.random.rand(100000, 128).astype(cp.float32) model = DBSCAN(eps=0.3, min_samples=10) labels = model.fit_predict(x) print(labels[:10])
5. 如果访客对生成的回答点赞,这部分数据如何用于 DPO 训练
点赞本身不是标准偏好对,它只是一个单边正反馈。所以不能直接把“点赞答案”拿去当 chosen,然后随便找个负样本当 rejected。更稳妥的方式是先做偏好对构造。比如同一个 query 下,如果有多个候选答案,可以把被点赞、被复制、停留时间长、追问少的答案作为 chosen,把未被点击、快速跳出、被点踩或者引发追问纠错的答案作为 rejected。这样偏好信号更可信。
如果没有天然成对答案,可以做两阶段构造。先收集高质量单边反馈,再通过离线采样构造对比样本。负样本来源可以是旧版本模型输出、低分 rerank 候选、人工改写劣质答案,或者同 query 下弱表现答案。要注意的是,点赞通常带有展示位置偏差和幸存者偏差,所以训练前最好先做去偏,比如按曝光位置、用户类型、问题难度分桶采样。
6. 为什么要对 chosen 和 rejected 做相似度过滤,这会不会忽视某些场景
做相似度过滤的核心原因是很多偏好对表面上是两条答案,实际上几乎一样。这样的样本对 DPO 的训练信号很弱,因为 chosen 和 rejected 的 token 级 log probability 差异很小,模型学不到稳定偏好,还容易被噪声带偏。尤其是很多日志里 rejected 只是 chosen 改了几个语气词,或者顺序略有变化,这类样本留太多反而会拖训练效果。
但过滤得太狠也确实会忽略某些关键场景。比如教育问答里,一个回答只错了一个公式符号,语义相似度可能很高,但事实质量差异非常大。如果只看文本相似度,这种高相似但强质量差的 pair 会被误杀。所以实际做法通常不是只看 embedding 相似度,而是加业务规则,比如答案正确性、一致性检查、是否包含关键步骤、是否引用了正确知识点。也就是说,相似度过滤只是第一层,不能替代质量判别。
7. 如果收集到的是单点数据,DPO 里只有 chosen 或者只有 rej
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏聚焦 AI-Agent 面试高频考点,内容来自真实面试与项目实践。系统覆盖大模型基础、Prompt工程、RAG、Agent架构、工具调用、多Agent协作、记忆机制、评测、安全与部署优化等核心模块。以“原理+场景+实战”为主线,提供高频题解析、标准答题思路与工程落地方法,帮助你高效查漏补缺.