腾讯 AI应用开发 一面
1. 做一下自我介绍
2. 讲一下你做的这个平台,重点说难点 解决了什么问题
这个项目的核心不是“把文档喂给模型”,而是先把不同来源的材料转成可稳定检索、可引用、可更新的知识单元。整体架构一般包括文档接入、格式解析、结构抽取、分块与向量化、倒排索引、重排服务、回答生成和引用回填。我负责的部分主要是 chunk pipeline、索引写入和查询编排。难点主要在复杂文档结构,比如目录、页眉页脚、跨页表格、附件引用和条款层级,如果直接按长度切块,召回会很乱,模型也很容易把不同证据拼错。
def build_index(doc):
blocks = parse_document(doc)
chunks = semantic_chunk(blocks)
vectors = embed(chunks)
save_dense_index(vectors)
save_sparse_index(chunks)
3. RAG 里你是怎么做分块的,为什么不能只按固定长度切
固定长度切块最大的问题是它不理解语义边界和结构边界。对说明文、合同、技术文档这种层级清晰的文本,硬切容易把定义和解释拆开,把结论和证据拆开,最后召回虽然相关,但上下文不完整。真正稳定的做法通常是结构优先、长度兜底,也就是先按标题、段落、表格、列表、章节关系切,再控制每块 token 上限,必要时加 overlap。这样做的目标不是让块更整齐,而是保证每个 chunk 本身就尽量自解释。
4. 不同文档类型你会怎么做分块,像 PDF、Word、网页、表格会一样吗
不会一样。PDF 更麻烦,因为它很多时候只有视觉布局,没有天然结构,要先做版面分析和阅读顺序恢复;Word 的结构信息通常更完整,可以利用标题层级、段落样式、表格和批注;网页则要先清洗导航、广告和重复模板,再抽正文和层级节点;表格文档不能简单按行切,因为很多语义是表头和单元格关系共同决定的。真正好的分块不是统一规则,而是根据载体决定结构恢复方式,再把它映射到统一 chunk schema。
5. 你常见的分块策略有哪些,什么时候会选哪一种
常见的策略有固定窗口切分、滑动窗口切分、基于段落切分、基于标题层级切分、基于语义相似度切分,以及结构化对象切分,比如按表格、代码块、FAQ 对来切。固定窗口实现最简单,但更适合结构弱、容错高的场景;标题层级适合文档规范的知识库;语义切分更适合长段连续文本,但成本更高;结构化对象切分对表格、接口文档、法律条文这类内容效果通常更稳。项目里一般不是只用一种,而是组合使用。
6. 语义分割策略如果往深了讲,真正难点在哪
语义分割不是“找一句话意思变了就切开”这么简单。它真正难在两个地方,一个是语义变化并不总是突变,很多文档是缓慢推进的;另一个是切分不仅影响召回,还影响引用和后续回答组织。过细会丢上下文,过粗会引入噪声。比较稳的做法通常是先做结构切分,再在长段内根据 embedding 相似度、主题漂移或者 discourse signal 做二次切分,同时保留父子关系,方便查询时回溯原始结构。
7. Word 文件你一般怎么做 chunk,尤其是带目录、表格、脚注的复杂文档
复杂 Word 文档不能直接导成纯文本后切。更合理的是先抽出段落级结构,包括标题级别、编号、正文、表格、图片说明、脚注和批注,再重建一个树状文档结构。之后 chunk 时优先保留标题路径,例如“第三章-2.1-定义”这种层级前缀,让每个 chunk 自带位置语义。对于表格要把表头和行数据拼成自然语言或结构化 KV,不然单独一行没有意义;脚注如果和正文强绑定,也要在切块时合并进去。
chunk = {
"path": ["第三章", "2.1 定义"],
"content": "被授权方是指......",
"table_refs": ["table_12"],
"footnotes": ["注:本条仅适用于..."]
}
8. 你怎么评估分块效果到底好不好,不能只说看最终回答对不对
只看最终答案太晚了,而且很难归因。分块效果至少要从三个层面看:第一,单块是否语义完整,是否保留了结构信息;第二,检索层是否能把正确块稳定召回,尤其是 topK 命中情况;第三,回答层是否因为 chunk 粒度问题出现引用缺失、证据断裂或者噪声过多。实践里我会做 query-chunk 标注集,评估 recall@k、mrr、chunk coverage,同时人工检查 bad case 里到底是切错、召回错还是生成错。
9. 向量一般怎么存,如果数据规模非常大,存储方案怎么设计
小规模场景直接把 embedding 存数据库或向量扩展就够了,但数据一大就要把写入、检索、冷热分层和更新成本一起考虑。通常会把元数据存在 MySQL 或 ES,向量存专门的 ANN 索引系统,文档原文放对象存储或文档库。规模上来以后还会做分片、分租户隔离、冷热索引拆分和异步构建,避免每次更新都触发大范围重建。真正难的是更新策略和查询延迟,不是“向量放哪”这一个点。
10. 如果文件更新了,向量数据库怎么更新才比较合理
最差的做法是整库重建,最稳的做法是基于文档版本和 chunk 粒度做增量更新。先对文档解析结果做 diff,找出新增、修改、删除的 chunk,只对受影响部分重新 embedding 和写索引,同时保留版本号和可回滚信息。这样既能控制成本,也能避免查询时新旧数据混杂。对于延迟敏感场景,还会设计双索引或影子索引,先构建新版本,再原子切流。
public void refreshDocument(String docId, String newContent) {
List<Chunk> oldChunks = chunkRepo.findByDocId(docId);
List<Chunk> newChunks = chunkService.split(newContent);
DiffResult diff = diffService.compare(oldChunks, newChunks);
vectorStore.delete(diff.getDeletedIds());
vectorStore.upsert(diff.getChangedChunks());
}
11. RRF 是怎么计算的,为什么很多混合检索喜欢用它
RRF 的核心思想很直接,不去比较不同检索器的原始分数,而是比较它们的排序位置。每个文档在不同召回列表里根据 rank 得到一个倒数分值,最后把这些分值相加。这样做的好处是稳,不依赖不同检索器分数空间可对齐。因为稠密检索和稀疏检索的 score 往往量纲不同,直接融合容易失真,而 RRF 只看名次,工程上更容易落地。
def rrf_score(ranks, k=60):
score = 0.0
for r in ranks:
score += 1.0 / (k + r)
return score
12. 稠密向量、BM25、TF-IDF 这三者如果放到一个系统里,你怎么理解它们的关系
TF-IDF 更像早期的词项权重思想,BM25 是在它基础上的工程化改进,适合做关键词匹配和倒排检索;稠密向量则更强调语义相似,适合解决同义表达、口语化提问和隐式关联。它们不是替代关系,而是互补关系。稀疏方法对关键词、专有名词、编号、精确术语特别敏感,稠密方法对语义泛化更好。真正上线系统里,往往先让两者都召回,再通过融合或重排解决各自偏差。
13. 除了 RRF,你还会用哪些检索优化策略
除了融合,我还会看 query rewrite、multi-query、元数据过滤、领域同义词扩展、chunk 邻接扩展、交叉编码器重排和答案前置摘要。比如用户问题模糊时先做改写,能显著提升召回稳定性;文档强结构场景下,把命中的 chunk 连同上下邻居一起喂给重排,通常比只看单块更稳;对高价值场景还会引入 cross-encoder 重排,哪怕成本高一点,也能压住 bad case。优化检索的关键不是堆技术,而是明确你是在补召回、补排序还是补上下文。
14. MySQL 的索引有哪些,真正线上最重要的是怎么选而不是怎么背
常见索引类型大
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏聚焦 AI-Agent 面试高频考点,内容来自真实面试与项目实践。系统覆盖大模型基础、Prompt工程、RAG、Agent架构、工具调用、多Agent协作、记忆机制、评测、安全与部署优化等核心模块。以“原理+场景+实战”为主线,提供高频题解析、标准答题思路与工程落地方法,帮助你高效查漏补缺.