deepseek rag 本地部署

接入与开发

给要自建的一方讲清本地跑通 DeepSeek RAG 的工程步骤:环境分层、服务编排、超时并发、降级与日志评测,附排查顺序与落地清单。

你可能已经看过 RAG 原理,也知道向量检索大概怎么回事,但真在自己机器或内网服务器上把 DeepSeek 和一套检索链路拼起来,卡住的往往不是概念,而是端口对不对、模型加载不上、检索回来一堆没用的、并发一上来就超时。这篇按工程顺序走一遍:先定组件边界,再逐个验证单点,最后才谈调优。不承诺一次跑通,而是给你一套能自查的对照步骤,出问题时知道先看哪一层。

你可能已经看过 RAG 原理,也知道向量检索大概怎么回事,但真在自己机器或内网服务器上把 DeepSeek 和一套检索链路拼起来,卡住的往往不是概念,而是端口对不对、模型加载不上、检索回来一堆没用的、并发一上来就超时。这篇按工程顺序走一遍:先定组件边界,再逐个验证单点,最后才谈调优。

这里不承诺一次跑通。本地部署的价值在于数据可控、链路可观测,代价是你得自己当运维。所以下面给的是一套能自查的对照步骤:每一段都有最小验证动作,出问题时知道先看哪一层,而不是从头重装一遍。全程涉及的数字(显存占用、单机吞吐、模型规格)都建议到站内对应页面核对当时的情况,别凭印象拍板。

先划清边界:本地 RAG 到底由哪几段组成

本地 RAG 不是一个进程,是五段拼起来的链路:生成模型、嵌入模型、向量库、编排层、接口层。每一段都能独立启动、独立验证,这是后面排查能快起来的前提。很多人一上来写个 docker-compose 全塞进去,结果报错时根本分不清是哪一段挂了,只能一段段拆开重来。

生成模型
负责根据检索到的上下文写答案,本地跑对显存要求最高,通常是决定整机规格的那一段
嵌入模型
把文档和问题转成向量,体积比生成模型小很多,但调用频率高,别忽略它的并发表现
向量库
存向量、做相似度检索,负责过滤和返回候选片段,是检索质量的直接来源
编排层
把「取问题→检索→拼上下文→调模型→返回」串起来,超时、降级、重试逻辑都写在这里
接口层
对外暴露 HTTP 或内部 RPC,负责鉴权、限流、日志埋点,业务方只跟它打交道

接下来要提前写下来的是取舍:哪几段必须留在内网,哪几段可以走外部接口。数据不出内网是常见硬约束,那向量库和嵌入模型基本得本地;生成模型如果显存不够,可以先接外部合规接口,把链路先跑通,之后再换本地。这个取舍最好在动手前落到纸面,不然后面每改一次都要重新纠结。

团队形态建议起步方式主要限制
个人或两人验证全部组件单机跑,先求链路通显存可能只够小规格模型,速度会慢
5 人左右小团队向量库与嵌入本地,生成先接合规接口依赖外部网络,需要处理鉴权和限流
有内网合规要求五段全本地,按访问量规划机器硬件成本和运维投入明显上升

显存和内存够不够,不要凭感觉估。把你手上的卡型号、数量、打算跑的模型规格输进去,到 /models/deploy 按实际硬件算一遍,那里有部署规格与适配提示。算出来差一点,宁可先降规格把链路跑通,也别硬上导致加载到一半失败。

环境准备与服务启动顺序

启动顺序建议从上到下:向量库 → 嵌入模型 → 生成模型 → 编排层 → 接口层。每起一段就验证一段,返回符合预期再进下一步。这个顺序的逻辑是依赖关系:编排层要能连上前面几段,接口层又要能连上编排层,倒过来起只会让你在最后一步同时面对一堆不确定。

  1. 起向量库用官方镜像或包起一个实例,验证方式是往里面写一条测试向量再按相似度查回来,能查到说明存储和检索都正常
  2. 起嵌入模型加载后调一次编码接口,输入一句中文,返回的向量维度符合模型说明即可,顺便记下单次耗时
  3. 起生成模型先发一条最简单的请求(比如让它复述一句话),确认能返回、不报显存错误,再测试长一点的上下文能不能装下
  4. 起编排层用一段写死的检索结果拼进提示词,看整条组装流程能不能跑出答案,这一步先不接真向量库
  5. 起接口层对外发一个请求,确认鉴权、限流、日志都生效,然后做一次从问题到答案的端到端验证

容器还是裸机、端口怎么规划、数据目录挂哪里,这三件事在启动前就该定好,写在对照表里。容器化的好处是依赖隔离,坏处是模型文件挂载和显存透传容易出问题;裸机跑性能直接,但依赖版本容易和系统里别的东西互踩。

