字节一面:RAG七连问,前3题筛掉一半,最后一题几乎没人扛得住

发布时间:2026/7/7 21:30:51
字节一面:RAG七连问,前3题筛掉一半,最后一题几乎没人扛得住 周末有个读者找我说他面字节 Agent 开发岗一面聊了四十分钟项目其中将近半小时全在追问他的 RAG 系统。不是那种你用了什么向量数据库chunk size 设了多少的表面问题。是从数据源头开始一层一层往下扒扒到第七层他发现自己简历上写的基于 RAG 的智能问答系统其实只做了皮毛。他说面试官的追问节奏特别有意思——每个问题看起来都在上个问题的基础上往下挖你第一个答得虚第二个就接不住第三个直接露馅。我听完他复述的七个问题第一反应是这不是在考 RAG这是在考你到底有没有真正做过数据工程。太多人的 RAG 项目是这套流程找几份 PDF用 LangChain 的 loader 读进来recursive splitter 切一刀往向量库一扔接个 LLM 生成回答完事。简历上写构建了完整的 RAG 知识库面试官一追问发现数据清洗没做、增量更新没有、冲突处理没想过、版本控制是什么都不知道。今天我就把这七个问题拆开聊。每一个我都给你讲到落地细节不是给你背概念。如果你也在做 RAG 项目准备面试这篇文章建议存下来反复看。第一问你的数据来源是什么这题看起来最温和其实是陷阱。很多人张口就来“我们用的是公司内部文档主要是 PDF 和 Markdown。”面试官不说话等你往下讲。然后你就卡住了。因为你不知道面试官想听什么。这个问题真正在考的是你有没有想清楚你的知识库到底要覆盖什么以及这些数据源的异构性会带来什么后果。你得这么答。先分类。数据源不是PDF 和 Markdown这种按文件格式分的而是按结构化程度分数据类型举例处理难度关键挑战结构化数据数据库表、API 返回的 JSON、Excel 表格低语义对齐字段映射半结构化数据Markdown、HTML、Confluence Wiki中噪声清洗结构提取非结构化数据PDF、Word、扫描件、图片高格式解析版面恢复然后你得说出每个数据源的具体问题。比如内部 Wiki最恶心的是什么是它有大量的历史版本、草稿、模板页、纯导航页。你如果不过滤直接入库用户问报销流程是什么检索出来三条结果一条是三年前的旧版一条是草稿箱的半成品一条是模板说明。回答能靠谱才怪。再比如 API 文档Swagger 自动生成的那种里面全是 schema 定义和示例 JSON信息密度极低。你按 512 token 切 chunk一个 chunk 里可能就一个字段定义检索命中了也没法回答问题。所以这个问题的高分回答是“我们的数据源主要分三类内部 Wiki 文档、产品 PDF 手册、以及业务系统的结构化数据接口。三类数据的异构性是后续所有处理的起点——Wiki 需要做噪声过滤和历史版本去重PDF 需要做版面解析和表格抽取结构化数据需要做语义映射转成自然语言描述。数据源的分类不是按格式分而是按结构化程度分因为它直接决定了你的 preprocessing pipeline 要分几条。”一句话让面试官知道你不是随便拿几份 PDF 就开干的。第二问数据源有很多冗余的无关信息入库前怎么处理的这题是第一问的自然延伸。面试官已经知道你的数据源了现在要听你做没做数据清洗。太多人在这题上翻车。翻车的方式高度一致——说我们做了一些清洗然后讲不出任何具体细节。数据清洗不是一句去掉了无关信息就能糊弄的。你得讲清楚洗什么、怎么洗、用什么工具、怎么判断洗得对。一个真正做过数据工程的 RAG 系统入库前的清洗 pipeline 至少包含五层第一层去重不是简单的文件级去重是内容级去重。同一个知识点可能在三份文档里都出现了描述还略有不同。你全入库检索时三条都召回LLM 拼在一起生成回答可能自相矛盾。怎么做对每个 chunk 算一个内容指纹。不是 MD5MD5 对空格、标点敏感稍微改一个字就变了而是用SimHash或者MinHash对文本做分词后生成局部敏感哈希。两个 chunk 的 SimHash 海明距离小于 3就判定为近似重复。from simhash import Simhashdef compute_simhash(text: str) - int: # 分词后计算 SimHash tokens jieba.lcut(text) return Simhash(tokens).valuedef is_duplicate(hash1: int, hash2: int, threshold: int 3) - bool: # 海明距离小于阈值视为重复 return bin(hash1 ^ hash2).count(1) threshold保留策略同内容多版本时保留来源权威性最高的那份。什么叫权威性高官方文档 内部 Wiki 个人笔记。这个优先级要在 metadata 里标好。第二层噪声过滤PDF 和 HTML 里最多的不是正文是噪声。HTML 文档有导航栏、侧边栏、页脚、广告、cookie 提示。PDF 有页眉页脚、目录页、空白页、纯封面页。过滤策略分两类基于规则的过滤删掉长度低于阈值的 chunk通常是 50 字以下大概率是页眉页脚碎片、删掉重复出现的固定文本跨页出现的页眉、删掉纯数字/纯符号 chunk。基于模型的过滤用一个轻量分类模型甚至可以是规则 关键词判断 chunk 是不是实质内容。比如判断一个 chunk 包含的实词比例低于 30% 的直接扔掉。第三层PII 脱敏内部文档里大概率有手机号、身份证号、内部 IP、员工工号。这些进向量库一是安全风险二是对检索没用。正则 NER 模型双保险。正则抓格式固定的手机号、身份证号NER 模型抓格式不固定的人名、公司名。第四层编码与格式统一PDF 提取出来的文本编码可能是 UTF-8、GBK、Latin-1 混着来。全量转 UTF-8全角半角统一不可见字符清掉。听着简单但这步不做后面 embedding 出来的向量全是垃圾。第五层质量评分不是所有清洗完的 chunk 都值得入库。给每个 chunk 打一个质量分信息密度实词占比语义完整性是否是一个完整的知识点来源权威性官方文档 个人笔记低于阈值的不入库。宁可少一点不要烂的进来污染检索。这五层讲完面试官知道你是真做过数据清洗的不是嘴上说说。第三问PDF 中的各种形式你是怎么处理的这题是上一题的深入版。面试官专门拎 PDF 出来问因为 PDF 是非结构化数据里最难啃的骨头。很多人答这题就是一句我们用了 PyPDF2 提取文本。不够。远远不够。PDF 难处理是因为它本质上是一个排版描述语言不是文档格式。它记录的是在坐标 (x, y) 处画一个字不是这是第一段第二行。所以 PDF 解析的核心挑战是从位置信息还原语义结构。你得把 PDF 里的内容分成五种类型分别处理1. 纯文本段落用 PyMuPDFfitz提取比 PyPDF2 强不少。PyMuPDF 能拿到文本块的坐标信息可以基于坐标做版面分析。关键点多栏排面的处理。很多技术文档是双栏的你按从上到下、从左到右读文本是乱的。得先做栏检测基于文本块的 x 坐标聚类把左右栏分开读再合并。2. 表格这是 PDF 解析里最恶心的部分。表格在 PDF 里就是一堆线条和文字没有表格这个语义标签。你得自己判断哪些线条围成了一个表格哪些文字属于同一个单元格。工具选择工具适用场景局限Camelot有明确边框线的表格无线框表格识别不了Tabula规则表格复杂合并单元格不行PaddleOCR PP-Structure扫描件表格、复杂表格依赖模型有误检LLM 辅助不规则表格、语义复杂的表格成本高速度慢实际工程里的做法先用 Camelot 试提不出来的用 PP-Structure 跑 OCR 版面分析最后对关键复杂表格用 LLM 做 structured extraction。提取出来的表格不要直接当文本塞进 chunk。转成 Markdown 表格或者 JSON 结构保留行列关系。否则 LLM 拿到一堆没有结构的数字根本没法理解。3. 图片图片分两类装饰性图片logo、背景图、分隔线和信息性图片流程图、架构图、数据图表。装饰性的直接扔掉。信息性的要处理——但不是做 OCR 就完了。你得判断图片里有没有文字。有文字的OCR 提取。没有文字但是是流程图的用多模态模型生成文字描述。把描述和原图的引用一起存进 chunk。4. 页眉页脚跨页重复出现的固定文本基于频率检测如果一个文本块在超过 30% 的页面里出现判定为页眉/页脚全局清除。5. 目录和书签PDF 的书签是结构化信息直接提取作为文档的章节层级。这个层级信息后面切 chunk 的时候有大用——按章节切比按固定长度切靠谱得多。讲完这五种再补一句总结“PDF 处理的核心思路是分类处理纯文本走版面分析表格走结构化提取图片走 OCR 多模态描述噪声走频率检测清除。不是一把梭用 PyPDF2 read 一下就完事的。不同内容类型的处理策略完全不同混在一起处理是 RAG 质量上不去的主要原因之一。”第四问有没有做知识抽取怎么做的前三问在考数据处理从这题开始面试官转向了知识层面的处理。很多人把知识抽取和分块搞混了。分块chunking是把文档切成片段知识抽取是从片段里提炼结构化信息。这是两件事。知识抽取做什么三个层面实体抽取从文本里识别出关键实体产品名、技术名词、人名、组织名、版本号。为什么重要因为用户提问往往是以实体为锚点的。“Spring Boot 3.0 的自动配置和 2.7 有什么区别”——这个问题里Spring Boot 3.0和Spring Boot 2.7是核心实体你得能识别出来才能做精准检索。做法NER 模型spaCy、HanLP LLM 辅助。模型抓通用实体人名、地名LLM 抓领域实体产品名、技术名词。关系抽取实体之间什么关系。“Spring Boot 依赖 Spring Framework”“Kafka 用 ZooKeeper 做协调”。这些关系不只是为了建知识图谱更重要的是在检索时做关联扩展。用户问 Kafka 的协调机制你不仅检索 Kafka 相关的 chunk还能通过关系图谱扩展到 ZooKeeper 相关的内容。元数据增强每个 chunk 除了存原文和向量还要存结构化元数据{ chunk_id: chunk_0823,content: Spring Boot 3.0 引入了 spring-boot-starter-web 的自动配置重构...,source_doc: spring-boot-3-migration-guide.pdf,page: 23,section: 自动配置变更,entities: [Spring Boot 3.0, spring-boot-starter-web],keywords: [自动配置, starter, 迁移],doc_version: v3.0.1,ingest_time: 2025-06-15T10:30:00Z}这些元数据后面每一问都会用到。增量更新靠它冲突处理靠它版本控制也靠它。如果你只存了 content embedding后面六问全部答不上来。知识抽取的落地推荐用 LLM function callingextraction_prompt 从以下文本中抽取结构化信息文本{chunk_text}请抽取1. 关键实体产品名、技术名词、版本号等2. 实体间关系3. 核心关键词3-5个4. 一句话摘要以 JSON 格式返回。用 GPT-4o-mini 或 Claude Haiku 做抽取成本可控效果远好于纯规则。第五问增量更新是怎么做的这题是分水岭。前四问你答得好说明你做过 RAG。这题你答得好说明你上线运营过RAG。没上线过的人数据是一次性全量灌进去的从来没想过增量更新。但真实场景里知识库是活的。文档会更新API 会改版产品手册会出新版。你不能每次都全量重建。增量更新的核心问题是怎么知道哪些文档变了变了之后怎么最小化更新。第一步变更检测每个文档入库时算一个内容哈希不是 SimHash是精确哈希用 SHA-256import hashlibdef compute_doc_hash(filepath: str) - str: with open(filepath, rb) as f: return hashlib.sha256(f.read()).hexdigest()维护一张文档注册表doc_idfilenamecontent_hashingest_timechunk_idsstatusdoc_001api-guide-v2.pdfa3f8b2…2025-06-01[c01, c02, c03]activedoc_002api-guide-v3.pdf7e1c09…2025-06-15[c04, c05, c06]active定时扫描源目录对比哈希新文件 → content_hash 不在表里 → 新增文件变了 → content_hash 不同 → 更新文件删了 → 注册表里有但扫描不到 → 软删除第二步最小化更新文档变了不是全量删掉重新切重新嵌入。那太贵了。做法是文档级 diff把旧文档和新文档分别切块对新旧 chunk 列表做对齐用 SimHash 找近似匹配没变的 chunk → 跳过变了的 chunk → 删旧的嵌新的新增的 chunk → 嵌入入库删除的 chunk → 标记失效软删除不是物理删留版本回溯用def incremental_update(doc_id: str, new_chunks: list, old_chunks: list): # 用 SimHash 对齐新旧 chunk old_hashes {c.id: compute_simhash(c.text) for c in old_chunks} new_hashes {c.id: compute_simhash(c.text) for c in new_chunks} to_add [] # 新增 to_update [] # 更新 to_delete [] # 删除 for new_chunk in new_chunks: matched False for old_id, old_hash in old_hashes.items(): if is_duplicate(new_hashes[new_chunk.id], old_hash): # 近似匹配内容可能有微调判断是否需要更新 if content_changed_beyond_threshold(new_chunk, old_chunks[old_id]): to_update.append((old_id, new_chunk)) matched True break ifnot matched: to_add.append(new_chunk) for old_id in old_hashes: if old_id notin [m[0] for m in to_update]: to_delete.append(old_id) # 执行最小化操作 batch_embed_and_insert(to_add) batch_embed_and_replace(to_update) soft_delete(to_delete)第三步Embedding 版本管理这里有个坑如果你换了 embedding 模型旧向量和新向量不在同一个空间相似度计算全是错的。所以 embedding 模型版本也要存进 metadata。换模型时走全量重新嵌入的流程而不是增量。面试官追问换模型怎么办时你的回答是“全量重建走灰度切换——新模型先在全量数据上跑一遍存到新 collection双写一段时间验证检索质量确认没问题再切流量。”第六问如果不同文档里的内容冲突了你是怎么处理的这题考的是你的系统有没有冲突感知能力。什么是冲突用户问我们的报销审批流程是什么检索到两个 chunkchunk A来自 2024 年版的行政手册“报销需部门经理审批后交财务”chunk B来自 2025 年新版行政手册“报销需直属主管审批后交财务共享中心”内容矛盾。LLM 拿到这两个 chunk要么随机选一个要么把两个揉在一起生成一个不存在的流程。两种都是错的。冲突处理的策略分三层第一层预防——来源权威性排序入库时就给每个文档打权威性标签权威性等级来源示例L1 最高官方文档、最新版规范产品官方手册 v3L2 高内部正式文档公司Wiki正式发布的页面L3 中内部非正式文档团队笔记、会议纪要L4 低外部非正式来源博客、论坛帖子检索时如果多个 chunk 语义相似但内容冲突优先取权威性高的。实现方式在向量检索后加一层 rerank对冲突的 chunk 按权威性排序def rerank_by_authority(results: list) - list: # 检测冲突语义相似但内容不同的 chunk conflict_groups detect_conflicts(results) for group in conflict_groups: # 按权威性排序低权威的降权或过滤 group.sort(keylambda x: x.metadata[authority_level]) # 保留最高权威的其余降权但不删除保留给 LLM 参考 for i, chunk in enumerate(group): if i 0: chunk.score * 0.3 # 降低相似度分数 return sorted(results, keylambda x: x.score, reverseTrue)第二层检测——语义矛盾识别光有权威性排序不够你得先知道冲突发生了。冲突检测方法对召回的多个 chunk 做两两比较。如果语义相似度高于 0.85说明在讲同一件事但关键实体/数值不同判定为冲突。更靠谱的做法是用 LLM 做冲突判断conflict_detection_prompt 以下是从知识库中检索到的多个片段请判断它们之间是否存在内容矛盾片段A{chunk_a}片段B{chunk_b}如果存在矛盾指出矛盾点。如果只是表述不同但语义一致不算矛盾。第三层处理——冲突消解策略检测到冲突后四种处理方式权威性优先取高权威来源的内容低权威的丢弃时效性优先取更新时间更晚的适用于文档版本更新场景LLM 融合把冲突信息连同来源信息一起给 LLM让它在生成回答时标注差异“根据 2025 年最新版手册报销流程为……注旧版流程为……已更新”上报人工关键业务冲突比如安全规范、合规要求不要自动消解标记冲突上报知识库管理员第三种是最实用的。不是非此即彼而是让 LLM 在回答里体现信息差异把判断权交给用户。第七问有没有做版本控制如果新同事把错误文档入库了怎么办最后一问也是最深层的一问。前六问都在考系统设计能力这题在考你的系统有没有可运营性和容错能力。版本控制不是 Git 那种代码级别的版本控制是知识库级别的版本管理。要回答这个问题你得有一套完整的知识库治理方案文档版本管理每个文档入库时记录版本信息doc_id: doc_0823filename: api-guide.pdfversion: v3.2content_hash: a3f8b2...parent_version: v3.1 # 上一版本ingest_time: 2025-06-15T10:30:00Zingest_by: zhang_sanstatus: active每次更新不是覆盖是新增一个版本。旧版本的 chunk 不删除标记为superseded。这样可以随时回溯到任意历史版本。入库审核机制错误文档入库的问题本质是缺少入库前的审核环节。分级审核文档类型审核要求全局知识库文档需管理员审核 预览检索效果团队级文档需团队负责人审核个人沙箱文档无审核但仅对本人可见不进全局检索入库不是直接写向量库而是先进暂存区[上传文档] → [暂存区] → [自动质检] → [人工审核] → [正式入库]自动质检包括文档完整性检查是否空文件、是否乱码内容质量评分信息密度是否达标重复检测是否与已有文档高度重复敏感信息扫描是否包含不该入库的内容回滚机制万一错误的文档已经入库了怎么处理三步第一步隔离。不是直接删除而是把该文档关联的所有 chunk 标记为quarantined从检索中排除。这比物理删除安全——万一判断错了还能恢复。def quarantine_document(doc_id: str, reason: str): chunks get_chunks_by_doc(doc_id) for chunk in chunks: chunk.metadata[status] quarantined chunk.metadata[quarantine_reason] reason chunk.metadata[quarantine_time] datetime.now().isoformat() # 从检索索引中移除但保留存储 vector_store.update_metadata(chunks)第二步回滚。如果文档更新导致问题回滚到上一个版本。因为有版本管理只需要把旧版本的 chunk 状态从superseded改回active新版本的 chunk 改为quarantined。第三步影响评估。检查在错误文档入库期间有没有用户问答命中了这些 chunk。如果有记录影响范围必要时通知相关用户。操作审计所有入库、更新、删除操作全部记录审计日志时间操作人操作类型文档ID版本状态2025-06-15 10:30zhang_saningestdoc_0823v3.2active2025-06-15 14:00li_siquarantinedoc_0823v3.2quarantined2025-06-15 15:00li_sirollbackdoc_0823v3.1active出问题能追溯能定位能恢复。七问之后面试官到底在找什么样的人回过头看这七个问题你会发现一条主线面试官不是在考你知不知道 RAG 的概念而是在考你有没有真正从数据源头到上线运营完整地趟过一遍。第一问考你对数据源的理解——你知不知道数据异构性是所有问题的起点。第二问考你的数据工程能力——你有没有做过清洗 pipeline。第三问考你的细节处理能力——PDF 这种难啃的骨头你有没有真碰过。第四问考你的知识建模能力——你有没有从存文本升级到存结构化知识。第五问考你的工程运营能力——系统上线后怎么维护。第六问考你的系统鲁棒性思维——数据冲突这种真实场景你有没有预案。第七问考你的容错和治理能力——出了问题能不能兜底。七问层层递进每一问都在前一问的基础上往下挖。你前面答得虚后面就接不住。很多人觉得 RAG 简单——加载文档、切块、嵌入、检索、生成五步搞定。面试官也知道简单。所以他不会问你五步是什么他问你每一步里面的坑是什么、你怎么处理的、有没有兜底方案。能答上来说明你真做过。答不上来说明你看了个教程就写简历了。最后说一句。RAG 项目的深度不在于你用了什么先进的 embedding 模型或者什么花哨的 rerank 策略。在于你对数据的理解有多深对工程细节的把控有多严。模型是别人的数据是你的。数据工程做到位了即使用最朴素的 embedding cosine similarity检索效果也不会差。数据工程没做到位用再贵的模型也是垃圾进垃圾出。这句话面试的时候你可以不说但心里一定要有。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】