文章目录【54.PythonAI】企业知识库问答系统100份PDF私有文档 RAG 引用溯源的完整方案导入语1 ~ 系统架构2 ~ 核心代码3 ~ 生产级增强要点思考 总结结尾【54.PythonAI】企业知识库问答系统100份PDF私有文档 RAG 引用溯源的完整方案文章简介本文是一个生产级RAG系统的完整实战方案——基于FastAPI LangChain Chroma构建企业私有知识库问答平台。内容涵盖100份PDF的批量摄入管线、增量更新的向量索引策略、可溯源问答每个回答附原文出处和置信度评分、以及FastAPI服务化部署。配以Mermaid架构图展示系统全貌代码可直用。适合想将RAG从Demo升级为内部系统的开发者。 个人主页源码骑士❄专栏传送门《Android开发基础》《python基础课程》⭐️热衷从源码视角拆解技术底层原理将复杂架构讲得通俗易懂 源码骑士的简介5年Android Framework系统开发经验曾主导多项系统级性能优化专项技术栈覆盖Android系统全链路Binder/Handler/AMS/WMS/启动流程及Java后端全家桶Spring MyBatis Redis Oracle累计产出原创技术文章100篇文章以流程图为特色被读者评价为看一篇胜过啃一周源码导入语前面六篇文章你学会了RAG的每一个组件。现在是把它们组装成产品的时候了——一个真正能给同事用的企业知识库问答系统。这篇文章的DAU可能只有你部门的十几个人但它和Demo的区别在于批量处理100份PDF不掉链子、每次回答带上原文出处、答案拿不准时告诉用户我只有60%的把握、新文档加进来不用重建全部索引。这些就是工程化——把能跑的东西变成敢用的东西。1 ~ 系统架构管理员上传PDFFastAPI /upload接口PDF解析引擎(Unstructured)文本分块向量化Chroma向量库(增量更新)用户提问FastAPI /ask接口检索模块(混合检索Reranker)LLM生成回答置信度评分返回{answer, sources, confidence}2 ~ 核心代码# enterprise_kb.py —— 企业知识库核心importos,uuidfromfastapiimportFastAPI,UploadFile,FilefrompydanticimportBaseModelfromlangchain_openaiimportChatOpenAI,OpenAIEmbeddingsfromlangchain_chromaimportChromafromlangchain_text_splittersimportRecursiveCharacterTextSplitterfromunstructured.partition.autoimportpartition appFastAPI()embeddingsOpenAIEmbeddings()vector_storeChroma(embedding_functionembeddings,persist_directory./kb_db)llmChatOpenAI(modelgpt-3.5-turbo,temperature0.2)# 文档上传接口 app.post(/upload)asyncdefupload_document(file:UploadFileFile(...)):上传单份PDF并入库增量更新不重建索引contentawaitfile.read()tmp_pathf/tmp/{uuid.uuid4()}.pdfwithopen(tmp_path,wb)asf:f.write(content)elementspartition(filenametmp_path)text\n.join(str(e)foreinelements)splitterRecursiveCharacterTextSplitter(chunk_size500,chunk_overlap100)chunkssplitter.create_documents([text],metadatas[{source:file.filename,id:str(uuid.uuid4())[:8]}])vector_store.add_documents(chunks)return{status:ok,chunks_added:len(chunks),filename:file.filename}# 问答接口带引用溯源 app.get(/ask)asyncdefask_question(q:str):retrievervector_store.as_retriever(search_kwargs{k:6})docsretriever.invoke(q)# 构建带引用编号的上下文context_parts[]fori,docinenumerate(docs,1):sourcedoc.metadata.get(source,未知文档)context_parts.append(f[文档{i}] 来源:{source}\n{doc.page_content})context\n\n.join(context_parts)responsellm.invoke(f基于以下文档回答问题。引用时标注[文档X]。\n\n{context}\n\n问题{q})# 置信度评分基于检索相似度importnumpyasnp similarities[float(np.dot(embeddings.embed_query(q),embeddings.embed_query(d.page_content)))fordindocs]confidenceround(float(np.mean(similarities[:3])),3)return{answer:response.content,confidence:confidence,sources:[{filename:d.metadata.get(source),excerpt:d.page_content[:100]}fordindocs[:3]]}# 启动uvicorn enterprise_kb:app --reload3 ~ 生产级增强要点增量索引策略 ├─ 新文档上传→add_documents不重建全库 ├─ 定期检查文档变更→更新特定chunks └─ 避免每次上传都全量重建100份PDF重建一次要十几分钟 置信度门槛 ├─ confidence0.8→ 直接返回回答 ├─0.5~0.8 → 返回 以上回答基于部分匹配的文档建议人工核实└─0.5→未找到足够相关的文档请尝试更换提问方式日志与监控 ├─ 记录每次问答的query、retrieved_docs、answer └─ 定期分析哪些问题召回率低 → 优化索引策略思考 总结增量索引是生产级的底线不支持增量更新的RAG系统每次加新文档都重建索引——100份PDF要十几分钟不可接受。引用溯源让AI回答变得可信每个答案附上来自哪份文档的第几个片段用户可以自己验证。置信度评分不是精确数学——但有就比没有好基于检索相似度的粗估至少能挡住完全没有依据的回答。FastAPI是RAG服务化的最优选原生async支持、自动Swagger文档、和LangChain无缝配合。一个RAG系统从能跑到能用的距离就是这些工程化细节堆起来的。结尾各位小伙伴本文完源码骑士 — Android Framework 全栈开发关注| ❤️点赞| ⭐收藏| 评论| 一键四连️寄语Demo是给自己看的系统是给别人用的——把引用溯源和置信度加上你的RAG才真正算产品。