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

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

## 背景介绍

大语言模型发展很快,但让 AI 回答私有领域的问题,始终是件麻烦事。通用模型再强大,也不知道你公司那份保密的技术规范里写了什么,更不知道你上周才写的项目文档。

解决这个问题的标准做法是 RAG(检索增强生成)。原理不复杂:先把私有文档切成小块,转成向量存起来。用户提问时,系统从文档里找出最相关的内容,连同问题一起发给 LLM,让模型根据提供的上下文来回答。

以前搭 RAG 系统,基本要靠云服务。OpenAI API、Pinecone 向量数据库、Azure 各种服务——钱是一方面,数据隐私是更棘手的事。你的文档得上传到第三方服务器,这对于敏感行业来说不太能接受。

好在开源模型现在也能打了。完全可以搭一套本地运行的 RAG 系统,不用联网,所有数据都在自己机器上。本文就聊聊怎么用 LangChain + Ollama + Chroma,在个人电脑上构建一个完整的 RAG 问答系统。

## 问题描述

很多开发者尝试搭建本地 RAR 系统时,经常卡在几个地方。首先是环境配置,LLM 运行时、向量数据库、嵌入模型,每个都要装,每个都可能不兼容。然后是性能,本地模型响应比云端 API 慢好几倍,得想办法优化。最后是中文支持问题,开源模型对中文的支持参差不齐,得挑合适的。

这篇文章就是来解决这些问题的。方案是这样的:用 Ollama 跑本地大模型,目前最流行的本地 LLM 运行时;用 Chroma 做向量数据库,轻量级、好安装;用 LangChain 整合各个组件,提供统一接口。整套装下来,一台普通笔记本就能跑,不需要显卡也能跑简单测试。

## 详细步骤

### 步骤一:安装必要组件

第一步是装 Ollama。访问 ollama.com,根据你的操作系统下载安装。装好以后,在终端里拉模型:

“`bash
# 拉 Mistral 模型,轻量级,适合本地
ollama pull mistral

# 或者拉对中文支持好一点的 Qwen
ollama pull qwen:7b
“`

Chroma 向量数据库直接 pip 安装:

“`bash
pip install chromadb langchain langchain-community langchain-ollama
“`

### 步骤二:准备文档和文本分割

文档要先处理成能检索的格式。TXT、PDF、Markdown 都行,这里用文本文件演示。

文本分割是 RAG 里最容易被忽视但其实很关键的环节。分块太小,语义不完整;分块太大,会把无关内容也带进来,影响答案质量。LangChain 提供了好几种分割器,RecursiveCharacterTextSplitter 是最常用的:

“`python
from langchain.text_splitter import RecursiveCharacterTextSplitter

def load_and_split_documents(file_path, chunk_size=500, chunk_overlap=50):
“””加载文档并分割成小块”””
with open(file_path, “r”, encoding=”utf-8″) as f:
text = f.read()

text_splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
separators=[“\n\n”, “\n”, “。”, ” “, “”]
)

chunks = text_splitter.split_text(text)
return chunks
“`

### 步骤三:创建向量存储

分好块的文本要转成向量才能做相似度搜索。Chroma 是轻量级向量数据库,非常适合本地开发。嵌入模型用 Ollama 自带的:

“`python
from langchain_ollama import OllamaEmbeddings
from langchain_chroma import Chroma

def create_vector_store(chunks, persist_directory=”./chroma_db”):
“””创建向量存储”””
embeddings = OllamaEmbeddings(
model=”nomic-embed-text”,
base_url=”http://localhost:11434″
)

vector_store = Chroma.from_texts(
texts=chunks,
embedding=embeddings,
persist_directory=persist_directory
)

return vector_store
“`

嵌入模型和 LLM 是分开的。nomic-embed-text 专门优化过文本嵌入,中文效果还行。想更好的中文支持可以换其他模型试试。

### 步骤四:构建问答链

向量存储好了,接下来搭问答系统。LangChain 的 LCEL 可以方便地把各个组件串联起来:

