Skip to content

LLM 网关与缓存 ​

在 InterX 项目中,LLM 调用是系统的核心算力来源,也是成本和延迟的主要瓶颈。为了解决这一问题,我们设计了一套完整的 LLM 网关层,基于 LiteLLM 实现统一的多上游路由,并引入双层语义缓存机制,大幅提升系统响应速度。

为什么需要 LLM 网关 ​

InterX 的 RAG 流水线中,一次完整的问答可能涉及多次 LLM 调用:查询改写、路由判断、三层并行回答、ensemble 融合。如果每次都直接请求上游 LLM 服务,会面临三个问题:

  1. 上游服务不稳定 — 单一 LLM 服务故障时整个系统不可用
  2. 成本高昂 — 高频重复问题反复调用 LLM 是浪费
  3. 延迟过高 — 多层 LLM 调用叠加,端到端延迟可达数十秒

因此,我们需要一个统一的 LLM 网关来解决这些问题。

LiteLLM 作为统一网关 ​

我们选择 LiteLLM Proxy 作为网关层,运行在 :4000 端口。它提供了统一的 OpenAI 兼容接口,屏蔽了不同上游 LLM 服务的差异。

多上游路由 ​

系统配置了三个上游 LLM 服务:

  • MiMo — 主力推理模型
  • DashScope — 通义千问系列,承担部分生成和 embedding 任务
  • GPT-5.5 — 作为备用和特定任务的模型

网关采用 simple-shuffle 轮转策略,自动在多个上游之间分配请求。每个上游配置独立的 RPM/TPM 限流,避免某个上游过载。

故障转移机制 ​

当某个上游服务出问题时,网关会自动处理:

  • 失败 1-3 次后标记该端点为不健康状态,冷却 15-30 秒
  • 冷却期间自动将请求路由到其他健康端点
  • drop_params: true 自动丢弃上游不支持的参数,避免兼容性错误

上游评分与探测 ​

网关会对每个上游进行评分:成功 100 分 + 延迟奖励(0-20 分)+ HTTP 状态分。通过 12 轮探测验证路由均匀性,冒烟测试不仅检查 HTTP 状态码,还会验证模型是否实际生成了有意义的响应。

双层语义缓存 ​

这是网关层最核心的设计。在产品客服场景中,用户经常会用不同措辞问同一个问题,比如"怎么开机"和"如何启动"本质上是同一个问题。如果我们每次都调用 LLM,就太浪费了。

第一层:SHA-256 精确匹配(~1ms) ​

当请求到达网关时,首先进行精确匹配:

json.dumps(payload, sort_keys=True) → SHA-256 → Redis GET

将请求的 payload 序列化为 JSON 字符串,计算 SHA-256 哈希值,然后到 Redis 中查找。如果命中,直接返回缓存结果,整个过程大约只需要 1ms。

这一层解决的是完全相同请求的重复调用问题,比如用户刷新页面、重试请求等场景。

第二层:LLM 语义等价判断(~500ms) ​

如果精确匹配没有命中,就进入第二层语义匹配:

  1. 提取最近 6 条消息的摘要(最多 4000 字符)
  2. 从 Redis 的候选列表中取出最多 5 个历史请求
  3. 使用轻量级 LLM(gpt-4o-mini)判断当前请求与候选是否语义等价
  4. 命中条件:hit=true 且 confidence ≥ 0.92

这一层用一个小型 LLM 来判断"怎么开机"和"如何启动"是否等价,虽然耗时约 500ms,但相比重新调用主力 LLM 生成回答(通常需要数秒),仍然快很多。

缓存策略 ​

  • TTL:精确缓存 1 小时过期
  • 候选列表:保留最近 50 条历史请求
  • 写入策略:未命中时,结果同时写入精确缓存和候选列表

缓存命中率 ​

在验证测试中,缓存表现如下:

缓存层级测试数准确率
精确匹配(SHA-256)6100%
语义匹配(LLM 判断)667%

精确匹配零误判;语义匹配对同义改写有效(confidence 达到 0.98),但在跨语言场景下存在一些局限。总体来说,在产品客服这种高频重复问题的场景下,缓存机制能显著降低 API 调用成本和延迟。

Prometheus 监控集成 ​

为了实时掌握网关的运行状态,我们集成了 Prometheus 监控,通过 6 个指标精确区分两种缓存的命中情况。这些指标让我们能够清楚地看到:

  • 精确匹配的命中率和延迟
  • 语义匹配的命中率和延迟
  • 上游各服务的响应时间和错误率
  • 缓存未命中时的回源调用情况

故障容忍与优雅降级 ​

网关层作为所有 LLM 调用的入口,自身的健壮性至关重要。我们设计了多级容错机制:

  1. 上游故障 — 自动轮转到其他健康端点
  2. 网关层故障 — 上层调用直接回退到默认 LLM 端点
  3. 缓存故障 — Redis 不可用时自动降级为无缓存模式,所有请求直接回源

结合整个系统的容错体系:

Dense 检索故障 → 静默降级到纯 BM25
Rerank 故障   → 静默保留融合排序
KG 扩展故障   → 跳过,不影响主流程
路由失败       → 默认走 RAG(保守策略)
回答重试       → 指数退避(1s → 2s),json_object 降级

系统在最极端的故障场景(Dense + Rerank 同时失败)下仍能返回 10 个有效检索结果,12/12 降级测试场景全部通过。

加速路径优先级 ​

整个系统的加速策略按优先级排列:

优先级路径延迟机制
1语义缓存精确匹配~1msSHA-256 → Redis
2语义缓存语义匹配~500ms-2s轻量 LLM 等价判断
3三级并行回答~3-5x 提速ThreadPoolExecutor(3)
4模块级缓存首次加载后零开销BM25 索引 + 语料驻留内存

优先级 1 和 2 直接在网关层拦截,避免了下游整个 RAG 流水线的执行。这种分层加速的设计,让高频问题的响应时间从数十秒降到毫秒级。

小结 ​

LLM 网关层的设计思路其实很简单:能不调用 LLM 就不调用(缓存),必须调用时选择最优路径(路由),出了问题自动切换(容错)。这三层机制叠加在一起,让 InterX 在保持高质量回答的同时,将延迟和成本控制在可接受的范围内。