基于 LangChain RAG 构建本地 AI 知识库助手
利用检索增强生成(RAG)技术,我们可以开发一个 AI 机器人,该机器人能够读取 Markdown 文本作为知识库,实现简单快捷的私有化问答。
RAG 是什么
大型语言模型(LLMs)是在一个大型但固定的数据语料库上进行训练的,这限制了它们对于私人或最新信息的推理能力。检索增强生成(RAG)已经成为一种流行且强大的机制,用于扩展 LLM 的知识库,通过从外部数据源检索的文档来通过上下文学习来支持 LLM 生成。

技术栈
- LLM 服务器: Ollama
- 模型: mistral:latest
- Language Model Integration Framework: LangChain
- Web framework for API: FastAPI
工作原理
系统主要包含三个部分:
- 数据加载与切片:将本地 Markdown 文件加载并切分为适合嵌入的片段。
- 向量存储:使用 Embedding 模型将文本片段转换为向量并存入向量数据库。
- 检索与生成:用户提问时,检索相关片段,结合 Prompt 发送给 LLM 生成回答。
环境配置
1. 安装依赖
确保 Python 环境已就绪,创建虚拟环境并安装所需包。
pip install -r requirements.txt
requirements.txt 内容如下:
langchain==0.1.0
langchain-community==0.0.6
fastapi==0.109.0
uvicorn[standard]==0.27.0
python-dotenv==1.0.0
ollama==0.1.0
chromadb==0.4.22
2. 配置环境变量
获取你的 langchain API Key(如使用 OpenAI 或其他服务),并将其配置在 .env.example 环境变量中,复制为 .env 文件使其生效。
cp .env.example .env
copy .env.example .env
.env 示例内容:
LANGCHAIN_API_KEY=your_api_key_here
OLLAMA_BASE_URL=http://localhost:11434
3. Ollama 模型配置
确保 Ollama 服务正在运行。
pip install ollama
ollama run mistral:latest
ollama list
检查模型列表确认 mistral:latest 已下载。
知识库准备
您可以随时更换 ./data/knowledge.md 知识库。这里选用了一本亚当斯密的《国富论》作为示例。
确保目录结构如下:
project_root/
├── main.py
├── requirements.txt
├── .env
├── data/
│ └── knowledge.md
└── vector_store/
└── (auto-generated)
核心代码实现
1. 初始化 LangChain 链 (main.py)
以下是一个完整的 FastAPI 应用示例,集成了 LangChain 和 Ollama。
import os
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from dotenv import load_dotenv
from langchain_community.llms import Ollama
from langchain.chains import RetrievalQA
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings
load_dotenv()
app = FastAPI(title="RAG Assistant")
DATA_PATH = "./data/knowledge.md"
VECTOR_STORE_PATH = "./vector_store"
loader = TextLoader(DATA_PATH, encoding='utf-8')
documents = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
chunks = text_splitter.split_documents(documents)
try:
from langchain_community.embeddings import OllamaEmbeddings
embeddings = OllamaEmbeddings(model="nomic-embed-text", base_url=os.getenv("OLLAMA_BASE_URL", "http://localhost:11434"))
except ImportError:
embeddings = None
if embeddings:
db = Chroma.from_documents(chunks, embeddings, persist_directory=VECTOR_STORE_PATH)
:
Exception()
retriever = db.as_retriever(search_kwargs={: })
llm = Ollama(
model=,
temperature=,
base_url=os.getenv(, )
)
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type=,
retriever=retriever,
return_source_documents=
)
():
question:
():
answer:
source_documents:
():
:
result = qa_chain({: request.question})
QueryResponse(
answer=result[],
source_documents=[doc.page_content doc result[]]
)
Exception e:
HTTPException(status_code=, detail=(e))
__name__ == :
uvicorn
uvicorn.run(app, host=, port=)
启动程序
在项目根目录下运行:
uvicorn main:app --reload
服务将在 http://localhost:8000 启动。
测试接口
可以使用 Postman 或 curl 进行测试:
curl -X POST 'http://localhost:8000/query' \
-H 'Content-Type: application/json' \
-d '{"question": "什么是国富论?"}'
前端集成建议
HTML 文件可包含简单的 JS 请求,可以在此基础上进一步开发前端。
<script>
fetch('http://localhost:8000/query', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({question: 'What is the wealth of nations?'})
}).then(res => res.json()).then(data => console.log(data.answer));
</script>
常见问题与优化
- 响应速度慢:尝试减小
chunk_size 或使用更快的 Embedding 模型。
- 幻觉问题:调整
temperature 参数至 0.1 以降低随机性。
- 知识更新:重新运行初始化脚本以更新向量数据库。
通过以上步骤,您就完成了一个基于 LangChain RAG 的本地 AI 小助手搭建。