Wiki-CN RAG 问答系统 · 面试准备指南

发布时间:2026/6/11 16:16:15

Wiki-CN RAG 问答系统 · 面试准备指南 Wiki-CN RAG 问答系统 · 面试准备指南基于qa_web/项目代码与 README 整理适用于软件开发实习生面试。目录一、开场 12 分钟项目介绍必背版二、技术栈分层说明三、项目运行流程从 0 到用户提问四、开发中遇到的问题与解决STAR 格式五、面试官可能问的问题 参考答案六、面试表达建议七、30 秒 / 2 分钟 / 5 分钟三个版本自我介绍面试官您好我是 XXXXXX 大学 XXX 专业来应聘软件开发实习生。我熟练掌握 Python、Web 基础自主学习大模型、RAG 相关开发关注 AI 软件落地开发。在校期间我担任班级班长也是一名共产党员擅长沟通协调、多任务处理学习上手快、并且能够吃苦耐劳敢于面对挑战对工作认真负责很高兴能参加贵公司的面试同时很期待成为公司的一员向前辈们学习为公司带来价值。这就是我的自我介绍谢谢。面试官您好我叫 XXX就读于 XXX 大学 XXX 专业应聘软件开发实习生。技术上我掌握 Python 与 Web 前后端基础课余自主钻研大模型与 RAG 应用开发动手vibe coding过如简历所示的三个AI 和软件开发结合的项目在校期间担任班长、中共党员长期统筹班级事务锻炼了多任务协调、高效沟通的能力抗压性不错。我自学能力强能快速适应项目技术栈做事严谨靠谱能按时完成开发任务。希望能加入贵公司跟着前辈们学习为公司带来价值。我的介绍完毕谢谢面试官。一、开场 12 分钟项目介绍必背版面试官先介绍一下这个项目。答我做的是一个基于中文维基百科Wiki-CN知识库的RAG 问答系统。背景与目标Wiki-CN 有约 130 万条百科条目、2GB 文本。直接让大模型回答容易幻觉所以我用 RAG先从本地知识库检索相关段落再交给 LLM 生成答案并给出参考文献。我负责的部分从数据处理、索引构建到后端 API、前端聊天界面和系统可观测性基本是端到端完成的。核心能力混合检索BM25关键词 向量检索ChromaDB BGE-M3用 RRF 融合重排序本地 BGE-Reranker 提升相关性生成主通道阿里云百炼 qwen-plus本地 Ollama 作备用Web 界面类 ChatGPT 的多会话聊天支持流式输出规模索引约290 万chunk服务启动后可在浏览器里对百科知识提问。一句话总结这是一个「本地百科知识库 混合检索 大模型生成」的完整 RAG 应用而不只是调 API 的 Demo。二、技术栈分层说明层次技术作用后端框架FastAPI UvicornREST API、页面渲染、流式响应前端HTML CSS 原生 JS聊天 UI、多会话、localStorage 持久化模板Jinja2服务端渲染首页、健康检查页数据校验Pydantic请求/响应模型语料处理OpenCC繁体转简体分词/检索jieba、rank-bm25、SentencePieceBM25 稀疏检索向量库ChromaDBHNSW稠密向量持久化检索EmbeddingBGE-M3本地 sentence-transformers查询/文档向量化RerankerBGE-Reranker-v2-m3CrossEncoder精排LLM阿里云百炼OpenAI 兼容 API、Ollama答案生成会话存储Redis可选/ 进程内存后端多轮对话历史配置python-dotenv.env环境变量评测RAGAS LangChain离线 RAG 质量评估面试加分说法Embedding 和 Reranker 尽量本地跑降低 API 成本生成走云端保证质量检索和生成解耦便于分别优化。三、项目运行流程从 0 到用户提问阶段 A离线构建一次性/增量Wiki-CN 原始 JSONprepare_corpus.py清洗 繁转简corpus_simplified.jsonlbuild_index.py切块 BM25 Embeddingchunks.jsonl / bm25.pklembeddings.f32 / chroma_dbprepare_corpus.py读 wiki-cn 原始文件 → 清洗去控制字符、零宽字符→ OpenCC 转简体 → 输出corpus_simplified.jsonl支持--resume断点续跑build_index.py按标题/句子切块 → 建 BM25 索引 → BGE-M3 批量 Embedding → 写入 ChromaDB产物chunks.jsonl、bm25.pkl、chroma_db/、embeddings.f32向量缓存用于重建常用命令# 生成简体语料python scripts/prepare_corpus.py--data-root../wiki-cn--output./build/corpus_simplified.jsonl# 构建索引python scripts/build_index.py--corpus./build/corpus_simplified.jsonl--build-dir./build--embed-model bge-m3--base-url http://127.0.0.1:11434/v1--resume--keep-emb-cache阶段 B在线服务POST /api/ask/stream用户浏览器FastAPI main.py会话管理 Redis/内存RagEngineQuery Rewrite 可选BM25 检索 Top-K向量检索 Chroma Top-KRRF 融合实体锚点 rescueReranker 重排LLM 生成答案启动conda activate ai_course cd qa_web python-m uvicorn app.main:app--host 0.0.0.0--port 8000--access-log--log-level info启动特点RAG 引擎在后台线程异步加载chunks → BM25 → Chroma → LLM 客户端页面可先打开失败则指数退避重试。一次问答前端带session_id、question、allow_web调/api/ask/stream后端取最近 N 轮历史最多 5 轮RagEngine.retrieve()混合检索 → 实体锚点补充 → Rerank → 取 Top 6本地证据不足且允许联网时SerpAPI 补充把 Top 3 证据每段约 320 字拼进 Prompt流式调用 LLM返回答案 参考文献会话写入 Redis 或内存可观测http://127.0.0.1:8000/api/health?formatjson重点字段engine_phase、index_ntotal、last_trace.timing_ms、last_vec_used、last_rerank_used。四、开发中遇到的问题与解决STAR 格式问题 1ChromaDB 索引损坏index_ntotal0现象health 显示向量索引为 0或报Error loading hnsw index。原因Chroma 的 SQLite 元数据在但 HNSW 向量文件不完整例如只有index_metadata.pickle缺少header.bin等。解决用已有embeddings.f32跑rebuild_chroma_from_cache.py重建后端缓存index_ntotal避免 health 每次慢 count启动时分阶段加载并上报engine_stage面试说法大索引构建易中断我保留了 embedding 缓存和重建脚本把「可恢复构建」当作工程能力的一部分。重建命令python scripts/rebuild_chroma_from_cache.py--build-dir./build--emb-cache./build/embeddings.f32--chroma-dir./build/chroma_db--collection-name wiki_cn_dense问题 2服务启动慢用户长时间白屏现象290 万 chunk BM25 Chroma冷启动要几分钟。解决后台 daemon 线程加载engine_phase: idle → loading → ready分阶段 ETAEMA 平滑预测剩余时间加载未完成时 API 返回友好提示而不是崩溃加载失败指数退避重试10s → 180s 上限面试说法大模型应用里「冷启动」是典型工程问题我用异步加载 状态机 健康检查而不是阻塞startup。问题 3答案对但参考文献不相关「牛头不对马嘴」现象LLM 答案还行但 references 是无关百科条目。原因混合检索对「谁创办了 X」「X 的原名是什么」等事实问法语义检索容易偏。解决实体锚点Anchor Rescue从问题抽核心实体如「阿里巴巴」「原名」在 title 索引里精确匹配补召回锚点优先排序参考文献按实体匹配强度重排RerankerCrossEncoder 对 query-doc 精排公开引用过滤候选完全不命中核心实体时不硬展示无关引用排查链路last_trace.anchor_terms、anchor_rescue_used、last_rerank_used面试说法RAG 质量不只看生成检索召回和排序同样关键我加了规则 模型的混合策略。问题 4响应延迟高现象首 token 和总耗时偏长。解决配置权衡默认关 Query Rewrite、Multi-hop少一次 LLM/检索只送 Top 3 证据、每段 320 字给 LLMLLM_MAX_TOKENS160控制生成长度Rerank 只对 Top 6 候选health 的timing_ms定位瓶颈llm_ms/rerank_ms/vector_ms面试说法我在延迟和质量之间做了可配置权衡并用 trace 做性能分析而不是盲目加功能。问题 5Redis 未启动现象启动报Redis 连接失败退回本地内存。解决Redis 可选连不上自动降级进程内存存会话。前端历史仍在localStorage核心问答不受影响。面试说法外部依赖要有 graceful degradation保证核心路径可用。问题 6LLM / Embedding 偶发超时解决失败计数 cooldown例如连续失败 2 次后冷却 6090 秒LLM 主备切换百炼 → Ollama → 抽取式兜底。五、面试官可能问的问题 参考答案基础认知类Q1什么是 RAG你为什么用 RAG 而不是直接问大模型ARAG 是 Retrieval-Augmented Generation先检索相关知识再让模型基于证据生成。Wiki 事实类问题若只靠模型预训练容易幻觉或过时RAG 能引用本地百科、给出处可控、可更新重建索引即可也更符合「知识库问答」场景。Q2BM25 和向量检索有什么区别为什么做混合检索ABM25稀疏检索擅长精确词匹配人名、专有名词、 rare token向量检索语义相似擅长 paraphrase“汽车”会匹配“轿车”单一方式有短板我用RRFReciprocal Rank Fusion融合两路排名互补召回再 Rerank 精排。BM25 保证了“字面匹配”的精确性向量检索提供了“语义相关”的泛化能力。混合检索同时拥有两者的优点适用于真实世界中既有专有名词又有模糊表达的综合查询。Q3RRF 是怎么工作的A不直接比 BM25 分和向量分量纲不同而是看排名score 1/(krank_bm25) 1/(krank_vector)k 通常取 60。两路都靠前的文档融合分更高。实现见app/rag_engine.py的_rrf_merge。Q4Reranker 和 Embedding 检索有什么不同AEmbedding 是双塔query 和 doc 分别编码再算相似度速度快但交互弱。RerankerCrossEncoder把 query 和 doc 拼一起打分更准但更慢。所以我先 hybrid 召回 Top 24再 Rerank Top 6平衡速度与质量。Embedding 检索是用双编码器快速从海量文档中圈出一批“看起来相关”的候选Reranker 是用交叉编码器对这批候选逐个仔细比较重新排出一个更精准的顺序。两者是“速度 vs 精度”的经典交换配合使用才能既快又准。Q5你的语料是怎么切块的ChunkingA先按 Markdown##标题分块过长再按句子切必要时字符窗口带 overlap控制长度。这样 chunk 尽量语义完整又不超过 embedding 上下文。架构与工程类Q6系统架构是怎样的A三层数据层Wiki-CN → 清洗语料 → chunks BM25 Chroma服务层FastAPIRagEngine封装检索与生成main.py管 API、会话、引擎生命周期展示层类 ChatGPT 前端流式 NDJSONlocalStorage 多会话Q7为什么用 FastAPIA异步友好、Pydantic 校验、OpenAPI 文档、StreamingResponse 做流式输出Python AI 生态numpy、chromadb、sentence-transformers集成方便。实习项目够用且易维护。Q8流式输出怎么实现的A后端/api/ask/stream返回application/x-ndjsonRagEngine.stream_answer()逐 chunk yield前端fetchReadableStream逐行解析边收边渲染。LLM 不可用则一次性返回抽取式答案。Q9多轮对话怎么做的A两层前端localStorage存会话列表和消息后端按session_id存最近 N 轮userassistantRedis 或内存TTL 24h生成时把 history 拼进 prompt支持追问。默认限制 5 轮控制 token 和干扰。Q10如果 LLM 挂了怎么办A三级降级主通道百炼 qwen-plus备用 Ollama 本地模型抽取式答案直接取 Top1 证据前两句话还有 failure threshold cooldown避免反复超时拖垮服务。深度追问类加分Q11290 万向量怎么存的检索性能如何AChromaDB PersistentClient HNSW。向量离线批量写入在线只对 query embedding 后 ANN 检索。大索引下collection.count()很慢所以 count 结果缓存health 不每次全量 count。向量检索慢时可调低TOP_K_VECTOR或临时FORCE_BM25_ONLY1做对比。Q12Embedding 为什么本地跑LLM 为什么上云A检索对每个问题都要 embedding调用量大本地 BGE-M3 成本低、延迟可控。生成对质量要求高云端 qwen-plus 效果更好本地 Ollama 作备用。职责分离便于分别优化成本和体验。Q13你怎么评估 RAG 效果A写了scripts/evaluate_rag.py用 RAGASfaithfulness、answer relevancy 等测试集eval_dataset.jsonl裁判模型用 qwen-max。线上用 health trace 人工抽测先看 references 是否相关再判断答案是检索问题还是生成问题。Q14Query Rewrite 和 Multi-hop 是什么为什么默认关闭AQuery Rewrite用 LLM 改写/query 扩展提升检索但每问多一次 LLM 调用Multi-hop根据首轮结果构造 follow-up query 再检索适合复杂推理默认面向简单事实问答为延迟和成本关闭调试复杂追问时可开。体现功能开关和场景化配置。Q15实体锚点 rescue 是什么思路A从问题模板抽核心实体「X 是谁创办的」→ X在title_to_rows索引里精确/模糊匹配标题补进候选。这是针对百科场景的规则增强检索弥补纯向量对专名的不足。不是写死单题规则而是覆盖常见事实问法模式。Q16如果让你继续优化会做什么A选 23 个说即可增量索引更新update_index.py已有基础缓存热门 query 的检索结果更细的分块策略按段落语义用户反馈点赞/点踩闭环优化容器化部署Docker Redis更完整评测集与 A/B 对比 hybrid vs BM25-only行为 / 项目 ownership 类Q17这个项目你独立完成的还是团队合作A按实际情况说可参考我独立完成从数据处理、索引构建、RAG 链路、FastAPI 后端到前端界面的主要开发。过程中查阅 RAG、Chroma、BGE 文档通过 health 接口和 README 记录运维经验方便后续维护。Q18遇到的最大困难是什么A用 Chroma 索引损坏 检索质量二选一深入最大困难是 Chroma HNSW 不完整导致向量检索失效。一开始只有 count0排查发现元数据和向量文件不一致。我保留 embedding 缓存、写重建脚本并在 health 暴露dense_ready、index_ntotal把「可诊断、可恢复」做进系统。这个过程让我理解ML 项目里数据和索引 pipeline 和模型同样重要。Q19为什么简历写这个项目A它覆盖完整软件链路数据 ETL、信息检索、LLM 应用、Web 服务、可观测性和降级策略。对实习岗位能体现工程能力不只是调包也有真实规模百万级 chunk和可演示的 UI。六、面试表达建议先业务后技术Wiki 知识问答 → RAG → 混合检索 → 生成别一上来堆名词。准备 1 个 Demo 故事例如问「阿里巴巴是谁创办的」讲检索 → 锚点 → 生成 → 参考文献。诚实边界实习生可说「Reranker / RRF 参考业界方案我负责集成、调参和工程落地」被追问 RRF 公式、CrossEncoder 原理要能答上。别背配置数字可以说「Top-K、context 长度可配置默认偏延迟优化」细节看 health trace。安全API Key 在.env不提交仓库——若被问到部署主动提这一点。七、30 秒 / 2 分钟 / 5 分钟三个版本30 秒Wiki-CN 百科 RAG 问答BM25向量混合检索、Rerank、百炼生成FastAPI 后端 聊天前端290 万 chunk含健康检查与流式输出。2 分钟使用本文 第一节 的开场介绍即可。5 分钟开场 技术栈 运行流程 12 个问题与解决Chroma 重建 检索质量优化。附录简历项目描述参考35 行Wiki-CN RAG 问答系统 | Python / FastAPI / ChromaDB - 基于 130 万条中文维基语料构建 BM25 BGE-M3 混合检索与 Rerank 精排链路索引规模约 290 万 chunk - 实现 FastAPI 后端与类 ChatGPT 流式聊天前端支持多会话、健康检查与 LLM 主备降级 - 针对大索引冷启动、Chroma 索引损坏、检索引用不准等问题设计异步加载、索引重建脚本与实体锚点增强检索附录关键 API 一览接口方法说明/GET聊天首页/api/askPOST同步问答/api/ask/streamPOST流式问答NDJSON/api/ask/clearPOST清空会话历史/api/healthGET健康检查支持?formatjson附录排查「答案不准」速查打开/api/health?formatjson看references是否相关检索问题 vs 生成问题查last_trace.rewrite_queries、anchor_terms、anchor_rescue_used查last_vec_used、last_rerank_used查last_trace.timing_ms判断性能瓶颈测试时用「新会话」避免历史上下文干扰

相关新闻