使用 LangChain + Ollama 构建本地 RAG 知识库问答系统

# 使用 LangChain + Ollama 构建本地 RAG 知识库问答系统

## 背景介绍

企业日常运营中会积累大量内部文档:技术手册、会议记录、产品说明、操作指南等等。这些文档散落在各个文件夹和系统里,查找起来非常麻烦。传统的关键词搜索只能匹配字面内容,比如搜”服务器”就找不到”主机”相关的内容,导致经常漏掉真正相关的信息。

大语言模型出现后,情况有了转机。RAG(检索增强生成)技术可以将私有知识库与大模型结合,让 AI 能够理解语义并回答关于私有数据的问题。但直接把文档上传到 OpenAI 等云服务存在数据泄露风险——对于处理敏感信息的企业来说,这是无法接受的。

本文介绍一个完全本地化的方案:使用开源的 LangChain 框架搭配本地运行的 Ollama 大模型,构建一个 RAG 知识库问答系统。所有数据处理都在本地完成,不需要任何云服务。

## 问题描述

搭建本地 RAG 系统需要解决这几个问题:

**模型怎么跑起来?** 大模型体积大、吃配置,一般的云端 API 用不了。Ollama 解决了这个问题,在本地就能跑多种开源大模型,一行命令部署。

**文档怎么处理?** PDF、Word、Markdown 这些格式都不一样,需要统一转成可检索的文本。LangChain 提供了各种文档加载器,能自动处理常见格式。

**怎么实现语义检索?** 简单匹配”关键词”已经不够了,需要把文本转成向量,用相似度来检索。Chroma 是轻量级的向量数据库,配合 Ollama 的嵌入模型就能用。

**怎么把检索到的内容喂给大模型生成答案?** 需要设计一套提示词模板,让模型知道哪些是参考内容、怎么组织回答。

## 详细步骤

### 1. 环境准备

先装依赖包。Python 版本建议 3.10 或以上:

“`bash
pip install langchain langchain-community langchain-ollama ollama chromadb pypdf python-docx sentence-transformers
“`

### 2. 下载并启动 Ollama

Ollama 支持 macOS、Linux 和 Windows。以 Ubuntu 为例:

“`bash
curl -fsSL https://ollama.com/install.sh | sh
“`

启动服务后,下载一个适合本地运行的模型。7B 参数的模型对硬件要求相对低一些,比如 llama3:8b 或 qwen:7b 都可以:

“`bash
ollama serve
ollama pull llama3:8b
“`

### 3. 准备知识库文档

写一个脚本 ingest.py,用来处理文档并构建向量数据库。代码如下:

“`python
#!/usr/bin/env python3
import os
from langchain_community.document_loaders import PyPDFLoader, TextLoader, MarkdownLoader, Docx2txtLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_ollama import OllamaEmbeddings
from langchain_chroma import Chroma

SUPPORTED_EXTENSIONS = {‘.pdf’: PyPDFLoader, ‘.txt’: TextLoader, ‘.md’: MarkdownLoader, ‘.docx’: Docx2txtLoader}

def load_documents(docs_folder):
documents = []
for root, _, files in os.walk(docs_folder):
for file in files:
file_path = os.path.join(root, file)
ext = os.path.splitext(file)[0].lower()
if ext in SUPPORTED_EXTENSIONS:
print(f”正在加载: {file_path}”)
try:
loader = SUPPORTED_EXTENSIONS[ext](file_path)
docs = loader.load()
documents.extend(docs)
except Exception as e:
print(f”加载失败 {file_path}: {e}”)
return documents

def split_documents(documents, chunk_size=500, chunk_overlap=50):
text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap, separators=[”

“, ”
“, “。”, “.”, ” “, “”])
return text_splitter.split_documents(documents)

def create_vector_store(doc_splits, persist_directory=”./chroma_db”):
embeddings = OllamaEmbeddings(model=”nomic-embed-text”, base_url=”http://localhost:11434″)
vectorstore = Chroma.from_documents(documents=doc_splits, embedding=embeddings, persist_directory=persist_directory)
return vectorstore

def main():
docs_folder = “./knowledge_base”
persist_directory = “./chroma_db”
print(“步骤 1: 加载文档”)
documents = load_documents(docs_folder)
print(f”共加载 {len(documents)} 个文档”)
print(“步骤 2: 分割文档”)
doc_splits = split_documents(documents)
print(f”分割为 {len(doc_splits)} 个文本块”)
print(“步骤 3: 构建向量数据库”)
vectorstore = create_vector_store(doc_splits, persist_directory)
print(f”向量数据库已保存到: {persist_directory}”)

if __name__ == “__main__”:
main()
“`

