1. 从一次检索质量事故说起:为什么RAG工程会需要一个网关层
先讲个真实的场景。上个月我们内部做了一次RAG知识库的压测,当时检索接口的 recall 指标一直表现不错,top-5命中率在85%左右,看起来一切正常。但线上用户反馈却完全不是一回事——大量提问返回的内容驴唇不对马嘴,有人问报销流程,系统答出来的是差旅标准,有人问合同审批节点,模型一本正经地开始解释法律条款。
问题出在哪?后来排查发现,我们的RAG链路是散装拼起来的:Embedding模型用的是一套,生成模型用的是另一套,知识库按业务线拆了十几个目录,但代码里全是硬编码的调用关系。某个目录的索引更新后,对应的路由配置忘了改,结果语义检索阶段就跑偏了。
这个事给了我一个很直接的教训:RAG项目的工程瓶颈,往往不在检索质量本身,而在检索之外的那一整条服务化链路。模型怎么选、知识库怎么路由、上下文怎么组装、请求怎么鉴权、缓存怎么命中、日志怎么追踪——这些乱七八糟的问题,不是靠调一个embedding模型的参数能解决的。于是我开始认真考虑一个问题:RAG服务化,是不是也该有一个"网关层"?
这就是我和MAI Gateway打交道的起点。实话说,一开始我对"AI网关"这个品类是有点怀疑的,总觉得是蹭概念的东西。但真正把一个开源网关接进RAG链路之后,我发现它解决的恰恰是纯检索算法派系最看不上的那些"脏活累活",而这些活不干,项目就是上不了生产。
这篇文章就基于我们实际的落地过程,聊聊AI网关和RAG结合的真实价值、配置细节、踩坑记录,以及哪些场景下"接入网关"是合理决策,哪些场景纯属给自己加戏。
2. MAI Gateway的架构定位:它替RAG链路干了哪些事
MAI Gateway本质上是一个模型接入与流量治理层,放在RAG项目里,它介于"应用层"和"模型/知识库"之间。如果你画过RAG的架构图,传统的画法是:用户请求 → 检索器 → 上下文组装 → LLM → 回答。加上网关之后,链路就变成:用户请求 →MAI Gateway→ 检索器/模型池 → 回答。
这一层多做出来的事,主要有四类。
第一类是模型路由。RAG服务里通常不止一个模型在干活——查询改写可能用一个小模型,Embedding可能用另一个,生成阶段往往又要换一个参数量更大的模型。没有网关的时候,这些切换逻辑散落在业务代码里,每个调用方都得自己维护模型列表和切换策略。MAI Gateway把这些收敛成路由规则之后,上层应用只需要请求一个逻辑上的服务名,比如"rag-generate",网关根据配置决定实际打到哪个模型上。
第二类是知识库路由。这个点一开始我没想到,实际用了才发现价值极大。RAG项目一旦有多个知识域(比如HR政策库、技术文档库、财务制度库),就面临一个问题:用户的问题属于哪个库?甚至一个问题需不需要同时查多个库?网关层可以基于模型/语义分类的结果,把请求路由到不同的RAG后端,或者做并行聚合。这比在业务代码里写if-else要优雅得多,而且规则变更不需要重新发版。
第三类是语义缓存。这个值得单独说,后面我会给一组真实数据。网关在请求入口处做语义相似度匹配,命中缓存就直接返回历史答案。对RAG场景来说,企业内部知识问答的重复率远比你想象的高——同一个报销问题一个月被问几百次,每次都跑一遍检索+生成,烧的都是钱和延迟。
第四类是统一治理。鉴权、限流、审计日志、调用量统计、失败重试、超时控制,所有和"服务治理"相关的能力,集中放在网关层做。没有网关的时候,这些功能等于每个接入方各做各的,最后一定是千疮百孔的。
有一类观点认为,这些东西自己做也就一两周的事,没必要引一个新组件。我的真实感受是:一两周做出来的和经过生产验证的,差距主要在异常处理和边界逻辑上。限流策略什么时候触发降级?模型超时之后重试会不会导致请求堆积?这些细节自己写很容易翻车,属于典型的"看着简单做起来脏"的活。
3. 落地配置:多模型池与知识库路由的接入逻辑
我们接入MAI Gateway的核心目标,是打通两条路由链:模型池路由和知识库路由。以下是我们最终落地的配置思路,结合的是MAI Gateway的provider模型管理机制。
3.1 Provider配置:把模型池抽象成可切换的上游
第一步先把所有模型统一挂到网关上。我们的模型池里有三组模型:一个轻量模型做意图识别和查询改写,一个开源Embedding模型做向量化,一个商用大模型做生成。每组模型可能有多个实例(比如不同部署区域、不同版本),统一在网关里定义成provider。
配置层面大概长这样(简化后的伪配置):
providers: - name: embedding-main type: openai_compatible base_url: http://llm-cluster.internal/v1 api_key_env: EMBEDDING_API_KEY models: - name: bge-m3 max_tokens: 8192 priority: 1 - name: llm-generate type: openai_compatible base_url: http://llm-cluster.internal/v1 api_key_env: GENERATE_API_KEY models: - name: deepseek-chat max_tokens: 4096 priority: 1 - name: qwen-plus max_tokens: 4096 priority: 2注意,这里的priority不是负载均衡,而是故障转移顺序。我们遇到过商用模型服务抖动导致超时,网关自动把请求切到备用的开源模型上,虽然回答质量略有下降,但至少服务没断。这个能力在RAG场景里特别重要——知识问答系统的可用性直接影响业务信任,你不能让用户三天两头碰到"服务异常"。
3.2 路由规则:把"知识库选择"变成网关能力
知识库路由是我们这次落地的重头戏。我们的知识域拆成了6个独立RAG服务,每个服务管理自己的向量库和检索逻辑。网关层需要做的是:根据请求内容,决定打到哪个RAG后端,或者多个后端并行查。
设计思路是这样的:网关前面加一个"路由分类器"(通常是一个轻量模型调用),先把用户问题分类到对应的知识域,然后网关按分类结果做路由。这样做的收益很明显——知识域的调整不再需要修改上层应用的代码,分类规则和路由规则的改动都收敛在网关配置里。
配置示意:
router: - name: hr-policy classification: ["hr", "policy", "benefits"] target: http://rag-svc-hr.internal/v1/retrieve - name: tech-docs classification: ["tech", "api", "troubleshooting"] target: http://rag-svc-tech.internal/v1/retrieve - name: finance classification: ["finance", "invoice", "travel"] target: http://rag-svc-finance.internal/v1/retrieve这里最考验设计的是多域并行场景。实际使用中,不少问题天然跨域——比如"报销技术培训的差旅费",既涉及财务制度,又涉及培训政策。我们最终的方案是网关支持一次请求携带多个target,并行调用再聚合上下文。代价是响应时间会拉长一些,但对比串行检索,体验提升非常明显。
3.3 一个很容易忽略的透传参数问题
接入过程中我踩过一个比较隐蔽的坑:RAG服务需要接收一些自定义参数(比如用户所属部门、知识库版本号、检索top-k值),网关默认不感知这些字段,如果你的配置没做透传映射,后端RAG服务拿不到这些关键上下文,检索结果就是错的。
MAI Gateway支持通过header或请求体的meta字段透传自定义参数。我们在每个RAG服务里都加了department_id和kb_version两个必填参数,最初网关汇聚层没配置透传,结果HR库的问答一直返回错误政策。排查了半天才发现,网关把这两个字段剥离了。
所以建议接入时第一件事就是梳理清楚:你的下游RAG服务依赖哪些自定义参数?在网关的API配置里逐个映射好,别等上了生产再排查。
4. 语义缓存:让重复检索不再烧token和延迟
RAG项目上线后,成本大头往往不在模型推理本身,而在检索+生成的重复执行。企业内部知识问答的提问模式高度重复,尤其业务类问题——报销标准、年假规则、软件安装流程。如果每个问题都走全套RAG链路,既是浪费,也是风险(每次生成的内容可能还不一样)。
4.1 缓存命中率比你想的高
我们观察到一组数据:上线语义缓存一个月后,缓存命中率稳定在38%~42%。也就是说,线上将近四成的请求根本不需要触发检索和生成,直接在网关层秒回。
这个数据很能说明问题。企业知识库不像C端闲聊,问来问去就是那些业务场景,语义缓存的收益是实打实的。而且缓存不只是省钱——平均响应时延从2.1秒降到了280毫秒,用户体感的提升非常明显。
4.2 相似度阈值是调参重点
MAI Gateway的语义缓存,核心机制是把输入问题向量化,和历史问题做相似度匹配。这里有一个很重要的参数:缓存命中相似度阈值。
阈值设置低了(比如0.80),很多语义相近但实际答案不同的问题会被错误命中,返回陈旧答案。阈值设置高了(比如0.97),缓存形同虚设,能命中的只有完全一样的问题。
我们最终的设置是0.92,同时叠加了一个小技巧:业务ID参与缓存键计算。比如"报销标准"这个问题,针对不同城市、不同职级,答案完全不同。如果只按问题文本做相似度匹配,A城市的答案可能被B城市的人命中。所以我们在缓存键里加上了department_id和city等业务因子,让缓存更精确。
4.3 失效策略:知识库更新后缓存怎么办
这是语义缓存最容易翻车的地方。知识库内容不是静态的——政策一更新,旧答案必须立刻作废。我们最初用固定TTL(比如24小时),结果政策调整之后,有用户当天仍然拿到旧答案,体验很糟糕。
后来我们做了两件事:
- 关键知识域(HR、财务)的缓存TTL缩短到30分钟,接受一定的重复计算成本,换取及时性;
- 知识库索引更新时,主动调用网关的缓存清理接口,针对该知识域的所有缓存键做精确失效。
注意,精确失效比全量清理好得多。全量清理会让大量高频问题瞬间回源,造成检索服务压力陡增,我们实际经历过一次,RAG后端的P99延迟直接翻了一倍。
语义缓存的价值一句话总结:它把RAG的"计算力开销"变成了"存储开销",而存储比算力便宜得多。如果你的RAG项目是以企业内部知识问答为主,这个功能会是ROI最高的一项配置。
5. 权限与审计:RAG服务化之后最容易被忽略的两道坎
RAG服务一旦开放给多个业务方使用,权限问题就绕不过去了。
我们的情况是:公司内部有HR、财务、技术、法务四个部门接入同一个RAG平台,每个部门的知识库只允许本部门员工访问。起初在无网关架构下,权限校验散落在每个RAG服务的业务代码里——每个服务各写各的鉴权逻辑,有的校验、有的不校验,混乱程度肉眼可见。
5.1 网关层做统一鉴权的好处
MAI Gateway支持基于API Key或JWT的请求级鉴权。我们把所有接入方的身份认证统一收口到网关层,上层RAG服务只管检索,不关心"这个用户能不能查这个库"。
配置思路很直接:
- 每个业务方分配独立的API Key,绑定一个角色;
- 角色和知识域做权限映射,比如HR角色只有
hr-policy域的访问权限; - 网关鉴权不通过直接返回403,RAG服务根本收不到请求。
这个设计最大的价值是可审计。谁在什么时间查了哪个知识库,网关层全部留痕。以前出个权限事故查半天日志,现在一条命令就能拉出来。
5.2 三种租户隔离方案对比
这是我们在设计阶段纠结过的地方。多业务方共用一个网关,知识库的隔离粒度应该怎么做?整理一下供参考:
| 隔离方案 | 做法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 共享库+权限过滤 | 一个向量库,检索结果按权限过滤 | 实现简单,索引易维护 | 过滤不及时可能泄露语义关联信息 | 各业务方知识重叠度高 |
| 独立库+网关路由 | 每知识域独立向量库,网关按身份路由 | 隔离彻底,检索结果天然隔离 | 跨域检索要设计聚合逻辑 | 业务方知识域边界清晰 |
| 独立网关实例 | 每部门一套独立网关+RAG部署 | 完全隔离,故障域最小 | 运维成本高,网关能力重复建设 | 安全合规要求极高 |
我们选的是第二种,独立库+网关路由。原因很简单:内部知识域边界清晰,且跨域检索的需求确实存在。完全隔离的第三套方案,适合那些有外部合规压力的场景,内部系统用起来太重。
5.3 操作审计日志里的几个坑
日志这块有几句实在话。网关的访问日志默认记录的是请求路径和时间,这对RAG场景远远不够。你必须额外记录几个关键维度:
- 请求的业务上下文(部门、工号、目标知识库);
- 实际路由到哪个RAG服务和模型(排查答案异常时这个信息能救命);
- 缓存是否命中(复盘成本优化时靠这个);
- 响应token数和时延(省钱和调优的基础数据)。
不把这些维度提前配好,后面做成本分析、质量复盘的时候,你会发现数据根本对不上,那才叫被动。
6. 可观测性改造:从"检索没结果"到"一眼定位问题"
RAG项目的排查难度,业内懂的人都深有体会。一个回答质量差的问题,可能是检索阶段的问题,可能是上下文组装的问题,也可能是模型生成的问题。没有好的观测手段,排查全靠猜。
接入MAI Gateway后,我们顺手做了一套基于trace的RAG观测链路,这个提升比预期大得多。
6.1 把RAG链路的四段耗时拆开看
一个完整的RAG请求,在网关视角下可以分为四个阶段:路由分类耗时、检索耗时、上下文组装耗时、模型生成耗时。没有网关时,这些阶段散落在不同服务里,数据根本串不起来。
网关接入后,每个请求自动生成一条trace,四个阶段的耗时一目了然。我们因此发现了一个此前始终定位不到的延迟问题:检索本身只要300ms,但整体响应却要2秒。拆开一看,问题出在下游Embedding服务的排队等待上——该服务在高峰期并发能力不足,请求排队的耗时占了1.2秒。这个结论在无网关架构下需要跨三个团队对指标才能找出来,现在一条trace记录就能说明白。
6.2 检索质量维度也要埋点
除了性能指标,我们还在网关层埋了三个检索质量相关的指标,这几个指标值得推荐给所有做RAG的人:
- 检索命中率(hit rate):top-5里面有多少真正的有效结果;
- 引用采用率(citation utilization):最终回答里,实际引用到的检索片段占比;
- 无效检索率:检索返回了结果但最终回答完全没用到的情况。
后两个指标的统计口径很依赖网关层的trace数据——每个请求都要记录"检索返回了哪些片段"以及"生成请求实际带上了哪些片段"。对照这两个数据,就能定量评估链路里的损耗。比如我们发现某些查询改写规则会把问题改得偏离原意,导致检索结果看似相关、实际无用,正是靠这两个指标的异常波动暴露出来的。
6.3 基于网关指标做近实时监控面板
MAI Gateway本身暴露Prometheus指标,我们基于这些指标做了一个简易看板,核心面板就三块:
- 流量与错误率(网关入口的请求量、错误率、4xx/5xx比例);
- 延迟分解(路由/检索/生成各阶段P50/P95耗时);
- 缓存命中率变化趋势。
实践中的体会是,不要一上来就做一个大而全的观测平台,先保证三块核心面板可用,已经能解决90%的线上问题定位需求。
7. 下一站:Agentic RAG场景下的网关诉求
最后聊点延伸的。最近"Agentic RAG"这个概念很热,我们也在实验把RAG从单轮问答升级成多轮任务。这个场景下,网关的定位又变了——它不再只是请求分发和治理层,更接近一个会话级调度器。
原因在于,Agentic RAG的任务链路很长:用户提出目标 → Agent规划子任务 → 每个子任务可能需要查询不同的知识库 → 结果不够还要补充检索 → 最终汇总生成。这个过程中,网关要处理的不再是单个请求,而是一个有状态的会话流。具体诉求包括:会话级别的上下文保持、子任务之间的循环检测、长时间运行的请求是否被网关超时中断等。
我们实测过程中发现,常见的网关对同步请求处理得很完善,但Agent场景下很多环节属于异步长任务——一个Agent要在不同RAG服务之间来回取数,单次请求可能持续数十秒甚至几分钟。这时候网关的超时配置、连接池大小、任务状态同步机制都会成为瓶颈。这块我们还在摸索,目前的策略是Agent任务单独走一条网关通道,配置更宽松的超时和重试策略,避免影响常规问答的稳定性。
如果你也在考虑Agentic RAG的方案,建议提前把"网关是否需要支持长会话状态"这个问题想清楚,不要等Agent跑到一半才发现请求被网关切断了,那排查起来真的会怀疑人生。
说几个我在整个落地过程中最值钱的体会。
第一,接入网关不是架构上的华丽变身,它是治理能力的集中化。RAG项目能不能上生产,不取决于检索算法多先进,而取决于那些没人愿意干的脏活有没有人管——鉴权、限流、缓存、超时、审计、观测,哪块缺了都会在生产环境咬你一口。
第二,MAI Gateway这类项目的配置看似简单,真正花时间的是梳理你自己的链路依赖。如果你连自己下游有哪几个模型、哪几个知识库、各自依赖什么参数都说不清楚,接什么网关都白搭。工具永远是放大你的思路,不是替你产生思路。
最后一个小技巧:接入网关后,把所有RAG后端的健康检查都挂到网关的统一健康检查接口上,我们用一个外部监控工具每30秒探测一次,任何后端服务出现异常,网关会在流量调度上自动摘除它。这个机制让我们的RAG服务从"经常被用户投诉超时"变成了"几乎无感知地自动恢复",成本只是几行配置。这种小细节,比调一大把这个参数那个参数实用得多。