rateLimit + forward + extract:限流、转发与回写 本节摘要:本节覆盖八步管道的中后段——执行段(rateLimit 限流、forward 转发)与收尾段的第一步(extract 回写)。rateLimit 用 TPM/QPM 滑窗防止失控,forward 把注入后的请求转发给真正的 LLM 并清理/补回头部,extract 把这次对话回写成 skill 与 L0 喂给抽取 Pipeline。这三步让请求「受控地执行、安全地转发、并沉淀成记忆」。 一、rateLimit:TPM/QPM 滑窗限流 注入完成后,转发前,先过限流。
本节摘要:本节覆盖八步管道的中后段——执行段(rateLimit 限流、forward 转发)与收尾段的第一步(extract 回写)。rateLimit 用 TPM/QPM 滑窗防止失控,forward 把注入后的请求转发给真正的 LLM 并清理/补回头部,extract 把这次对话回写成 skill 与 L0 喂给抽取 Pipeline。这三步让请求「受控地执行、安全地转发、并沉淀成记忆」。
注入完成后,转发前,先过限流。限流用 TPM(每分钟 token)+ QPM(每分钟请求)两个滑窗:
滑窗限流原理 时间窗口(每分钟): 当前分钟已用 token / 请求数 ↓ ├─ TPM 超限? → 拒绝或排队 ├─ QPM 超限? → 拒绝或排队 └─ 都未超 → 放行,转发 「滑窗」:窗口随时间滑动,不是固定的「整点重置」 → 比固定窗口更平滑,避免边界突发
| 限流维度 | 防的问题 |
|---|---|
| TPM(token/分钟) | 防成本失控(LLM 按 token 收费) |
| QPM(请求/分钟) | 防频率失控(防滥用/防 DDoS) |
关键概念:限流不只是「防滥用」,更是「防成本失控」。LLM 按 token 收费,如果没有 TPM 限制,一个失控的 Agent 可能在几分钟内烧掉大量费用。TPM 限流让成本可控,这是生产部署的必要保障。第 12 章会讲限流与计费的配置。
过了限流,forward 把注入后的请求转发给真正的 LLM。这一步有个细节——头部(header)的处理:
forward 的头部处理 转发前: ├─ 清理:去掉代理层用的内部头部(如 x-tdai-user-key) │ (这些是代理内部用的,不该传给 LLM) ├─ 补回:加上 LLM 需要的认证头部 │ (用代理层 .env 里的真正 LLM 密钥) └─ 转发给真正的 LLM 返回时: └─ LLM 答复原路返回,代理层可能再加工(如 sanitize)
| 头部处理 | 为什么 |
|---|---|
| 去掉内部头部 | 不泄露代理内部信息给 LLM |
| 加 LLM 认证 | LLM 要的是真正的密钥,非代理密钥 |
| 答复加工 | 可能做 sanitize 清洗(第 9 章讲) |
⚠️ 注意:forward 看似简单(就是转发),但头部处理是安全关键——若把 x-tdai-user-key 误传给 LLM,等于泄露代理密钥;若没正确加 LLM 认证,转发会被 LLM 拒绝。这一步的「细节」决定了系统能否安全正确地工作。
forward 拿到 LLM 答复返回给 Agent 后,extract 步骤把这次对话回写——这是「记忆生长的入口」:
extract 的回写 这次对话(用户问 + Agent答 + 工具调用) ↓ 回写到核心服务: ├─ L0 录制:对话作为 L0 原始上下文保存 │ (即时,第6章) └─ skill 归档:若对话含可复用做法,归档为 skill 候选 ↓ 触发异步抽取 Pipeline: → L0 → L1 抽取去重 → L2/L3 沉淀 → 这次对话成为下次可召回的记忆
| 回写对象 | 内容 |
|---|---|
| L0 | 完整对话(原话保存) |
| skill 候选 | 对话里提炼出的可复用做法 |
extract 的核心价值:让记忆「持续生长」。没有它,系统只消耗记忆(召回)不产生记忆(回写),越用越空。这就是第 2 章反复强调「回写不是可选」的原因——extract 和 forward 放在同等地位,正是因为记忆复利依赖它。
把三步串起来,看它们如何协作完成「请求的执行与沉淀」:
中后段协作 injection 完成(请求已带记忆) ↓ rateLimit:检查 TPM/QPM ├─ 超限 → 拒绝/排队 └─ 未超 → 继续 ↓ forward:清理头部 + 加认证 + 转发 LLM ↓ LLM 返回答复 ↓ 答复返回 Agent(用户拿到答复) ↓ extract:回写对话 → 触发抽取(记忆生长) ↓ report:上报可观测(下一步,第5节讲)
注意一个关键时序:extract 在「答复返回 Agent」之后。也就是说,用户拿到答复不需要等 extract——extract 是答复返回后的后台动作。这保证了「回写不拖慢响应」——用户该多快拿到答复就多快,回写在后台默默做。
💡 技巧:这个时序设计体现了「同步响应用户、异步沉淀记忆」的原则——前半场(准备+执行)同步让用户尽快拿到答复,后半场(回写+上报)异步不阻塞用户。这与第 6 章「同步录 L0、异步炼 L1/L2/L3」是同一个节奏哲学,贯穿全系统。
中后段每步都可能失败,降级策略保证「即使部分失败,用户仍能拿到答复」:
| 失败 | 降级 |
|---|---|
| rateLimit 触发 | 拒绝或排队(让用户稍后重试) |
| forward 失败(LLM 故障) | 返回错误(无法降级,LLM 是核心) |
| extract 失败 | 不影响答复,后台重试回写 |
⚠️ 注意:extract 失败的降级特别重要——回写失败不能让用户拿不到答复。所以 extract 设计成「fire-and-forget」式:触发后不等结果,失败了后台重试。即使某次回写彻底失败(丢了这次记忆),至少用户当时拿到了正确答复。这种「记忆可丢、响应不可丢」的优先级,是面向用户体验的工程取舍。
中后段清楚后,下一节看横切的存储与计费——存储抽象的五后端降级链与 Credit 计费。