本地 RAG 可以把文档切片并存入本机 Chroma,再检索相关片段交给 DeepSeek 生成答案。Chroma 和 embedding 可以留在本机,但使用 DeepSeek API 时,提交给模型的上下文会离开本机,不能把它描述成完全离线方案。
架构与边界
典型流程是:加载文档、切片、生成 embedding、写入 Chroma、检索 Top-K 片段、拼接上下文、调用模型生成答案。文档原文和向量可以本地保存;如果使用云端模型,问题和检索片段会发送到 API 服务,应先做脱敏和访问控制。
环境准备
python3 -m venv .venv
source .venv/bin/activate
pip install chromadb openai langchain langchain-community
pip install sentence-transformers pypdf python-docx python-dotenv
如果需要固定依赖,请把经过测试的完整版本写入 requirements.txt。带有比较符号的 pip 版本约束要加引号,例如 pip install 'openai>=1.0.0'。
使用 Chroma 建立本地集合
import chromadb
from openai import OpenAI
chroma = chromadb.PersistentClient(path="./chroma_db")
collection = chroma.get_or_create_collection("docs")
client = OpenAI(
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
)
collection.add(
ids=["doc-1"],
documents=["这里是已经切片的文档内容"],
embeddings=[embedding_vector],
)
result = collection.query(query_embeddings=[query_vector], n_results=3)
context = "\n\n".join(result["documents"][0])
实际项目应给每个片段保存来源、页码、更新时间和权限标签,避免检索结果无法追溯。
调用 DeepSeek API
response = client.chat.completions.create(
model="deepseek-flash",
messages=[
{"role": "system", "content": "只根据提供的资料回答,资料不足时明确说明。"},
{"role": "user", "content": f"资料:\n{context}\n\n问题:{question}"},
],
temperature=0.2,
)
print(response.choices[0].message.content)
DeepSeek 官方当前文档列出 deepseek-flash 和 deepseek-v4-pro。旧的 deepseek-v4-flash 名称属于兼容旧请求的名称,正式代码应以官方模型列表和价格页面为准。
检索质量与安全
- 中文文档先按标题、段落和列表结构切片,再调整 chunk size 和 overlap。
- 用召回率、答案引用正确率和拒答准确率评估,不只看响应速度。
- 检索结果必须过滤租户、部门和文档权限。
- 对用户问题、文档内容和系统提示分层,防止提示注入。
- 对模型调用设置超时、重试、缓存和成本上限。
参考资料
如果数据不能离开内网,应把生成模型也部署在本地,或使用经过合规评估的私有化推理服务。
