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

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

## 背景

企业用 AI 时最头疼的事是什么?数据不敢往外送。文档堆成山,想让 AI 看完给个答案,结果 API 调用成本高到肉疼,离线环境更是想都别想。

以前唯一的办法是把文档内容硬塞进 prompt,可几千页的资料怎么办?一条条复制粘贴非把人逼疯不可。

RAG(Retrieval-Augmented Generation,检索增强生成)换了个思路:先把文档切成小块,通过向量检索找出最相关的片段,再把这些片段喂给大模型。这样模型既保留了自己的推理能力,又能”看”到企业的私有数据。

这篇文章就手把手教你用开源工具 LangChain 和 Ollama,在自己电脑上跑一个完整的 RAG 问答系统。整个过程不依赖任何云服务,数据不出本地。

## 实际问题

企业场景下最常见的几个坑:

1. **数据隐私**:合同、财报、内部文档,这些敏感内容不可能发给第三方 API
2. **离线办公**:某些项目环境完全断网,商业 API 根本用不了
3. **成本问题**:大规模调用 GPT-4 API,费用相当可观
4. **领域知识**:通用模型不懂你公司的业务术语和内部流程

有人说我用开源大模型本地部署不就行了?问题是,模型再大也不可能把你公司十年积累的文档都装进去。RAG 的做法是让模型按需”查阅”相关文档,而不是把整个知识库硬塞进模型脑子。

## 搭建步骤

### 1. 安装依赖

“`bash
# 创建虚拟环境
python -m venv rag_env
source rag_env/bin/activate # Linux/Mac
# 或 rag_env\Scripts\activate # Windows

# 安装必要包
pip install langchain langchain-community langchain-ollama \
langchain-text-splitters \
langchain-huggingface \
pypdf \
chromadb \
sentence-transformers
“`

### 2. 下载 Ollama

Ollama 是在本地跑大模型的神器,支持一堆开源模型,安装也简单:

“`bash
# 安装 Ollama(macOS/Linux)
curl -fsSL https://ollama.com/install.sh | sh

# 拉取模型(推荐 qwen2.5 或 llama3)
ollama pull qwen2.5:7b

# 启动服务
ollama serve
“`

### 3. 准备知识库

建个文件夹扔你的文档进去,比如 `knowledge/faq.md`:

“`markdown
# 公司 FAQ

## 关于年假
公司员工每年享有 15 天带薪年假。工作满一年后即可享受。

## 关于报销
员工因公产生的差旅费用可以报销,需在费用发生后 30 天内提交申请。

## 关于技术栈
公司主要使用 Python、Go 和 TypeScript 进行后端开发。
“`

### 4. 完整代码

