1. 一次 RAG 链路排查的真实场景
知识库 RAG 链路排查与修复记录(Runbook)这类内容,通常出现在文档上传后一直卡在 processing、对话检索报“无法访问知识库”的时候。我这次遇到的场景很典型:pgvector 检索异常和 vLLM 推理超时同时出现,表面看是两个独立问题,实际是三层故障串在一起。这篇 Runbook 会给出可复制的 config.toml 与 settings.json 骨架,并演示通过 TaoToken 统一 Key/API 通道完成连通性验证与错误定位,目标是一份能直接照做的修复清单。
适合谁看:正在维护 RAG 知识库、用 pgvector 做向量存储、用 vLLM 做嵌入或推理服务、并且希望把 MCP 工具链跑通的工程师。整条链路从上传到检索大致是这样:
上传文档 -> 解析切块 -> 向量化(调 vLLM) -> 写 pgvector 对话检索 -> researcher 子代理 -> knowledge/* MCP 工具 -> 检索服务正常时每一段都应该有日志、有请求、有结果。异常时最常见的表现是:vLLM 向量服务零请求、pgvector 里没有新向量、MCP 工具列表为空。下面按“先定位、再修复、后验证”的顺序展开,每一步都给出可复制的配置和命令。
2. TaoToken 前置:统一 Key 与 API 通道
在排查之前,先把模型调用通道统一。TaoToken 在这里的作用是提供一个统一的 Key 和 API 入口,让嵌入模型、推理模型、编码 Agent 都走同一条通道,排查时只需要验证一个连通性,而不是到处找不同的 base_url 和 key。
你需要先拿到 API Key,入口在控制台的 API Keys 页面:
https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=rag_runbook拿到 Key 之后,统一的基础地址是:
https://taotoken.net/api注意这个地址不加 UTM 参数,直接用于代码里的 base_url。接入文档在这里,配置字段和兼容格式都可以对照:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=rag_runbook如果你要验证某个模型是否可用,可以直接在模型对话页面测试:
https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=rag_runbook长期做编码或 Agent 任务,可以看 Coding Plan:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=rag_runbook把 Key 和 base_url 统一之后,RAG 链路里所有模型调用都指向同一个通道,排查时只要确认这一条通道通不通,就能快速排除“是不是模型侧的问题”。
3. 可复制配置:config.toml 与 settings.json 骨架
这一节给出两份骨架配置。config.toml 用于向量化和检索服务,settings.json 用于 MCP 工具与 Agent 侧。字段名按常见约定,你可以按自己项目改名,但结构建议保留。
3.1 config.toml 骨架
# config.toml - RAG 链路配置骨架 [embedding] provider = "openai_compatible" base_url = "https://taotoken.net/api" api_key = "<TAOTOKEN_API_KEY>" model = "your-embedding-model" dimension = 2560 # 与 vLLM 原生输出维度对齐 batch_size = 16 timeout_seconds = 30 [vector_store] driver = "pgvector" dsn = "postgres://user:<REDACTED>@192.168.10.101:5432/lab_kb?sslmode=disable" collection = "kb_chunks" dimension = 2560 index_type = "hnsw" [retrieval] top_k = 8 score_threshold = 0.2 hybrid = true [llm] base_url = "https://taotoken.net/api" api_key = "<TAOTOKEN_API_KEY>" model = "your-chat-model" timeout_seconds = 60关键点:embedding 的 dimension 必须和 pgvector collection 的 dimension 一致。vLLM 原生输出 2560 维时,不要依赖上层发送 dimensions 参数去截断,直接把两边都设成 2560,避免维度不匹配导致的写入失败。
3.2 settings.json 骨架
{ "mcpServers": { "kb": { "command": "python3", "args": ["/app/mcp-servers/kb/kb_mcp_server.py"], "env": { "KB_BASE_URL": "http://lab-kb:8080/api/v1", "KB_API_KEY": "<REDACTED>", "TAOTOKEN_BASE_URL": "https://taotoken.net/api", "TAOTOKEN_API_KEY": "<TAOTOKEN_API_KEY>" } } }, "agent": { "researcher": { "tools": ["knowledge/hybrid_search", "knowledge/get_document"], "timeout_seconds": 45 } } }MCP 的 command 一定要指向构建产物里真实存在的入口。如果构建时只复制了源码、没有 pip 安装,那么 console script 是不存在的,必须用python3 + 脚本路径的方式启动。
3.3 依赖版本钉住
mcp>=1.0.0,<2 pydantic>=2,<3mcp不封顶会被上游 major 升级打穿,1.x 的装饰器在 2.0 里被删掉,直接导致 MCP server 起不来。钉住版本是最省事的做法。
4. 验证请求与成功结果
配置写好后,按“先模型通道、再向量写入、后检索工具”的顺序验证。每一步都要看到明确的成功信号,不要跳步。
4.1 验证 TaoToken 通道连通
curl -sS https://taotoken.net/api/v1/models \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ | head -c 500返回模型列表即通道正常。如果这里就失败,先解决 Key 或网络问题,不要往下查 RAG。
4.2 验证嵌入请求
curl -sS https://taotoken.net/api/v1/embeddings \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"your-embedding-model","input":"连通性测试"}'返回里应包含data[0].embedding,长度与 config.toml 里的 dimension 一致。长度对不上,就是维度配置问题。
4.3 验证 pgvector 写入
SELECT id, collection, dimension FROM kb_chunks ORDER BY id DESC LIMIT 5;上传一份小文档后,这里应该出现新记录。如果一直为空,回到第 5 节排查向量引擎绑定。
4.4 验证 MCP 工具加载
kubectl -n lab logs deploy/lab-agent | grep -E 'MCPManager|Registered tools|knowledge_'成功时能看到服务器 kb 连接成功和工具数量,比如 22 个工具。如果看到transport closed或 0 个工具,按第 5 节逐项排查。
5. 本篇常见错排查
这一节按故障层组织,每层给出症状、根因和修复动作。
5.1 嵌入配置断桥:配置从未被使用
症状:文档卡 processing,vLLM 零请求,models 表里 embedding 记录的 base_url 为空。
根因:配置源和消费方之间没有桥。Agent 侧有/model-config接口,但业务侧从不调用;业务侧只读缓存里的参数,而缓存是从 DB 重建的,只写缓存不写 DB 必丢。
修复动作:
1. 业务启动时调用 Agent 的 /model-config,UPSERT 到 DB 参数表并镜像到缓存 2. rebind 直接读缓存最新值,不读可能陈旧的内存缓存 3. 启动顺序:先同步配置,再 rebind 4. 检索服务加 SSRF 白名单,允许内网向量/LLM 地址验证:日志出现“已从 agent 同步 kb_models”,models 表出现新 embedding 记录且 base_url 指向 vLLM 地址。
5.2 向量引擎 nil panic:哨兵字面量
症状:配置通了、切块成功,但入库在估算存储大小时 panic,重试耗尽,文档卡 processing。
根因:知识库的 vector_store_id 被写成哨兵字面量__env_pgstore__。校验层放行,解析层不认,查不到真实 store 后返回错误,调用方吞掉错误带着 nil 引擎继续,解引用就 panic。
修复动作:
UPDATE knowledge_bases SET vector_store_id = NULL WHERE vector_store_id = '__env_pgstore__';同时在代码里对引擎创建失败显式判空,标记 failed 并写 error_message,不再 panic。
验证:新建知识库上传文档,越过估算存储大小,vLLM 收到POST /v1/embeddings。
5.3 MCP server 起不来:命令、版本、架构三连
症状:对话报“无法访问知识库”,日志连接服务器 kb 失败: transport closed,0 个 knowledge 工具。
根因通常是三个叠加:
1. 命令不存在:mcp.json 用 console script,但构建只复制源码没 pip 安装 2. 版本不兼容:MCP SDK 2.0 删了 1.x 的装饰器 3. 原生扩展架构不匹配:amd64 构建机装的 .so,arm64 运行镜像加载不了修复动作:
{ "command": "python3", "args": ["/app/mcp-servers/kb/kb_mcp_server.py"] }pip install "mcp>=1.0.0,<2"原生扩展按目标架构装:
docker run --platform linux/arm64 ... pip install --target=build/mcp-deps docker buildx build --platform linux/arm64 ...验证:日志出现“服务器 kb 连接成功,发现 22 个工具”,crictl查 .so 为aarch64-linux-gnu。
5.4 vLLM 推理超时
症状:嵌入请求偶发超时,批量入库时更明显。
排查顺序:
1. 确认 base_url 指向正确的 vLLM 地址和端口 2. 检查 batch_size 是否过大,先降到 8 或 4 3. 检查 timeout_seconds,批量场景适当放大到 60 4. 确认维度一致,避免服务端反复重试如果单条请求正常、批量超时,多半是 batch_size 和超时设置的问题,不是链路断了。
5.5 维度不匹配
症状:写入 pgvector 报维度错误,或检索结果异常。
处理:把 embedding 配置维度、pgvector collection 维度、vLLM 原生输出维度三者对齐到同一个值。已有文件的知识库不允许直接换 embedding 模型,需要清空文件或新建知识库。
6. 继续用 TaoToken 统一通道做验证
排查完成后,建议把验证动作固定成日常检查。模型通道用模型对话页面快速确认:
https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=rag_runbookKey 管理在控制台:
https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=rag_runbook接入字段对照文档:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=rag_runbook长期跑编码或 Agent 任务,用 Coding Plan 更省心:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=rag_runbook最后留一个我踩过的坑:构建机架构和运行架构不一致时,带原生扩展的 Python 依赖必须按运行架构装。Go 靠 GOARCH 交叉编译能解决,Python 的 .so 没有等价物,要么在目标架构环境里装,要么交叉拉对应 wheel。这一条在 MCP server 起不来的时候,往往是最容易被忽略的第三层原因。