Python + LangChain 本地 RAG 实战:让 AI 学你的知识

# Python + LangChain 本地 RAG 实战:让 AI 学你的知识

Ollama 跑通了,下一个问题是:怎么让它学会你自己的东西?

单纯跑模型,AI 一问三不知。你扔给它一份公司文档,它该不知道还是不知道。这时候该 RAG 上场了——Retrieval Augmented Generation,检索增强生成。听起来高大上其实就是那么回事:先找到相关内容,再让 AI 根据这些内容回答。

这篇文章就教你用 Python + LangChain,在本地搭一个完整的 RAG 问答系统。

## RAG 到底是怎么回事

传统 LLM 有几个硬伤:训练数据有截止日期、不知道你的私有数据、偶尔会一本正经地胡说八道。RAG 通过一套流程来补这些短板:

1. 把 PDF、txt、markdown 文档读进来
2. 把长文档切成小块
3. 把文本转成向量存起来
4. 用户提问时,先找出最相关的几个小块
5. 把这些小块塞进 Prompt 里
6. 最后让 LLM 基于这个增强后的上下文生成答案

说白了就是:先检索,再生成。

环境准备很简单:

“`bash
pip install langchain langchain-community langchain-ollama ollama chroma beautifulsoup4 pypdf
“`

本文用的版本:Python 3.10+、LangChain 0.3+、Chroma 向量数据库、Ollama 的 llama3:latest 模型。

## 实际问题

你可能遇到过这些场景:

– 公司有一堆内部文档,想让 AI 帮忙查
– 自己的笔记、日记、博客想让它分析
– 扔一个 PDF 报告进去,想问点什么
– 不希望 AI 凭空编造,必须有据可查

这些需求,RAG 都能解决。

## 一步步来

### 第一步:准备知识文档

先建个测试目录扔点文档进去:

“`python
import os

# 创建测试目录
docs_folder = “./knowledge_base”
os.makedirs(docs_folder, exist_ok=True)

# 扔几个测试文档进去
sample_docs = [
(“公司介绍.txt”, “””我们的公司成立于2020年,专注于人工智能领域。
创始团队来自谷歌、微软等知名科技公司。
公司总部位于北京,在上海和深圳设有分部。
2023年获得红杉资本B轮融资5000万美元。””),

(“产品手册.txt”, “””产品名称:SmartAI Assistant
版本:3.2.1
主要功能:智能问答、文档分析、数据可视化
支持语言:中文、英文、日文
系统要求:Mac/Windows/Linux
定价:企业版999元/年,团队版299元/年”””
)
]

for filename, content in sample_docs:
with open(f”{docs_folder}/{filename}”, “w”, encoding=”utf-8″) as f:
f.write(content)

print(“文档就绪”)
“`

### 第二步:加载文档、切块

用 LangChain 的文档加载器处理:

“`python
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
import os

# 加载文件夹里的文档
def load_documents(folder_path):
documents = []
for filename in os.listdir(folder_path):
if filename.endswith((“.txt”, “.md”, “.pdf”)):
filepath = os.path.join(folder_path, filename)
loader = TextLoader(filepath, encoding=”utf-8″)
docs = loader.load()
documents.extend(docs)
return documents

# 加载并切块
raw_documents = load_documents(docs_folder)

# 切块策略:每个块 200 字符,相邻块重叠 50 字符
text_splitter = CharacterTextSplitter(
chunk_size=200,
chunk_overlap=50,
separator=”\n”
)

docs = text_splitter.split_documents(raw_documents)

print(f”共 {len(docs)} 个文档块”)
for i, doc in enumerate(docs[:3]):
print(f”块 {i+1}: {doc.page_content[:50]}…”)
“`

### 第三步:建向量数据库

Chroma 是本地向量数据库的好选择:

“`python
from langchain_ollama import OllamaEmbeddings
from langchain_community.vectorstores import Chroma

# 嵌入模型用 Ollama 的 nomic-embed-text
embeddings = OllamaEmbeddings(
model=”nomic-embed-text”,
base_url=”http://localhost:11434″
)

# 存入 Chroma
vectorstore = Chroma.from_documents(
documents=docs,
embedding=embeddings,
persist_directory=”./chroma_db”
)

print(“向量数据库建好了”)
“`

### 第四步:拼装 RAG 链

检索和生成要连起来:

