使用 LangChain 搭建本地大模型 RAG 问答应用)
张高兴的 Hailo-10 开发指南二使用 LangChain 搭建本地大模型 RAG 问答应用大家好我是张高兴。上期我们成功在 Hailo-10 上部署了本地大模型今天我们来玩点更酷的——用 LangChain 搭建一个 RAG检索增强生成应用。想象一下你有一个私人知识库比如技术文档、论文、甚至小说然后你可以像跟 ChatGPT 聊天一样直接问它“这篇论文里关于 Transformer 的注意力机制怎么实现的”——它不仅能回答还能引用原文。这就是 RAG 的魅力。## 什么是 RAG为什么需要它RAGRetrieval-Augmented Generation是一种结合检索和生成的技术。核心思想是当用户提问时系统先从一个本地知识库比如向量数据库里检索出最相关的文档片段再把这些片段作为上下文喂给大模型让模型基于这些信息生成答案。传统大模型的问题模型训练数据有截止日期无法回答私有或实时更新的内容。比如你问它“Hailo-10 最新驱动版本号”模型可能不知道。RAG 的解决方案把知识库存在本地每次问答时动态检索既保证答案新鲜又保护隐私数据不出本地。Hailo-10 的 NPU神经网络处理单元做推理很快非常适合这种本地化场景。## 环境准备Hailo-10 LangChain 向量数据库我们先安装必要组件。Hailo-10 上我们已经部署了 Qwen 1.5 7B 模型量化版现在需要- Python 3.10± LangChain框架- Chroma轻量级向量数据库支持本地运行- sentence-transformers生成文本嵌入向量bash# 在 Hailo-10 的终端执行pip install langchain langchain-community chromadb sentence-transformers注意如果 Hailo-10 是 ARM 架构需要预编译的 wheels 文件建议用pip install --only-binary:all:跳过编译。## 第一步将本地文档转换为向量RAG 的第一步是“建库”——把文档拆成小块每块生成一个向量embedding存入向量数据库。这样后续检索时系统能快速找到语义相似的片段。假设我们有一个knowledge_base.txt文件里面是 Hailo-10 的技术手册片段Hailo-10 支持 Int8 量化推理峰值算力可达 26 TOPS。NPU 核心采用数据流架构无需外部 DRAM 缓存。驱动版本 4.18.0 修复了 PCIe 通信延迟问题。下面代码演示如何加载文档、分块、生成向量并存入 Chromapythonfrom langchain_community.document_loaders import TextLoaderfrom langchain.text_splitter import CharacterTextSplitterfrom langchain_community.embeddings import HuggingFaceEmbeddingsfrom langchain_community.vectorstores import Chroma# 1. 加载文档loader TextLoader(knowledge_base.txt, encodingutf-8)documents loader.load()# 2. 将文档切割成小块每个块 200 字符重叠 50 字符避免切断语义text_splitter CharacterTextSplitter( chunk_size200, chunk_overlap50, separator\n # 按换行符分割保留段落完整性)chunks text_splitter.split_documents(documents)print(f文档被拆分为 {len(chunks)} 个块)# 3. 使用轻量级句子嵌入模型Hailo-10 上跑很快# 模型会自动下载到 ~/.cache/huggingface/hubembedding_model HuggingFaceEmbeddings( model_namesentence-transformers/all-MiniLM-L6-v2, model_kwargs{device: cpu} # Hailo-10 的 NPU 暂不支持此模型用 CPU 即可)# 4. 存入 Chroma 向量数据库自动持久化到本地磁盘vector_store Chroma.from_documents( documentschunks, embeddingembedding_model, persist_directory./chroma_db # 数据库存储路径)vector_store.persist() # 确保写入磁盘print(知识库构建完成)运行后./chroma_db目录下会出现向量数据文件。下次启动时可以直接用Chroma.load()加载无需重复处理。## 第二步搭建 RAG 问答链路有了知识库接下来就是核心的“检索生成”流程用户提问 → 检索相关文档片段 → 拼接提示词 → 调用大模型 → 输出答案。这里的关键是 LangChain 的RetrievalQA链它自动封装了上述流程。我们只需配置- 检索器从 Chroma 中找最相似的 3 个片段- 大模型Hailo-10 上运行的本地模型- 提示词模板告诉模型如何引用上下文pythonfrom langchain.chains import RetrievalQAfrom langchain.prompts import PromptTemplatefrom langchain_community.llms import Ollama # 假设 Hailo-10 上通过 Ollama 运行模型# 1. 初始化大模型以 Ollama 的 Qwen 为例# 确保先启动 Ollama 服务ollama servellm Ollama( modelqwen:7b-chat-v1.5-q4_K_M, # 量化版适配 Hailo-10 内存 base_urlhttp://localhost:11434, # Ollama 默认端口 temperature0.7, # 控制回答随机性 num_predict512 # 最大输出 token 数)# 2. 创建检索器返回最相关的 3 个文档块retriever vector_store.as_retriever( search_typesimilarity, # 基于余弦相似度检索 search_kwargs{k: 3} # 返回 top-3)# 3. 自定义提示词模板强调基于上下文回答prompt_template 你是一个基于本地知识库的问答助手。请根据以下上下文内容回答问题。如果上下文没有相关信息请直接说“不知道”不要编造。上下文{context}问题{question}回答prompt PromptTemplate( templateprompt_template, input_variables[context, question])# 4. 构建检索增强生成链qa_chain RetrievalQA.from_chain_type( llmllm, chain_typestuff, # 将所有检索结果合并为一个上下文 retrieverretriever, chain_type_kwargs{prompt: prompt}, return_source_documentsTrue # 返回来源文档方便验证)# 5. 测试问答question Hailo-10 的驱动版本 4.18.0 有什么改进result qa_chain.invoke({query: question})# 输出答案print(答案, result[result])print(\n参考来源)for doc in result[source_documents]: print(f - {doc.page_content[:80]}...) # 截取前 80 字符运行效果示例假设知识库中有相关文档答案根据上下文Hailo-10 的驱动版本 4.18.0 修复了 PCIe 通信延迟问题。参考来源 - 驱动版本 4.18.0 修复了 PCIe 通信延迟问题...如果问题不在知识库中比如问“如何烹饪披萨”模型会回答“不知道”避免幻觉。## 进阶优化让 RAG 更智能### 1. 分块策略优化上面的CharacterTextSplitter很基础。对于技术文档推荐用RecursiveCharacterTextSplitter它会根据换行符、句号、空格等逐级递归切分保留更多语义pythonfrom langchain.text_splitter import RecursiveCharacterTextSplittertext_splitter RecursiveCharacterTextSplitter( chunk_size300, chunk_overlap50, separators[\n\n, \n, 。, , , , , ])### 2. 混合检索如果文档包含很多代码或表格纯向量检索可能不够精准。可以结合 BM25关键词检索做混合搜索python# 安装pip install rank_bm25from langchain.retrievers import EnsembleRetrieverfrom langchain.retrievers.bm25 import BM25Retriever# 创建 BM25 检索器基于关键词bm25_retriever BM25Retriever.from_documents(chunks)bm25_retriever.k 2# 混合检索向量 0.7 权重关键词 0.3 权重ensemble_retriever EnsembleRetriever( retrievers[retriever, bm25_retriever], weights[0.7, 0.3])### 3. 对话历史如果想支持多轮对话可以用ConversationalRetrievalChain它会自动维护聊天历史避免重复检索。## 性能调优让 Hailo-10 跑得更快Hailo-10 的 NPU 擅长固定形状的推理但 LangChain 的向量检索和文本生成涉及动态形状计算。实测建议-嵌入模型用all-MiniLM-L6-v2约 80MB在 CPU 上处理 1000 个文档块仅需 1.2 秒够用。-大模型量化版 Qwen 7B 在 NPU 上推理速度约 15 token/s加上检索时间一次问答总耗时约 3-5 秒。如果嫌慢可以换成 3B 级别的模型如 Phi-3-mini。-向量数据库Chroma 默认使用 SQLite 存储数据量大时建议升级到 FAISSFacebook 的相似度搜索库速度提升 5 倍。bash# 安装 FAISSCPU 版pip install faiss-cpu# 将 Chroma 替换为 FAISS 只需改一行代码vector_store FAISS.from_documents(chunks, embedding_model)## 总结今天我们用 LangChain 在 Hailo-10 上搭建了一个完整的 RAG 问答应用。核心三步走文档切块 → 向量化存储 → 检索增强生成。关键收获1. RAG 让本地大模型“活”了起来能回答私有知识库的问题且数据不出设备。2. LangChain 的RetrievalQA链封装了检索和生成的流程代码不到 30 行。3. 针对 Hailo-10 的硬件特性我们选择了量化模型和轻量嵌入平衡了性能和准确性。下一步你可以尝试- 将知识库替换为 PDF 或网页用UnstructuredPDFLoader或WebBaseLoader- 添加前端界面比如下期我会讲用 Gradio 做一个聊天窗口- 用 Hailo-10 的 NPU 加速嵌入生成需要自定义算子比较硬核如果你在搭建过程中遇到问题欢迎在评论区留言。下期见张高兴继续带你玩转 Hailo-10