“`python
import os
from langchain_ollama import OllamaEmbeddings, ChatOllama
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import TextLoader, PyPDFLoader
from langchain_community.vectorstores import Chroma
from langchain import hub
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

# ============ 配置 ============
OLLAMA_MODEL = “qwen2.5:7b”
OLLAMA_BASE_URL = “http://localhost:11434”
CHROMA_PATH = “./chroma_db”
KNOWLEDGE_PATH = “./knowledge”

# ============ 步骤1: 加载文档 ============
def load_documents():
documents = []

# 加载 Markdown 文件
for file in os.listdir(KNOWLEDGE_PATH):
file_path = os.path.join(KNOWLEDGE_PATH, file)
if file.endswith(“.md”):
loader = TextLoader(file_path, encoding=”utf-8″)
documents.extend(loader.load())
elif file.endswith(“.pdf”):
loader = PyPDFLoader(file_path)
documents.extend(loader.load())

return documents

# ============ 步骤2: 文档分块 ============
def split_documents(documents):
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
length_function=len,
add_start_index=True,
)
return text_splitter.split_documents(documents)

# ============ 步骤3: 创建向量存储 ============
def create_vector_store(chunks):
# 使用本地 embedding 模型
embeddings = OllamaEmbeddings(
model=”nomic-embed-text”,
base_url=OLLAMA_BASE_URL
)

# 创建 Chroma 向量数据库
vector_store = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory=CHROMA_PATH
)

return vector_store

# ============ 步骤4: 构建问答链 ============
def create_qa_chain(vector_store):
# 检索器
retriever = vector_store.as_retriever(
search_type=”similarity”,
search_kwargs={“k”: 3}
)

# 提示模板
prompt = hub.pull(“rlm/rag-prompt”)

# 语言模型
llm = ChatOllama(
model=OLLAMA_MODEL,
base_url=OLLAMA_BASE_URL,
temperature=0.7
)

# 输出解析器
parser = StrOutputParser()

# 构建 RAG 链
rag_chain = (
{“context”: retriever | format_docs, “question”: RunnablePassthrough()}
| prompt
| llm
| parser
)

return rag_chain

def format_docs(docs):
return “\n\n”.join(doc.page_content for doc in docs)

# ============ 主程序 ============
if __name__ == “__main__”:
print(“正在加载文档…”)
docs = load_documents()
print(f”加载了 {len(docs)} 个文档”)

print(“\n正在分块…”)
chunks = split_documents(docs)
print(f”分块后共有 {len(chunks)} 个片段”)

print(“\n正在创建向量数据库…”)
vector_store = create_vector_store(chunks)
print(“向量数据库创建完成!”)

print(“\n正在构建问答系统…”)
qa_chain = create_qa_chain(vector_store)

print(“\n” + “=”*50)
print(“RAG 知识问答系统已准备就绪!”)
print(“=”*50)

# 测试问答
questions = [
“员工每年有多少天年假?”,
“差旅费用报销的时限是多久?”,
“公司使用什么技术栈?”
]

for q in questions:
print(f”\n问题: {q}”)
print(“-” * 30)
answer = qa_chain.invoke(q)
print(f”答案: {answer}”)
“`

### 5. 运行

“`bash
python rag_qa_system.py
“`

## 运行效果

跑起来之后会看到:

“`
正在加载文档…
加载了 1 个文档

正在分块…
分块后共有 8 个片段

正在创建向量数据库…
向量数据库创建完成!

正在构建问答系统…

==================================================
RAG 知识问答系统已准备就绪!
==================================================

问题: 员工每年有多少天年假?
——————————
答案: 根据公司规定,员工每年享有 15 天带薪年假。工作满一年后即可享受这项福利。

问题: 差旅费用报销的时限是多久?
——————————
答案: 员工因公产生的差旅费用可以在费用发生后 30 天内提交报销申请。

问题: 公司使用什么技术栈?
——————————
答案: 公司主要使用以下技术栈进行后端开发:Python、Go 和 TypeScript。
“`

测试结果在意料之中——RAG 成功把文档内容喂给了模型,所以答案都是基于我们的 FAQ 来的,不是模型在那胡编。

### 还能怎么改

实际落地时可以考虑:

1. **embedding 模型**:BAAI/bge-large-zh-v1.5 效果更好
2. **混合检索**:关键词 + 语义一起上
3. **重排序**:用 BGE-Reranker 把检索结果再筛一遍
4. **多格式支持**:PDF、Word、Excel 都安排上
5. **多轮对话**:加上聊天历史,AI 能记得住上下文

## 总结

这篇文章演示了怎么用 LangChain + Ollama 在本地搭一个 RAG 问答系统。核心好处就几点:

– **数据不出门**:文档和模型全在本地
– **省钱**:开源模型随便用,不按 token 收费
– **灵活**:想换模型换配置都很方便
– **安全**:内部敏感数据不会泄露

RAG 本质上是给大模型配了个”查阅资料”的能力,让它能用到那些没训练过的私有数据。随着开源工具越来越好用,本地 RAG 会成为企业 AI 的标配。

暂无评论

发送评论 编辑评论


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