构建全离线 RAG 智能体:使用 LangGraph Ollama 和嵌入式 Qdrant
- 作者

- 姓名
- Nino
- 职业
- Senior Tech Editor
绝大多数的 检索增强生成 (RAG) 教程在开头都会要求你 “设置 OPENAI_API_KEY”。虽然这对于快速原型开发非常方便,但在实际的企业级应用中,这种对外部云端的依赖往往会带来数据隐私、网络延迟以及不可控的成本问题。本指南将展示如何构建一个完全离线的 RAG 智能体,它不依赖任何外部 API,完全运行在你的本地设备上。
我们将使用 LangGraph 进行任务编排,使用 Ollama 运行本地大语言模型 (LLM) 和嵌入模型 (Embeddings),并利用 Qdrant 的嵌入式模式 (Embedded Mode) 作为向量存储。这种架构的核心在于 “可插拔的边界设计”。这意味着你可以在本地进行低成本开发,而当需要上线生产环境时,可以通过 n1n.ai 轻松切换到高性能的云端模型,而无需重写核心业务逻辑。
离线技术栈的核心组件
要实现零 API 密钥的 RAG 系统,我们需要以下三个关键组件:
- Ollama: 本地推理引擎。我们将运行两个模型:
qwen3.5:9b(或DeepSeek-V3)用于对话推理,以及bge-m3(1024 维多语言模型)用于生成向量。 - 嵌入式 Qdrant (Embedded Qdrant): 无需 Docker 容器或独立的服务器进程。Qdrant 的 Python 客户端支持直接在磁盘路径上运行,将向量数据持久化到本地目录。
- LangGraph: 用于构建状态机和 ReAct (Reasoning and Acting) 循环。它负责协调模型何时进行检索,何时整合信息并回答用户。
第一步:配置本地模型
首先,确保你的机器上安装了 Ollama。通过以下命令拉取必要的模型:
ollama pull qwen3.5:9b # 用于对话和推理
ollama pull bge-m3 # 用于生成嵌入向量(1024 维)
在本地运行这些模型可以完全消除按 Token 计费的开销。对于追求极致稳定性的开发者,n1n.ai 提供了与这些本地模型接口高度兼容的云端 API,方便你在本地资源不足时进行平滑迁移。
第二步:实现可切换的嵌入工厂
为了保证代码的灵活性,我们使用工厂模式来管理嵌入模型。这样,无论后端是 Ollama 还是像 n1n.ai 这样的服务商,上层逻辑都保持一致。
# app/llm/embeddings.py
from functools import lru_cache
from langchain_core.embeddings import Embeddings
@lru_cache
def get_embeddings() -> Embeddings:
settings = get_settings()
provider = settings.embedding_provider.lower()
if provider == "ollama":
from langchain_ollama import OllamaEmbeddings
return OllamaEmbeddings(
model=settings.embedding_model,
base_url=settings.ollama_url
)
if provider == "openai":
from langchain_openai import OpenAIEmbeddings
# 在生产环境中,通过 n1n.ai 获得更快的响应
return OpenAIEmbeddings(
base_url="https://api.n1n.ai/v1",
api_key=settings.n1n_api_key,
model=settings.embedding_model
)
raise ValueError(f"未知的嵌入提供商: {provider}")
第三步:配置嵌入式向量存储
Qdrant 的嵌入式模式非常适合本地调试。它不需要维护复杂的数据库集群,只需指定一个文件夹路径即可。
# app/rag/store.py
from qdrant_client import QdrantClient
@lru_cache
def get_client() -> QdrantClient:
s = get_settings()
if s.qdrant_url:
# 生产环境:连接到远程 Qdrant 服务
return QdrantClient(url=s.qdrant_url, api_key=s.qdrant_api_key)
# 本地开发:使用嵌入式模式,数据持久化到本地路径
return QdrantClient(path=s.qdrant_path)
专家提示 (Pro Tip):嵌入式模式会将目录锁定在当前进程中。如果你在运行服务器的同时尝试运行数据注入脚本,会触发数据库锁定错误。正确的操作顺序是:停止服务器 -> 运行注入脚本 -> 重新启动服务器。
第四步:智能数据注入流程
不同的嵌入模型生成的向量维度不同(例如 bge-m3 是 1024 维,而 OpenAI 的 text-embedding-3-small 是 1536 维)。为了避免手动修改配置,我们可以通过 “探测 (Probe)” 机制自动检测维度。
# scripts/ingest.py (核心逻辑)
# 1. 加载并切分文档
# 2. 动态探测嵌入维度
embeddings = get_embeddings()
probe_dim = len(embeddings.embed_query("probe"))
# 3. 自动创建匹配维度的集合
ensure_collection(name="docs", vector_size=probe_dim)
# 4. 写入向量数据
get_vector_store().add_documents(chunks)
这种自动化处理使得当你从本地 Ollama 切换到 n1n.ai 的高性能 API 时,系统能够自动适应不同的向量规格。
第五步:运行 ReAct 循环与结果分析
在本地环境中,LangGraph 的 ReAct 循环表现得非常直观。当用户询问 “本项目如何实现长期记忆?” 时,我们可以看到以下状态流转:
- HumanMessage: 用户的提问。
- AIMessage (tool_calls): 模型判断需要调用
search_docs工具。 - ToolMessage: 从本地 Qdrant 检索到的文档片段返回给模型。
- AIMessage: 模型综合检索到的信息,给出带引用的回答。
所有的这些步骤,包括复杂的向量检索和模型推理,都在你的笔记本电脑上完成,无需连接互联网。
本地 RAG 的常见坑位与避坑指南
虽然全离线运行非常酷,但在实际操作中你会遇到一些云端 API 隐藏掉的问题:
- 模型合成失败 (Synthesis Whiff): 有时 9B 级别的本地模型在检索到正确信息后,却返回一个空字符串。这是因为小参数模型在处理复杂长上下文时偶尔会 “短路”。如果你的业务对稳定性要求极高,建议在生产环境中使用 n1n.ai 提供的
Claude 3.5 Sonnet或DeepSeek-V3等更强大的模型。 - 冷启动延迟: Ollama 在第一次接收请求时需要将模型加载到显存。首条请求可能会有几秒甚至十几秒的延迟,随后的请求则会非常迅速。在进行基准测试时,请忽略第一次运行的数据。
- 维度不匹配: 如果你切换了
embedding_provider,必须清空向量数据库并重新注入数据。1024 维的向量无法在 1536 维的集合中进行检索。
总结
通过结合 LangGraph、Ollama 和 Qdrant,我们证明了即使在没有网络连接的情况下,依然可以构建出功能完备、具备推理能力的 RAG 智能体。这种 “本地优先” 的开发模式不仅保护了隐私,还极大地降低了开发成本。当你准备将应用推向市场,需要更高的并发处理能力和更低的推理延迟时,n1n.ai 将是你最可靠的合作伙伴,助你轻松实现从本地到云端的跨越。
立即在 n1n.ai 获取免费 API 密钥。