很多人看完 RAG 概念文章,动手时照样卡住:文档切完不知道丢哪,检索回了东西模型却不用,接口调通了答得还是离谱。这篇不讲原理大道理,只按「数据进去—检索出来—拼进提示词—DeepSeek 生成」这条线,给一份能照着做的步骤清单和出错时的排查顺序,适合已经能跑通一次 API 调用的开发者。
不少人把 RAG 想复杂了,以为要上向量数据库集群、上多路召回、上 rerank,结果动手第一天就卡在文档切完不知道丢哪。其实核心就一条线:数据进去、检索出来、拼进提示词、DeepSeek 生成。这四段每一段都能单独跑、单独打印中间结果,出了问题才定位得到。
这篇写给已经能跑通一次 API 调用的开发者。不讲原理大道理,只给能照着抄的步骤,以及答不准时该按什么顺序往回查。前置条件很简单:一个能发请求的 DeepSeek 对话接口、一个 embedding 模型、一套能存向量的东西(本地文件也行)。
先把最小链路跑通,别一上来做架构
最小链路就是四段式:文档清洗切块、向量化入库、按问题检索 top-k、拼进 prompt 交给 DeepSeek 生成。先把这四段串成一个能端到端跑的脚本,哪怕检索是暴力遍历、存储是本地 json,只要能把一条问题走完并拿到回答,骨架就立住了。之后再换向量库、加 rerank,都是替换零件,不是重搭房子。
- 圈定测试集先挑几十份文档,再固定几个测试问题,答案必须能在这些文档里找到。这个测试集就是后面所有改动的标尺,别用它来调参,用它来看改动有没有变好。
- 确认接口能通先用一次普通对话调用确认 base URL、Key、返回格式都对。走中转的话,配置口径到 /guides/relay-first-call-verification 对一遍,别把接口问题误判成检索问题。
- 每段留中间产物原始切块、向量、召回结果、最终 prompt,四样都能单独打印出来。跑一次就把这四样存下来,后面排查全靠它。
- 先闭环再优化链路不通之前不要加 rerank、不要上多路召回。一个能跑通但粗糙的闭环,比一个跑不通的精致设计有用得多。
切片与向量化:决定后面能不能检索到
切块是整条链路里最容易被糊弄、也最容易出问题的环节。优先按语义边界切:标题、段落、列表项。固定字数切会把一句话拦腰截断,检索到时上下文是断的。块太大检索不精准,块太小上下文不完整,没有标准答案,只能靠抽检判断。
要分清两件事:DeepSeek 负责生成,向量侧得另选 embedding 模型。这两个模型能力不挂钩,生成模型好不代表向量质量好。embedding 选型可以到 /embeddings 对照当时的模型资料,重点看它对中文和长文本的表现,别只看参数。
| 检查项 | 判断标准 | 不适用情况 |
|---|---|---|
| 切块边界 | 抽 5 条看,语义是否完整、有没有半句话 | 表格、代码类文档按行切更合适 |
| 块大小 | 同一问题能否在单块里找到答案 | 跨多段才能回答的问题,需要容忍更大块 |
| 来源标记 | 每块带路径和标题,能追回原文 | 纯临时问答场景可以简化 |
| 入库前抽检 | 手工看几十条切块结果 | 文档量极少时直接全看 |
检索与拼提示词:让模型真的用上资料
检索回来一堆片段,模型却答得像没看见,问题通常出在提示词结构上。用户问题和召回片段要分开标清楚,片段编号要标上,并明确要求只依据给出的片段作答、找不到就说找不到、答案里带上片段编号。这样模型不会把资料里的句子当成指令执行,也方便你回查它到底用了哪条。
- top-k 先设保守值,再按答非所问的比例慢慢调,别默认开很大把上下文塞满。
- 提示词里写死「找不到就说找不到」,减少模型硬编答案。
- 给片段编号并要求答案引用编号,生成结果可追溯。
- 把问题表述里的代词补全,指代不清时检索基本不会准。
- 判断是没召回还是召回了没用上,参考 /guides/rag-retrieval 的召回思路对照。
答不准时的排查顺序:从后往前查
答不准时最忌讳上来就调检索参数。正确的顺序是从后往前:先看最终拼进 prompt 的片段里到底有没有答案。不含,问题在检索;含了但模型答歪,问题在生成。这一刀切下去,后面的排查范围就小了一半。
| 现象 | 先查哪 | 常见原因 |
|---|---|---|
| 片段里没有答案 | 切块质量、向量模型、top-k、相似度阈值 | 切太碎、向量模型对中文弱、阈值过高 |
| 片段有答案但答偏 | 提示词约束、上下文长度、问题表述 | 没要求依据片段、超出上下文被截断、问题有歧义 |
| 请求直接报错 | 接口层:401、403、超时 | Key 配置、base URL、网络和限流,与检索无关 |
| 答案部分正确部分离谱 | prompt 里片段排序和编号 | 相关片段被挤到末尾、模型只看了开头 |
接口层的错误要单独归一类,先确认请求本身通不通,再去调检索参数。很多人花几小时调相似度阈值,最后发现是 Key 配错了。
上线前要盯的两个数:延迟和调用量
一次问答通常包含一次向量化和一次生成,延迟和成本要分开估。把检索和生成分段计时,哪段慢就改哪段,别整体归因到「模型慢」。价格口径别凭印象,到 /official-api/providers/deepseek 和 /tools/token-price-calculator 核对当时的数字,再决定要不要压缩上下文长度。
- 分段计时:检索耗时、生成耗时、总耗时分三列记录。
- 控制拼进 prompt 的片段总量,上下文越长生成越慢、越贵。
- 并发上来前先设计好限流和排队,参考 /guides/429-concurrency-backoff。
- 缓存高频问题的检索结果,能省掉重复的向量化开销。
- 上线前跑一轮真实问题的响应时间抽样,别只看测试集。
常见问题
DeepSeek 自己带向量检索能力吗,还是得另配?
生成和检索是拆开的两件事。DeepSeek 负责最后那段根据资料作答,文档向量化和召回要你自己用 embedding 模型加向量库完成,所以链路里必须单独考虑向量侧选型和入库。
为什么检索明明返回了片段,模型还是答非所问?
通常是提示词没约束住,或者片段里混了无关内容把模型带偏。先检查最终拼进去的 prompt,确认答案确实在片段里,再收紧「只依据片段作答、没有就直说」这类要求,并适当降一点 top-k。
搭建阶段用官方接口还是走中转?
看你的网络和预算情况。官方接口口径最干净,排查问题少一层变量;中转方便但要先验证通不通。切换通道前按 /guides/relay-switch-api-verification 测一遍,别把通道问题和 RAG 逻辑混在一起查。