### 4. 构建问答系统

创建主脚本 rag_app.py:

“`python
#!/usr/bin/env python3
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_chroma import Chroma
from langchain_ollama import OllamaEmbeddings

LLAMA_MODEL = “llama3:8b”
EMBEDDING_MODEL = “nomic-embed-text”
PERSIST_DIRECTORY = “./chroma_db”

def setup_qa_chain():
llm = ChatOllama(model=LLAMA_MODEL, base_url=”http://localhost:11434″, temperature=0.7)
embeddings = OllamaEmbeddings(model=EMBEDDING_MODEL, base_url=”http://localhost:11434″)
vectorstore = Chroma(persist_directory=PERSIST_DIRECTORY, embedding_function=embeddings)
retriever = vectorstore.as_retriever(search_type=”similarity”, search_kwargs={“k”: 5})
system_prompt = “你是一个专业的技术文档问答助手。请根据以下参考文档回答用户的问题。如果文档中没有相关信息,请明确告知用户。请用中文回答问题。参考文档: ” + “{context}”
prompt = ChatPromptTemplate.from_messages([(“system”, system_prompt), (“human”, “{input}”)])
question_answer_chain = create_stuff_documents_chain(llm, prompt)
rag_chain = create_retrieval_chain(retriever, question_answer_chain)
return rag_chain

def chat_loop():
print(“本地 RAG 知识库问答系统”)
print(“输入问题进行咨询,输入 quit 或 exit 退出”)
rag_chain = setup_qa_chain()
while True:
try:
user_input = input(“你: “).strip()
if user_input.lower() in [‘quit’, ‘exit’, ‘q’]:
print(“再见!”)
break
if not user_input:
continue
response = rag_chain.invoke({“input”: user_input})
print(“回答:”, response[“answer”])
if “context” in response:
print(“参考来源:”)
for i, doc in enumerate(response[“context”], 1):
source = doc.metadata.get(“source”, “未知来源”)
print(f” {i}. {source}”)
except KeyboardInterrupt:
print(“退出问答”)
break
except Exception as e:
print(f”错误: {e}”)

if __name__ == “__main__”:
chat_loop()
“`

## 运行结果

### 文档摄入

先在 knowledge_base 文件夹里放要处理的文档,支持 PDF、Word、Markdown、纯文本等格式。然后运行:

“`bash
python ingest.py
“`

输出示例:

“`
步骤 1: 加载文档
正在加载: ./knowledge_base/技术文档.pdf
正在加载: ./knowledge_base/产品手册.md
共加载 15 个文档

步骤 2: 分割文档
分割为 287 个文本块

步骤 3: 构建向量数据库
向量数据库已保存到: ./chroma_db
“`

### 问答交互

启动问答系统:

“`bash
python rag_app.py
“`

交互示例:

“`
本地 RAG 知识库问答系统

你: 如何重启服务器?

回答:
根据参考文档,重启服务器的步骤如下:
1. 使用 SSH 连接到服务器:ssh admin@server-ip
2. 使用重启命令:sudo reboot
或者使用 systemctl 命令:sudo systemctl restart <服务名称>
3. 等待服务器重新启动后,验证服务状态:sudo systemctl status <服务名称>

参考来源:
1. ./knowledge_base/运维手册.md
2. ./knowledge_base/服务器维护指南.txt
“`

## 总结

本文演示了用 LangChain 和 Ollama 搭建本地 RAG 知识库的全过程。核心优点有这几个:

数据安全——所有处理都在本地,不用把内部文档发到第三方服务器。

没有 API 费用——用开源模型,不按调用次数付钱。

灵活度高——可以换不同的开源模型,调整文档处理逻辑,改提示词模板。

部署门槛低——Ollama 安装简单,LangChain 把复杂的 RAG 流程封装成了简单的 API。

这个方案适合企业内部知识管理、技术文档查询、客服知识库等场景。实际部署时根据文档量选择合适的向量数据库配置,根据并发需求调整模型参数就好。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