引言
RAG(Retrieval-Augmented Generation)是一种结合检索与生成的AI架构,能让大模型基于私有知识库回答问题。本教程将使用LangChain框架和Ollama本地模型,搭建一个完全离线的文档问答系统。
准备工作
环境要求
- Python 3.10+
- 至少8GB内存(推荐16GB)
- 操作系统:Windows/macOS/Linux
安装依赖
pip install langchain langchain-community chromadb sentence-transformers ollama
下载本地模型
使用Ollama下载一个嵌入模型和一个语言模型:
ollama pull nomic-embed-text
ollama pull llama3:8b
步骤1:加载文档
假设你有一个PDF文件夹./docs,使用LangChain的PDFLoader:
from langchain_community.document_loaders import PyPDFDirectoryLoader
loader = PyPDFDirectoryLoader("./docs")
documents = loader.load()
print(f"加载了 {len(documents)} 个文档")
步骤2:分割文档
将大文档分割成小块,便于检索:
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50
)
splits = text_splitter.split_documents(documents)
print(f"分割为 {len(splits)} 个块")
步骤3:创建向量数据库
使用Chroma作为向量存储,并生成嵌入:
from langchain_community.embeddings import OllamaEmbeddings
from langchain_community.vectorstores import Chroma
embeddings = OllamaEmbeddings(model="nomic-embed-text")
vectorstore = Chroma.from_documents(
documents=splits,
embedding=embeddings,
persist_directory="./chroma_db"
)
print("向量数据库创建成功")
步骤4:构建检索链
使用LangChain的检索QA链:
from langchain_community.llms import Ollama
from langchain.chains import RetrievalQA
llm = Ollama(model="llama3:8b", temperature=0)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
return_source_documents=True
)
步骤5:运行问答
query = "文档中提到了哪些重要的技术?"
result = qa_chain.invoke({"query": query})
print("回答:", result["result"])
print("来源:", [doc.metadata["source"] for doc in result["source_documents"]])
进阶优化
1. 使用更好的嵌入模型
nomic-embed-text是轻量级模型,如果追求精度,可以替换为bge-large-en-v1.5(需Ollama支持)。
2. 调整检索参数
search_kwargs={"k": 5}:返回更多相关文档- 使用MMR(最大边际相关性)避免重复:
retriever = vectorstore.as_retriever(search_type="mmr")
3. 添加对话记忆
使用ConversationBufferMemory让系统记住历史对话:
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
memory=memory
)
4. 部署为Web服务
使用Gradio或Streamlit快速搭建前端界面:
import gradio as gr
def answer_question(question):
result = qa_chain.invoke({"query": question})
return result["result"]
iface = gr.Interface(fn=answer_question, inputs="text", outputs="text")
iface.launch()
结语
至此,你已经拥有一个完全本地化的RAG系统。你可以将任何私有文档(PDF、Word、网页)放入./docs文件夹,系统就能基于它们回答问题。这种方法确保了数据安全,无需上传到云端。
下一步可以尝试:
- 支持更多文件类型(如CSV、Markdown)
- 集成语音输入输出
- 优化检索速度(使用FAISS替代Chroma)
祝你搭建愉快!