“`python
from langchain_ollama import ChatOllama
from langchain import hub
from langchain_core.output_parsers import StrOutputParser

# 用本地模型
llm = ChatOllama(
model=”llama3:latest”,
base_url=”http://localhost:11434″,
temperature=0
)

# LangChain Hub 上现成的 RAG prompt
prompt = hub.pull(“rlm/rag-prompt”)

# 检索器:找最相关的 3 个块
retriever = vectorstore.as_retriever(
search_kwargs={“k”: 3}
)

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

rag_chain = (
{“context”: retriever | format_docs, “question”: lambda x: x}
| prompt
| llm
| StrOutputParser()
)

print(“RAG 链完成”)
“`

## 完整代码

上面的步骤整合到一个脚本里:

“`python
#!/usr/bin/env python3
“””本地 RAG 问答系统”””

import os
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_ollama import OllamaEmbeddings, ChatOllama
from langchain_community.vectorstores import Chroma
from langchain import hub
from langchain_core.output_parsers import StrOutputParser

class LocalRAG:
def __init__(self, docs_folder=”./knowledge_base”):
self.docs_folder = docs_folder
self.embeddings = None
self.vectorstore = None
self.llm = None
self.rag_chain = None

def init(self):
print(“加载文档…”)
documents = self._load_documents()

print(“切块…”)
chunks = self._split_documents(documents)

print(“建向量库…”)
self._create_vectorstore(chunks)

print(“拼装 RAG 链…”)
self._build_rag_chain()

print(“搞定”)

def _load_documents(self):
documents = []
for root, dirs, files in os.walk(self.docs_folder):
for file in files:
if file.endswith((“.txt”, “.md”)):
loader = TextLoader(
os.path.join(root, file),
encoding=”utf-8″
)
documents.extend(loader.load())
return documents

def _split_documents(self, documents):
splitter = CharacterTextSplitter(
chunk_size=200,
chunk_overlap=50
)
return splitter.split_documents(documents)

def _create_vectorstore(self, chunks):
self.embeddings = OllamaEmbeddings(
model=”nomic-embed-text”
)
self.vectorstore = Chroma.from_documents(
documents=chunks,
embedding=self.embeddings,
persist_directory=”./chroma_db”
)

def _build_rag_chain(self):
self.llm = ChatOllama(
model=”llama3:latest”,
temperature=0
)

retriever = self.vectorstore.as_retriever(search_kwargs={“k”: 3})
prompt = hub.pull(“rlm/rag-prompt”)

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

self.rag_chain = (
{“context”: retriever | format_docs, “question”: lambda x: x}
| prompt
| self.llm
| StrOutputParser()
)

def ask(self, question):
if not self.rag_chain:
raise RuntimeError(“先调用 init()”)

print(f”\n问题: {question}”)
print(“思考中…”)

answer = self.rag_chain.invoke(question)

print(f”回答: {answer}”)
return answer

if __name__ == “__main__”:
# 初始化
rag = LocalRAG(“./knowledge_base”)
rag.init()

# 问答测试
questions = [
“公司成立于哪一年?”,
“产品多少钱一年?”,
“创始团队来自哪里?”
]

for q in questions:
rag.ask(q)
print(“-” * 50)
“`

## 跑起来

“`bash
$ python rag_chatbot.py

加载文档…
切块…
建向量库…
拼装 RAG 链…
搞定

问题: 公司成立于哪一年?
思考中…
回答: 我们的公司成立于2020年,专注于人工智能领域。

问题: 产品多少钱一年?
思考中…
回答: 企业版999元/年,团队版299元/年

问题: 创始团队来自哪里?
思考中…
回答: 创始团队来自谷歌、微软等知名科技公司。
“`

像模像样了。AI 不仅能回答,还能从你给的文档里找到答案。

## 总结

这套流程跑下来,你应该掌握了:

1. 文档加载:txt、md、pdf 都能读
2. 文本切块:重叠机制保证语义不丢
3. 向量存储:Ollama 的 nomic-embed-text 做嵌入,Chroma 本地持久化
4. RAG 链路:检索增强 + LLM 生成

想玩更大?可以试试:

– 加载 PDF:用 PyPDFLoader
– 加载网页:用 WebBaseLoader
– 调参数:改 chunk_size、改 k 值
– 换模型:qwen2.5、deepseek 都可以
– 加界面:Gradio 搭一个简单的 Demo

RAG 的核心价值在于:让任何人都能基于自己的知识库和 AI 对话。企业做内部知识库、个人做私有助手、客服系统接文档——都能用这个思路。自己去试试吧。

暂无评论

发送评论 编辑评论


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