从零构建本地知识库问答系统:LangChain + DeepSeek + Chroma 实战

张开发
2026/4/9 8:54:14 15 分钟阅读

分享文章

从零构建本地知识库问答系统:LangChain + DeepSeek + Chroma 实战
从零构建本地知识库问答系统LangChain DeepSeek Chroma 实战你是否想过把一份 PDF、一个网页、甚至一整个文档目录丢进去然后直接用自然语言提问让 AI 帮你检索并回答本文带你用不到 200 行 Python 代码实现这件事。背景为什么需要 RAG大语言模型LLM天生有两个缺陷知识截止训练数据有截止日期无法了解最新信息。幻觉模型可能一本正经地编造并不存在的答案。RAGRetrieval-Augmented Generation检索增强生成是目前业界最主流的解决方案。它的思路简洁而优雅用户问题 → 向量检索相关文档片段 → 把片段塞进 Prompt → LLM 基于真实资料回答这样模型的回答有了参考资料的支撑幻觉大幅减少还能实时更新知识库。项目介绍本项目是一个基于LangChain DeepSeek Chroma的完整 RAG 问答系统具备以下特性特性说明多格式文档支持.txt/.pdf/.md及整个目录批量加载网页内容加载直接传入 URL自动抓取并解析中文 Embedding使用BAAI/bge-small-zh-v1.5专为中文优化持久化向量库Chroma 存盘避免每次重复计算多轮对话交互模式下支持上下文连贯的连续问答流式输出回答实时逐字打印体验更流畅自主检索决策基于 AgentExecutor 的工具调用架构模型自主判断是否需要检索自动执行检索并整合结果项目地址https://github.com/wangxinpo777/langchain-playgroundhttps://gitee.com/wangxinpo/langchain-playground技术栈LangChain— 构建 LLM 应用的框架提供文档加载、文本切分、链式调用等能力DeepSeek— 国产高性价比大语言模型API 兼容 OpenAI 格式ChromaDB— 轻量级本地向量数据库支持持久化sentence-transformers— 加载 HuggingFace Embedding 模型架构设计项目被拆分为八个职责清晰的模块main.py ← 入口解析参数组合流程 config.py ← 全局配置模型、参数、API Key loader.py ← 文档加载文件 / 目录 / URL vector_store.py ← 向量库构建与持久化 rag_chain.py ← Agent 构建AgentExecutor Tool Calling tools.py ← 检索工具供模型按需调用 chat_history.py ← 多轮对话历史管理 callback_handler.py ← 调试回调打印中间过程核心数据流如下[文档] → 切分 → Embedding → ChromaDB ↓ [用户问题] → LLM 判断是否检索 → (按需) 向量检索 → 相关片段 → DeepSeek → 回答核心代码解析1. 文档加载与切分LangChain 提供了统一的文档加载接口无论是本地文件还是网页都能一行代码搞定。# 支持 txt / pdf / md 文件loaderTextLoader(file_path,encodingutf-8)# 支持网页 URLloaderWebBaseLoader(url)# 切分成小块中文场景建议 200-500splitterRecursiveCharacterTextSplitter(chunk_size200,chunk_overlap40)docssplitter.split_documents(raw_docs)为什么要切分向量检索需要把文本转为固定维度的向量太长的文本会丢失细节切成合适大小的块检索精度更高。2. 向量库构建与复用fromlangchain_community.vectorstoresimportChromafromlangchain_community.embeddingsimportHuggingFaceEmbeddings embeddingHuggingFaceEmbeddings(model_nameBAAI/bge-small-zh-v1.5)# 首次构建持久化到磁盘storeChroma.from_documents(docs,embedding,persist_directory./chroma_db)# 后续直接加载无需重新计算storeChroma(persist_directory./chroma_db,embedding_functionembedding)持久化的好处是显而易见的Embedding 计算有一定耗时把结果存到磁盘下次启动直接复用节省大量等待时间。3. 自主检索决策AgentExecutor 架构传统 RAG 每次都强制检索不管问题是否需要。新架构使用AgentExecutor实现工具调用循环fromlangchain.agentsimportcreate_tool_calling_agent,AgentExecutor# 1. 定义检索工具tooldefsearch_knowledge_base(query:str)-str:在本地知识库中搜索相关信息。docsretriever.invoke(query)ifnotdocs:return知识库中未找到相关信息return\n\n---\n\n.join(doc.page_contentfordocindocs)# 2. 创建 Agent需要 agent_scratchpad 占位符promptChatPromptTemplate.from_messages([(system,你是一个智能助手...),(human,{input}),MessagesPlaceholder(variable_nameagent_scratchpad),# Agent 工作区])agentcreate_tool_calling_agent(llm,[search_knowledge_base],prompt)# 3. 用 AgentExecutor 驱动工具调用循环agent_executorAgentExecutor(agentagent,tools[search_knowledge_base])工作流程用户提问 → Agent 判断是否需要调用工具如需检索 → 执行search_knowledge_base→ 获取结果将检索结果喂回 LLM → 生成最终回答如不需要检索 → 直接基于自身知识回答系统提示词告诉模型使用策略(system,你是一个智能助手可以回答各种问题。 使用策略 - 对于常识性问题、通用知识你可以直接回答 - 对于涉及特定文档、专业领域、具体数据的问题使用检索工具 - 如果检索无结果可以基于自己的知识给出合理回答)这样问你好会直接回答问文档里说了什么才会触发检索。4. 多轮对话支持交互模式下链会携带历史消息让模型理解上下文promptChatPromptTemplate.from_messages([(system,你是一个智能助手...),MessagesPlaceholder(variable_namechat_history),# 注入历史消息(human,{question}),])快速上手环境准备# 克隆项目gitclone https://github.com/wangxinpo777/langchain-playgroundcdlangchain-playground# 安装依赖pipinstall-rrequirements.txt配置 API Keycp.env.example .env编辑.env文件填入你的 DeepSeek API Key在 platform.deepseek.com 免费注册获取LLM_API_KEYyour_api_key_here运行示例# 最简单的方式使用内置示例文本直接提问python main.py# 加载你自己的文档python main.py--fileyour_doc.pdf# 批量加载目录下所有文档python main.py--file./docs# 从网页抓取内容python main.py--urlhttps://docs.langchain.com/docs/# 进入交互式多轮对话模式python main.py--interactive# 强制重建向量库修改文档后使用python main.py--rebuild实际效果演示以下是交互模式的一段对话示例知识库为 LangChain 文档❓ 你的问题: LangChain 是什么 LangChain 是一个用于构建大语言模型应用的开源框架。它提供了一系列工具和 抽象层方便开发者将 LLM 与外部数据源、工具和记忆模块结合起来... ❓ 你的问题: 它支持哪些向量数据库 根据文档LangChain 支持多种向量数据库包括 Chroma、FAISS、Pinecone 等。 其中 Chroma 是本地部署的轻量级选择Pinecone 则适合云端生产环境... ❓ 你的问题: 上面提到的 FAISS 是什么原理 FAISS 是 Facebook AI Research 开源的高效相似度搜索库它通过...基于上 文理解「上面提到的」指代 FAISS可以看到第三个问题中模型正确理解了代词指代这就是多轮对话历史的作用。常见问题Q: 首次运行很慢A: 首次运行会从 HuggingFace 下载 Embedding 模型约 100MB完成后会缓存到本地后续运行秒启动。网络不好的话可以提前手动下载模型文件。Q: 如何更换成其他 LLMA: 修改config.py中的BASE_URL、MODEL_NAME和API_KEY。由于使用了 OpenAI 兼容接口理论上支持任何兼容该格式的模型服务如 Qwen、GLM、本地 Ollama 等。Q: PDF 中文乱码A: 确保安装了pypdf4.0.0部分扫描版 PDF 需要额外的 OCR 工具处理。Q: 如何评估检索质量A: 调整config.py中的RETRIEVER_TOP_K默认 3和CHUNK_SIZE默认 200。一般来说chunk 越小检索越精准但可能丢失上下文top_k越大召回越全但 Prompt 也越长。可扩展方向这个项目是一个扎实的 RAG 基础实现在此基础上你可以继续探索HyDE假设文档嵌入先让 LLM 生成一个假设答案再用这个答案去检索提升召回率重排序Rerank检索后用交叉编码器对结果重新排序提升精度Web UI接入 Streamlit 或 Gradio做成可视化界面多知识库路由根据问题自动选择不同的知识库总结这个项目用不到 300 行代码8 个模块实现了一个生产可用的 RAG 系统骨架模块化设计每个文件职责单一便于扩展中文友好Embedding 模型专为中文优化开箱即用5 分钟完成配置和首次运行成本极低DeepSeek API 价格仅为 OpenAI 的约 1/30如果你在学习 LangChain 或想把 RAG 落地到自己的项目中这个项目是一个很好的起点。欢迎 Star、Fork也欢迎提 Issue 和 PR本文代码已在 Python 3.11 环境测试通过。如有问题欢迎在评论区交流。

更多文章