基于 LangChain、本地 Llama3.1 与 Chroma 构建 RAG 增强生成系统
本文详细阐述了如何利用 LangChain 框架结合本地部署的 Llama3.1 大模型与 Chroma 向量数据库,构建私有化 RAG(检索增强生成)系统。内容涵盖核心概念解析、环境搭建、数据向量化处理、知识库查询实现及常见问题排查。通过本地化部署方案,有效解决了数据安全与隐私保护问题,避免了公有云 API 的成本与延迟,适合企业级知识问答场景的落地实践。

本文详细阐述了如何利用 LangChain 框架结合本地部署的 Llama3.1 大模型与 Chroma 向量数据库,构建私有化 RAG(检索增强生成)系统。内容涵盖核心概念解析、环境搭建、数据向量化处理、知识库查询实现及常见问题排查。通过本地化部署方案,有效解决了数据安全与隐私保护问题,避免了公有云 API 的成本与延迟,适合企业级知识问答场景的落地实践。

在实际开发检索增强生成(RAG, Retrieval Augmented Generation)系统时,数据安全与隐私保护往往是首要考虑的因素。对于企业级应用或涉及敏感信息的场景,使用公有云 API 存在数据泄露风险且成本较高。此时,采用本地部署的大模型配合本地矢量数据库成为必要的选择。
本文将以 Python 为开发语言,利用 LangChain 框架、本地运行的 Llama3.1 大模型以及 Chroma 向量数据库,详细讲解如何搭建一套完整的私有化 RAG 知识问答系统。我们将深入探讨核心概念、环境配置、代码实现及优化策略。
计算机无法直接理解自然语言文本,必须将其转换为数值向量才能进行计算处理。这个过程称为嵌入(Embedding)。在 RAG 系统中,我们通常使用专门的 Embedding 模型将文本片段转化为高维向量。这些向量能够捕捉文本的语义信息,使得语义相似的文本在向量空间中距离更近。
经过 Embedding 处理后的文本被称为'矢量'。矢量数据库专门用于存储和检索这些高维向量。常见的矢量数据库包括 Chroma、Milvus、Faiss 等。Chroma 因其轻量级、易于集成和无需额外服务启动的特性,非常适合本地开发和原型验证。
在查询阶段,系统将用户的问题也转化为相同的向量表示,然后在数据库中搜索最相似的历史文档片段,将这些片段作为上下文提供给大模型,从而生成基于事实的回答。
大型语言模型(LLM)虽然强大,但存在知识截止、幻觉等问题。RAG 技术通过引入外部知识库来弥补这些不足。其工作流程如下:
确保已安装 Python 3.8 及以上版本。建议创建虚拟环境以隔离依赖。
python -m venv rag_env
source rag_env/bin/activate # Windows: rag_env\Scripts\activate
Ollama 是一个运行本地大模型的便捷工具。访问官网下载对应系统的安装包,安装后执行以下命令拉取 Llama3.1 模型:
ollama pull llama3.1
验证安装是否成功:
ollama run llama3.1
在终端中执行以下命令安装必要的 LangChain 组件:
pip install --upgrade langchain langchain-community langchain-chroma langchain-ollama
首先,我们需要准备待处理的文本文件。假设有一个名为 state_of_the_union.txt 的文件位于 doc 目录下。LangChain 提供了 TextLoader 来读取文本。
为了便于向量化处理,长文本需要被切分成较小的块(Chunk)。RecursiveCharacterTextSplitter 是常用的分割器,它会根据字符长度和特定分隔符(如段落、句子)进行递归分割。
from langchain.document_loaders import TextLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 加载文本文件,指定 utf-8 编码
loader = TextLoader('doc/state_of_the_union.txt', encoding='utf-8')
documents = loader.load()
# 定义文本分割器
# chunk_size: 每个块的最大字符数
# chunk_overlap: 块之间的重叠字符数,有助于保持上下文连贯性
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)
在存储嵌入之前,必须确保嵌入模型与后续查询时使用的模型一致。这里我们使用 Ollama 提供的嵌入功能。
from langchain.vectorstores import Chroma
from langchain.embeddings import OllamaEmbeddings
persist_directory = 'chroma_langchain_db_test'
model_name = "llama3.1"
def get_embedding():
return OllamaEmbeddings(model=model_name)
# 创建向量数据库实例并持久化
vectordb = Chroma.from_documents(
documents=texts,
embedding=get_embedding(),
persist_directory=persist_directory
)
# 将数据写入磁盘,以便后续重启程序时加载
vectordb.persist()
执行此过程后,项目根目录下会生成 chroma_langchain_db_test 文件夹,其中包含向量索引数据。
查询阶段需要重新加载向量数据库实例,并初始化大模型。LangChain 的 VectorDBQA 链封装了检索和生成的逻辑。
from langchain_ollama.llms import OllamaLLM
from langchain.chains import VectorDBQA
# 初始化大模型
model = OllamaLLM(model=model_name)
# 加载已持久化的向量数据库
vectordb = Chroma(
persist_directory=persist_directory,
embedding_function=get_embedding()
)
# 创建 QA 链
# chain_type="stuff" 表示将所有检索到的上下文一次性放入提示词
qa = VectorDBQA.from_chain_type(
llm=model,
chain_type="stuff",
vectorstore=vectordb
)
# 执行查询
query = "What did the president say about Ketanji Brown Jackson?"
result = qa.run(query)
print(result)
以下是整合后的完整脚本,可直接运行测试:
import os
from langchain.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OllamaEmbeddings
from langchain_ollama.llms import OllamaLLM
from langchain.chains import VectorDBQA
from langchain.document_loaders import TextLoader
# 配置参数
persist_directory = 'chroma_langchain_db_test'
model_name = "llama3.1"
def get_embedding():
return OllamaEmbeddings(model=model_name)
def create_db():
if not os.path.exists('doc'):
print("请确保 doc 目录下存在 txt 文件")
return
loader = TextLoader('doc/state_of_the_union.txt', encoding='utf-8')
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)
vectordb = Chroma.from_documents(
documents=texts,
embedding=get_embedding(),
persist_directory=persist_directory
)
vectordb.persist()
print("数据库创建完成")
def ask(query):
model = OllamaLLM(model=model_name)
vectordb = Chroma(
persist_directory=persist_directory,
embedding_function=get_embedding()
)
qa = VectorDBQA.from_chain_type(
llm=model,
chain_type="stuff",
vectorstore=vectordb
)
result = qa.run(query)
return result
if __name__ == "__main__":
# 首次运行需创建数据库
create_db()
# 执行查询
query = "What did the president say about Ketanji Brown Jackson?"
r = ask(query)
print(f"Query: {query}")
print(f"Answer: {r}")
如果在创建数据库和查询时使用了不同的 Embedding 模型,向量空间将不一致,导致检索结果无效。务必保证 get_embedding() 函数中的模型名称一致。
如果检索到的文档片段总长度超过了 LLM 的最大上下文窗口,会导致报错或截断。可以通过调整 chunk_size 减小分块大小,或者使用 map_reduce 类型的 Chain 来处理长上下文。
默认的相似度搜索可能不够精准。可以考虑引入重排序(Re-ranking)机制,先粗排再精排。此外,调整 k 参数(检索返回的文档数量)也能影响结果质量。
本地部署虽然安全,但推理速度受限于硬件。建议使用 GPU 加速 Ollama 运行。对于大规模数据,Chroma 支持多种后端存储,可迁移至 PostgreSQL 以提升并发能力。
通过本文的介绍,我们掌握了使用 LangChain、Llama3.1 和 Chroma 构建本地 RAG 系统的全流程。这种架构不仅保障了数据隐私,还降低了 API 调用成本。开发者可以根据实际需求进一步扩展功能,例如增加多模态支持、引入 Agent 智能体或对接更多数据源。随着本地大模型生态的成熟,私有化 RAG 将成为企业智能化转型的重要基础设施。
希望本教程能为您的 AI 项目开发提供有价值的参考。如有技术问题,欢迎查阅官方文档或社区讨论。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online