“`python
from langchain_ollama import ChatOllama
from langchain import PromptTemplate
from langchain.schema.runnable import RunnablePassthrough

def build_qa_chain(vector_store):
“””构建问答链”””
llm = ChatOllama(
model=”mistral”,
base_url=”http://localhost:11434″,
temperature=0.7
)

template = “””你是一个专业的问答助手。请根据以下上下文信息来回答用户的问题。

上下文信息:
{context}

用户问题:{question}

请给出准确、详细的回答。如果上下文中没有相关信息,请如实说明。”””

prompt = PromptTemplate(
template=template,
input_variables=[“context”, “question”]
)

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

qa_chain = (
{“context”: vector_store.as_retriever() | format_docs,
“question”: RunnablePassthrough()}
| prompt
| llm
)

return qa_chain
“`

### 步骤五:运行完整示例

把各部分组合起来,完整的可运行程序:

“`python
import os

def main():
# 示例文档内容
sample_document = “””
项目名称:企业知识管理系统

项目概述:本系统旨在为企业提供一个集中管理内部文档的知识管理平台。
主要功能包括文档上传、版本控制、全文检索和权限管理。

技术栈:
– 后端:Python + FastAPI
– 数据库:PostgreSQL
– 前端:React + TypeScript
– 搜索引擎:Elasticsearch

部署环境:Docker 容器化部署,支持 Kubernetes 集群

开发团队:
– 产品经理:张三
– 技术负责人:李四
– 前端开发:王五
– 后端开发:赵六
“””

# 保存示例文档
with open(“sample.txt”, “w”, encoding=”utf-8″) as f:
f.write(sample_document)

# 加载并分割文档
print(“正在加载和分割文档…”)
chunks = load_and_split_documents(“sample.txt”)
print(f”文档已分割为 {len(chunks)} 个片段”)

# 创建向量存储
print(“正在创建向量存储…”)
vector_store = create_vector_store(chunks)
print(“向量存储创建完成”)

# 构建问答链
print(“正在构建问答链…”)
qa_chain = build_qa_chain(vector_store)

# 提问
questions = [
“项目使用什么技术栈?”,
“开发团队有哪些人?”,
“如何部署这个项目?”
]

print(“\n” + “=”*50)
print(“开始问答测试”)
print(“=”*50 + “\n”)

for question in questions:
print(f”问题:{question}”)
response = qa_chain.invoke(question)
print(f”回答:{response.content}”)
print(“-” * 50 + “\n”)

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

## 运行结果

跑一下试试:

“`
正在加载和分割文档…
文档已分割为 5 个片段
正在创建向量存储…
向量存储创建完成
正在构建问答链…

==================================================
开始问答测试
==================================================

问题:项目使用什么技术栈?
回答:项目使用以下技术栈:
– 后端:Python + FastAPI
– 数据库:PostgreSQL
– 前端:React + TypeScript
– 搜索引擎:Elasticsearch

————————————————–

问题:开发团队有哪些人?
回答:开发团队成员包括:
– 产品经理:张三
– 技术负责人:李四
– 前端开发:王五
– 后端开发:赵六

————————————————–

问题:如何部署这个项目?
回答:项目采用 Docker 容器化部署方式,支持 Kubernetes 集群部署。

————————————————–
“`

回答得挺准确,直接从文档里摘的内容,没有乱说。测试用的文档比较简单,如果是更复杂的文档,可能需要调调参数。

## 总结

本文介绍了怎么用 LangChain + Ollama + Chroma 在本地搭建 RAG 问答系统。最大好处是数据都在自己机器上,不用传给第三方。

几个可以调整的参数:chunk_size 决定每个片段多大,根据文档特点调;temperature 控制 LLM 的 creativity,高一点回答更发散,低一点更正经;retriever 返回多少个相关文档片段,也能调。

想做得更好,可以尝试:换其他 LLM 模型,Qwen、Yi 这些对中文支持更好;针对不同类型文档用不同的分割策略;加上对话历史功能,让系统能记住之前说了什么。

RAG 技术在发展,除了基础版,还有 Hybrid Search、Query Rewriting、Self-Query 那些高级玩法。学会了这些,能搭出更猛的知识问答系统。

暂无评论

发送评论 编辑评论


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