启动前要确认的项目常见做法出问题时的典型表现
部署方式容器跑服务,模型文件挂宿主机目录容器内路径找不到模型,启动即退出
端口规划每段一个固定端口,写进配置文件端口被占用,服务起了但连不上
数据目录用绝对路径,挂载前确认权限换目录后相对路径失效,读不到数据
依赖版本锁定版本,别用浮动标签升级某个库后另一段突然报错

这一段的高频坑有三个:依赖版本互踩、端口占用、模型文件写相对路径。前两个靠启动前对照表规避,第三个最隐蔽——你在原目录跑得好好的,一换工作目录就找不到文件。统一改成绝对路径,能省掉很多莫名其妙的报错。踩过的坑建议随手记成清单,换机器或换人接手时直接复用。

资料进库这一段最容易返工

资料进库看起来简单,实际是返工最多的一段。原因是很多人把清洗、切片、向量化揉成一个脚本,出了问题不知道是文本脏、切得不合适,还是编码本身有问题。正确做法是三步分开做,每步的产出都能单独看:清洗完先人工抽查几篇,切片完看片段长度分布,向量化完做一次召回自检。

  • 清洗:去掉页眉页脚、乱码、重复段落,扫描件先做 OCR 再进流程
  • 切片:先粗后细,从较大的块开始试,召回不够再往下切,别一上来就调到最细
  • 向量化:同一批文档用同一个嵌入模型,中途换模型要整批重算
  • 入库:带上来源标识和版本字段,后面做过滤、重跑、溯源都靠它
  • 自检:提一个只有某份文档才有的问题,看能不能召回那份文档

文档类型不同,处理方式也不同。扫描件要先 OCR,表格要么转成结构化文本要么单独走一路检索,代码文件按函数或类切比按固定字数切更合理。把这些分类处理完再统一入库,比混在一起塞进去效果好得多。想看看别人在数据管道上怎么组织工具,可以去 /tools 里的目录翻一翻,挑适合自己的组合。

什么时候这段不用太讲究?语料就几十篇、问题范围也很窄的时候,粗切加简单清洗通常够用。但只要语料上百篇、问题开始细化,切片和清洗的差距就会明显放大,这时候再回头补,返工量比一开始就分开做要大。

检索质量不行,先从这三处查

检索不好用,先别急着换模型或调参数,按三段定位:没召回、召回但排序差、召回了模型没用好。这三种现象的处理方向完全不同,混着调只会越调越乱。判断方法也简单:把检索返回的片段直接打印出来看,就知道卡在哪一段。

现象先查什么常见原因
相关片段根本没返回切片粒度和嵌入模型切片太长淹没关键句,或嵌入模型和语料语言不匹配
返回了但排在后面候选数量和过滤条件过滤条件写太死被卡掉,或候选给太少没轮到对的
片段对了但答案不对提示词和上下文拼接上下文太长被截断,或提示词没要求引用来源

什么时候需要加重排?候选多、噪声大、问题偏细节的时候,加一层重排通常能明显改善排序。什么时候不需要?语料很小、问题宽泛的时候,加重排只会增加延迟,收益有限。重排本身也要占资源,本地跑之前算一下它和生成模型能不能共享显存。

调参必须留对照组,一次只改一个变量,改完记录改了什么、效果往哪边变。今天调切片、明天调提示词、后天换嵌入模型,最后你根本不知道是哪个起了作用。固定一批用例做对照,比凭感觉改靠谱得多。

超时、并发与排队:本地跑最容易忽略的一层

超时别只设一个总超时,要分档:连接超时、单次推理超时、整条链路超时各设一个值。连接超时短一点,快速失败;单次推理给足,别让正常的长回答被误杀;整条链路兜底,防止检索加生成叠加起来卡住。三档分开,排查时才知道是连不上还是算得慢。

并发上限由显存和批处理能力决定。做法是先压测:用递增的并发数打生成接口,观察耗时和显存曲线,找到耗时开始明显上升的那个点,那就是单机能扛的上限。这个数去 /tools/speed-test 做一次实际探测,比自己估更靠谱。

  1. 压测出上限从低并发开始逐步加,记录每个并发档位的平均耗时和显存占用,找出拐点
  2. 设排队机制超过上限的请求进队列等待,不要直接拒绝,也不要无限重试
  3. 配退避策略被限流或超时的请求按倍数退避重试,重试次数设上限,避免打爆机器
  4. 验证效果压测时观察队列长度和超时比例,正常应该是有排队但不大面积超时

离线批量任务可以放宽并发,但要错峰跑,别和在线请求抢同一张卡。这条纪律如果一开始没定,后面在线请求变慢时很难查到是批量任务在后台占资源。反过来,如果业务本身就是纯离线、没人等结果,那超时可以设得宽松些,把机器利用率拉满,这是「不适用在线场景」的一种情况。

降级方案与日志要记哪几个字段

