RAG 知识库搭建实战:国产开源模型 + 本地部署的完整方案
RAG 知识库搭建实战:国产开源模型 + 本地部署的完整方案
RAG(检索增强生成)是国产开源模型最有价值的应用场景之一:把你的文档、代码库、内部知识喂给模型,让它基于你的数据回答问题——而不是靠通用训练数据「猜」。本文给出用国产开源模型搭建 RAG 知识库的完整方案:Embedding 选型、向量库选型、文档切分策略,以及本地部署(Ollama Embedding + llama.cpp)和云端 API 两条路线的实现。
30 秒版本
RAG = 文档切分 → Embedding 向量化 → 存入向量库 → 用户提问时检索相关片段 → 拼进提示词让模型回答。本地方案:Ollama Embedding + llama.cpp 模型 + Chroma 向量库;云端方案:EXAIV API + 任意向量库。核心代码用 LangChain 30 行搞定。
RAG 的四个环节
RAG 不是「把文档塞给模型」那么简单。它是一个流水线:
| 环节 | 做什么 | 关键决策 |
|---|---|---|
| 1. 文档切分 | 把文档拆成可检索的片段 | 片段大小、重叠度 |
| 2. Embedding | 把片段转成向量 | Embedding 模型选型 |
| 3. 向量检索 | 用户提问 → 找相关片段 | 向量库选型、相似度阈值 |
| 4. 生成回答 | 把检索片段拼进提示词 | LLM 选型、提示词设计 |
Embedding 和 LLM 分开选
Embedding 模型负责「理解文本的语义并转成向量」,LLM 负责「基于检索到的片段生成回答」。它们是两个独立的模型,不必用同一个——你可以用一个轻量 Embedding 模型配一个能力强的 LLM。这和「全用一个模型」的方案相比更灵活也更省资源。
Embedding 选型
Embedding 模型的选择标准:多语言支持(中文场景必须有)、向量维度(影响存储和检索速度)、模型大小(影响 Embedding 速度)。
| 方案 | 说明 | 适用 |
|---|---|---|
| Ollama Embedding | 本地运行,零成本 | 本地方案首选 |
| 云端 API Embedding | 按量计费,无需本地资源 | 云端方案 |
| Sentence Transformers | 开源 Python 库,模型丰富 | 自定义部署 |
本地方案用 Ollama 的 Embedding 最简单:
# 拉取一个 Embedding 模型(社区维护,以 Ollama 实际可用为准)
ollama pull nomic-embed-text
向量库选型
| 向量库 | 特点 | 适用 |
|---|---|---|
| Chroma | 轻量、纯 Python、零部署 | 个人项目、原型验证 |
| Qdrant | 高性能、支持过滤 | 生产环境 |
| Milvus | 分布式、大规模 | 大规模企业 |
| FAISS | Meta 开源、纯计算库 | 嵌入到应用里 |
个人和小团队从 Chroma 起步最省事——纯 Python、零外部依赖,一行代码存取向量。
完整实现:LangChain 30 行起步
以下是一个最小可运行的 RAG 流水线,用本地模型:
# pip install langchain langchain-community chromadb
from langchain_community.embeddings import OllamaEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.llms import Ollama
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 1. 文档切分
splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每个片段约 500 字符
chunk_overlap=50, # 片段间重叠 50 字符
)
docs = splitter.split_documents(your_documents)
# 2. Embedding + 存入向量库
embeddings = OllamaEmbeddings(base_url="http://127.0.0.1:11434", model="nomic-embed-text")
vectorstore = Chroma.from_documents(docs, embeddings)
# 3. 检索 + 生成
llm = Ollama(base_url="http://127.0.0.1:11434", model="your-model")
query = "你的问题"
results = vectorstore.similarity_search(query, k=3) # 取最相关的 3 个片段
context = "\n\n".join([r.page_content for r in results])
prompt = f"根据以下内容回答问题。\n\n{context}\n\n问题:{query}"
answer = llm.invoke(prompt)
print(answer)
切换到云端 API 只改三行
把 Ollama 的 LLM 换成 EXAIV 的 OpenAI 兼容端点,Embedding 保持本地或改用云端 Embedding API,向量库不变——LangChain 的抽象层让「本地模型」和「云端 API」可以互换,这正是 OpenAI 兼容接口的价值。
云端方案:EXAIV 端点
如果不想管理本地模型,用 EXAIV 的 OpenAI 兼容端点做 RAG 的生成环节:
from openai import OpenAI
client = OpenAI(
api_key="你的APIKey",
base_url="https://exaiv.com/api/ai/v1",
)
# 检索到的片段拼进系统提示
resp = client.chat.completions.create(
model="kimi-k3", # 以 /models 目录实时为准
messages=[
{"role": "system", "content": f"根据以下内容回答问题。如果内容不足以回答,请明确说明。\n\n{context}"},
{"role": "user", "content": query},
],
)
print(resp.choices[0].message.content)
文档切分的策略
切分粒度直接影响检索质量:
| 策略 | chunk_size | 适合 |
|---|---|---|
| 精细 | 200-300 字符 | FAQ、短文档、精确匹配 |
| 标准 | 400-600 字符 | 通用文档 |
| 粗粒度 | 800-1200 字符 | 长文档、上下文密集 |
切分不是越小越好
片段太小时上下文断裂(一个完整论点被切成两半),检索到的片段无法独立回答问题。片段太大时会稀释语义、降低检索精度。从 500 字符起步,根据检索效果调整——这是 RAG 调优里最值得花时间的参数。
本地 vs 云端的取舍
| 维度 | 本地方案 | 云端方案 |
|---|---|---|
| 数据隐私 | 文档和查询都不出机 | 文档内容发给 API |
| 成本 | 零调用成本 | 按 token 计费 |
| 质量 | 受限于本地模型能力 | 可用旗舰模型 |
| 运维 | 自己管理 | 零运维 |
敏感数据 → 本地方案(数据不出机);需要旗舰质量 → 云端方案(kimi-k3 等旗舰模型);混合需求 → 本地 Embedding + 云端 LLM(Embedding 不含敏感信息、LLM 从 EXAIV 调用)。
FAQ
RAG 和直接把文档塞给模型有什么区别?
Embedding 模型用什么好?
检索出来的片段不准怎么办?
可以在 RAG 里用多个模型吗?
LangChain 和 LlamaIndex 怎么选?
相关阅读
- LangChain 接入 EXAIV — LangChain 完整接入教程
- Qwen 本地部署完整手册 — 本地部署全流程
- Qwen 系列怎么选 — 模型选型
- 国产开源 vs 海外旗舰 — 本地与云端取舍
- 定价 — 云端方案实时价格