模拟来自 OpenAI API 的错误

概览
目标: 测试 OpenAI API 错误处理
时间: 10 分钟
Plugins:GenericRandomErrorPlugin、 RetryAfterPlugin
先决条件:设置开发代理

在应用中使用 OpenAI API 时,应测试应用如何处理 API 错误。 开发人员代理允许使用 GenericRandomErrorPlugin 模拟任何 OpenAI API 上的错误。 借助 RetryAfterPlugin,开发代理还会检查应用是否在再次调用 API 前按 Retry-After 标头中的时间等待。

小窍门

通过在命令提示符 devproxy config get openai-throttling中运行来下载此预设。

在项目文件夹中,创建名为 的新文件。 在代码编辑器中打开该文件。

在plugins数组中创建一个新对象,该数组引用GenericRandomErrorPlugin。 定义 Dev Proxy 要监视的 OpenAI API URL,并添加对插件配置的引用。

文件: devproxyrc.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/rc.schema.json",
  "plugins": [
    {
      "name": "GenericRandomErrorPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
      "configSection": "openAIAPI"
    }
  ],
  "urlsToWatch": [
    "https://api.openai.com/*"
  ]
}

添加RetryAfterPlugin并创建插件配置对象,以向GenericRandomErrorPlugin提供错误响应的位置以及要使其失败的请求百分比。

文件: devproxyrc.json(完整配置)

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/rc.schema.json",
  "plugins": [
    {
      "name": "RetryAfterPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll"
    },
    {
      "name": "GenericRandomErrorPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
      "configSection": "openAIAPI"
    }
  ],
  "urlsToWatch": [
    "https://api.openai.com/*"
  ],
  "openAIAPI": {
    "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.schema.json",
    "errorsFile": "openai-errors.json",
    "rate": 90
  }
}

Caution

在您的配置文件中,于 RetryAfterPlugin 之前添加 GenericRandomErrorPlugin。 如果在之后添加它,GenericRandomErrorPlugin会在RetryAfterPlugin检查请求之前使请求失败。

在同一文件夹中,创建 openai-errors.json 文件。 此文件包含 Dev Proxy 在使请求失败时从中选择的错误响应。 它们与 OpenAI API 返回的错误匹配:

Status error.code 它模拟的内容
429 rate_limit_exceeded 您的应用已达到其每分钟令牌数(TPM)或每分钟请求数(RPM)限制。
429 slow_down 你的应用的请求速率增长过快。
429 credit_balance_exhausted 你的组织没有剩余预付费额度。 重试无济于事。
503 server_is_overloaded 模型暂时负载过高。

有关这些错误的详细信息,请参阅 OpenAI 文档中的 错误代码 。

文件: openai-errors.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.errorsfile.schema.json",
  "errors": [
    {
      "request": {
        "url": "https://api.openai.com/*"
      },
      "responses": [
        {
          "statusCode": 429,
          "headers": [
            {
              "name": "content-type",
              "value": "application/json; charset=utf-8"
            },
            {
              "name": "Retry-After",
              "value": "@dynamic"
            }
          ],
          "body": {
            "error": {
              "message": "Rate limit reached for gpt-4.1 in organization org-K7hT684bLccDbBRnySOoK9f2 on tokens per min (TPM): Limit 30000, Used 30000, Requested 1200. Please try again in 2.4s. Visit https://platform.openai.com/settings/organization/limits to learn more.",
              "type": "tokens",
              "param": null,
              "code": "rate_limit_exceeded"
            }
          }
        },
        {
          "statusCode": 429,
          "headers": [
            {
              "name": "content-type",
              "value": "application/json; charset=utf-8"
            },
            {
              "name": "Retry-After",
              "value": "@dynamic"
            }
          ],
          "body": {
            "error": {
              "message": "Rate limit reached for gpt-4.1 in organization org-K7hT684bLccDbBRnySOoK9f2 on requests per min (RPM): Limit 500, Used 500, Requested 1. Please try again in 120ms. Visit https://platform.openai.com/settings/organization/limits to learn more.",
              "type": "requests",
              "param": null,
              "code": "rate_limit_exceeded"
            }
          }
        },
        {
          "statusCode": 429,
          "headers": [
            {
              "name": "content-type",
              "value": "application/json; charset=utf-8"
            },
            {
              "name": "Retry-After",
              "value": "@dynamic"
            }
          ],
          "body": {
            "error": {
              "message": "Your request rate increased too quickly. Reduce your request rate and increase it gradually.",
              "type": "rate_limit_error",
              "param": null,
              "code": "slow_down"
            }
          }
        },
        {
          "statusCode": 429,
          "headers": [
            {
              "name": "content-type",
              "value": "application/json; charset=utf-8"
            }
          ],
          "body": {
            "error": {
              "message": "Your organization has no prepaid credits remaining. Add credits to continue using the API. For more information on this error, read the docs: https://developers.openai.com/api/docs/guides/error-codes.",
              "type": "insufficient_quota",
              "param": null,
              "code": "credit_balance_exhausted"
            }
          }
        },
        {
          "statusCode": 503,
          "headers": [
            {
              "name": "content-type",
              "value": "application/json; charset=utf-8"
            }
          ],
          "body": {
            "error": {
              "message": "The requested model is temporarily overloaded. Please try again later.",
              "type": "service_unavailable_error",
              "param": null,
              "code": "server_is_overloaded"
            }
          }
        }
      ]
    }
  ]
}

该值 @dynamic 设置 Retry-After 标头,并指示 RetryAfterPlugin 跟踪应用必须等待多长时间。 响应 credit_balance_exhausted 没有 Retry-After 标头,因为等待无法修复它。

在项目文件夹中启动开发代理:

devproxy

当你的应用调用 OpenAI API 时,Dev Proxy 会使用openai-errors.json文件中的随机错误使 90% 的请求失败。 如果你的应用在Retry-After标头中指定的时间之前再次调用 API,RetryAfterPlugin会报告该情况并对请求进行限流。

检查你的应用是否:

  • 等待发生rate_limit_exceeded或slow_down错误后的Retry-After时间。
  • 在发生 credit_balance_exhausted 错误后停止调用 API,而不是重试。
  • 在发生 server_is_overloaded 错误后进行延迟重试,并在重试次数用完时显示一条清晰的消息。

详细了解 GenericRandomErrorPlugin。

另请参阅