降级要逐级退,不是直接报错。顺序建议是:本地生成不可用 → 换更小的本地模型或外部合规接口 → 只返回检索片段不生成。最后一级虽然体验差,但至少给出了相关信息,比一个错误页有用。每级降级都要在日志里标出来,否则你根本不知道线上有多少请求其实是降级在撑。

  • 请求标识:串起一次请求经过的所有组件,排查时按它搜
  • 耗时拆分:检索多久、生成多久分开记,慢在哪一段一目了然
  • 召回条数:返回了几条片段,为零时直接指向检索环节
  • 是否降级:走了哪一级降级,统计降级比例
  • 失败分类:模型加载失败、超时、检索为空、上下文超长,各对应不同处理

失败原因分类记下来很有用,因为它直接指向动作:模型加载失败要查硬件和路径,超时要查并发,检索为空要查数据管道,上下文超长要查切片和拼接。把这四类分开统计,问题分布一眼就出来。本地部署还有个合规注意点:日志别夹带原文敏感内容,按团队要求脱敏,尤其是答案里可能引用到的片段。

怎么知道自己的 RAG 是好是坏

没有评测的本地部署,改到最后全靠感觉。做法是攒一批固定用例,覆盖三类:能答的、明确答不了的、需要拼多篇才答得全的。每次改动——换模型、调切片、改提示词——都把这批用例跑一遍,对比前后结果。用例不用多,几十条稳定覆盖关键场景就够。

看三类指标:召回有没有拿到对的那段、回答有没有引用来源、拒答是否合理。第二类常被忽略,其实回答里带出来源比答案本身更能说明链路是通的。第三类也很关键,资料里没有的东西,模型应该明确说不知道,而不是编一个。

改动要有版本记录,模型、切片参数、提示词任一项变了都记一笔,配上那次评测的结果。这样下次效果变差时,你能倒回去看是哪次改动引入的。想参考别人的测法,去 /benchmarks/registry 看看它们用哪些方法,但别照搬指标——你的语料特征和别人不一样,挑适合自己场景的那几项。

下一步把你的硬件规格和打算部署的模型规格带上去 /models/deploy 核对一遍,确认显存、内存和部署方式对得上,再开始动手起服务。

出问题时的排查顺序清单

出问题时的第一原则:先确认每一段单独能跑,再从编排层往下逐段断链定位。直接在端到端请求上猜,效率最低。按固定顺序查,比东一榔头西一棒子快得多,也更容易交给别人接手。

  1. 查服务起没起逐个确认五段进程都在、端口都监听,正常表现是每段日志无报错、端口可连通
  2. 查接口通不通直接调各段自己的接口,绕过编排层,正常表现是返回结构完整、耗时在预期内
  3. 查检索有没有结果单独触发一次检索,看返回片段数量和内容,正常表现是能命中相关问题
  4. 查生成有没有拿到上下文看拼接后的提示词里上下文是否完整、有没有被截断
  5. 查整条链路超时端到端发一次请求,看耗时拆分里检索和生成各占多少,定位是哪段拖慢

每一步都有「正常长什么样」的预期,对照着看比盲猜快很多。这套顺序的价值不在步骤本身,而在于它逼你把问题缩小到一段,而不是在一个黑盒里反复重试。每次踩的坑和解决方式记成清单,下次换机器或上新环境能直接复用。

最后提醒一句:本地 RAG 不是一次配好就完事,语料在变、硬件在变、需求也在变,这套分层和验证的思路比任何一次性的配置都更值钱。真要选型或者看别人踩过什么坑,站内的工具目录和评测资料可以当参考,但最终还是要落到你自己机器上跑一遍。

逛逛工具目录部署过程中要挑组件、查工具,可以去 /tools 里按类别翻一翻,省得一个个搜。

常见问题

本地部署 DeepSeek 跑 RAG,一定要有显卡吗?

看你怎么切分。如果生成走外部接口、只把嵌入模型和向量库放本地,普通机器也能起步。如果生成也要本地跑,就得看模型规格和量化档位,具体要吃多少显存去 /models/deploy 按手上的卡算,别照别人配置直接抄。

检索老是召回不相关内容,是模型问题还是资料问题?

先别换模型。按顺序查:切片是不是切断了语义、嵌入模型和语料语言对不对得上、过滤条件有没有写死。这三项排完还不行,再考虑加重排。语料本身质量差、重复多,换什么模型都救不回来。

本地跑的时候并发一高就超时,怎么处理?

先在单机压出一个真实并发上限,再在编排层加排队和退避,超过上限就排队而不是无限重试。同时把超时拆成连接、单次推理、整条链路三档分别设。离线批量任务错峰跑,别和在线请求抢同一张卡。

怎么判断自己这套 RAG 到底能不能用?

攒一批固定用例,按能答、不能答、要多篇拼三类覆盖,每次改动跑一遍,看召回准不准、回答有没有引用、该拒答有没有拒。用例要长期留着,不然调着调着连退步了都发现不了。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。