DeepSeek Harness 中使用商汤deepseek v4 flash 的 429 限流排查与解决

记一次 DeepSeek V4 Flash 在 DeepSeek Harness 中的 429 限流排查与解决

背景

最近在使用 DeepSeek Harness (DSH) 搭建 AI Agent 工作流,模型用的是商汤 SenseNova 平台提供的 deepseek-v4-flash。使用过程中频繁遇到请求超时/失败,一开始以为是网络问题,结果仔细一看错误信息,发现另有玄机。

现象

Agent 在执行任务时,经常卡住很长时间,然后报错。从 DSH 的日志中可以看到类似这样的记录:

重试延迟:8515ms
失败原因:429: {"message":"inference tpm exhausted","type":"invalid_request_error","code":"429001"}

关键信息:

  • HTTP 429 — 不是超时,是限流(Rate Limit)
  • 错误码 429001 — 这是 SenseNova 网关的限流标识
  • 错误消息 inference tpm exhaustedTPM(Tokens Per Minute,每分钟 Token 配额)用尽了
  • 重试延迟 8515ms(约 8.5 秒)— SenseNova 网关要求等待这么久之后才能重试

根本原因分析

1. 什么是 TPM?

TPM = Tokens Per Minute,即每分钟能处理的 Token 数量上限。这是 API 网关对每个用户/每个 API Key 设置的硬性配额限制。当你在短时间内发送的请求累积 Token 数超过这个配额时,网关就会返回 429 Too Many Requests

2. 为什么 deepseek-v4-flash 特别容易撞墙?

查看 DSH 的配置:

deepseek-v4-flash:
  apiKeyEnv: DEEPSEEK_V4_FLASH_API_KEY
  api: openai-completions
  baseURL: https://token.sensenova.cn/v1
  models:
    - id: deepseek-v4-flash
      name: deepseek-v4-flash
      contextWindow: 1048576  # 100万 token 上下文!

"Flash" 系列模型的设计定位是高吞吐、低延迟、低成本,因此网关对这类模型的 TPM 配额通常设置得更低。再加上它宣称的 contextWindow 高达 1,048,576 tokens(100万),每次请求的输入可能非常大。

3. Agent 的工作模式加剧了问题

DSH 的 Agent 在单个 turn 内的工作流程大致是:

用户提问
  → Agent 调用工具(如 pwsh、read、grep 等)
  → 工具返回结果
  → Agent 再次请求模型处理结果
  → 又调用另一个工具
  → 工具返回结果
  → Agent 再次请求模型...

每次模型请求,输入 Token = 系统提示词 + 全部历史对话 + 当前工具结果,上下文越来越长。在密集的工具调用场景下,几分钟内就能把 TPM 配额打满。

4. 重试延迟 8515ms 的由来

DSH 内置了 dsh-llm-retry 模块来处理模型请求失败。它的行为是:

  1. 收到 429 错误后,检查 provider 是否返回了 Retry-After 延迟
  2. 如果 provider 返回的延迟值不超过配置的 maxDelayMs(默认 10000ms),则直接使用 provider 返回的延迟
  3. SenseNova 返回了 8515ms,小于 10000ms,所以 DSH 直接等待 8.5 秒后重试

默认的重试策略是:

  • maxRetries: 5 次
  • initialDelayMs: 500ms
  • maxDelayMs: 10000ms(10秒)
  • jitterRatio: 0.1

如果网关返回的 Retry-After 超过 10 秒,normal 模式就会直接放弃重试。

解决方案

1. 自定义 retryPolicy

~/.dsh/settings.yaml 中给 deepseek-v4-flash provider 添加自定义重试策略:

llm-pi-ai:
  providers:
    deepseek-v4-flash:
      apiKeyEnv: DEEPSEEK_V4_FLASH_API_KEY
      api: openai-completions
      baseURL: https://token.sensenova.cn/v1
      models:
        - id: deepseek-v4-flash
          name: deepseek-v4-flash
          contextWindow: 1048576
        # ... 其他模型
      retryPolicy:
        mode: normal
        maxRetries: 8              # 默认 5 → 提高到 8
        backoff:
          initialDelayMs: 1000     # 默认 500ms → 提高到 1s
          maxDelayMs: 60000        # 默认 10s → 提高到 60s
          jitterRatio: 0.2         # 默认 0.1 → 增加抖动

关键改动:

  • maxRetries: 8 — 从默认 5 次提高到 8 次,给更多机会
  • maxDelayMs: 60000 — 从默认 10 秒提高到 60 秒,即使网关要求等 30 秒也能接受
  • initialDelayMs: 1000 — 首次退避从 500ms 提高到 1s,减少不必要的快速重试

2. 注意事项:retryPolicy 是 provider 级,不是 model 级

dsh-llm-pi-ai 的代码中,retryPolicyprovider 路由级 的设置,同一个 provider 下的所有模型共享同一份重试策略。如果你需要不同模型用不同策略,需要把它们拆成独立的 provider 路由。

配置会在下一次请求时立即生效,无需重启 DSH 服务。

原理:DSH 重试机制的工作流程

模型请求失败
  → 触发 agent/request-error 事件
  → dsh-llm-retry 拦截
  → 检查 retryPolicy 是否存在
  → 检查失败 code 是否在 retryableCodes 中(RATE_LIMIT 在列表内)
  → 检查是否超过 maxRetries
  → 计算退避延迟
    → 如果 provider 返回了 Retry-After 且 ≤ maxDelayMs → 使用 provider 的延迟
    → 否则使用指数退避:initialDelayMs × 2^retry
  → 追加 llm/retry 事件(含 retryId、延迟、失败原因)
  → 等待延迟时间
  → 追加 llm/retry-started 事件
  → 返回 { kind: "retry" }
  → 循环重新发送请求

经验总结

  1. HTTP 429 不等于网络超时 — 看到 429 先看错误消息,tpm exhausted 说明是配额问题
  2. Flash 模型 TPM 配额通常更低 — 选择模型时要考虑它的限流特性,尤其是 Agent 密集调用的场景
  3. DSH 的 retryPolicy 配置是解决限流的正确方式 — 不要试图修改代码,配置就能搞定
  4. 配置实时生效settings.yamlllm-pi-ai 分节在每次请求时重新读取,改完就能用
  5. 如果限流仍然严重,考虑换模型 — 同一个 provider 下 sensenova-6.7-flash-lite 的 context window 更小(262K),单次请求消耗更少 Token,可能更不容易触发限流

记录于 2026 年,使用 DeepSeek Harness 作为 AI Agent 框架的日常踩坑。

posted @ 2026-08-20 17:32  口嗨养生博  阅读(217)  评论(0)    收藏  举报