Telnyx 的 Python 示例将重试与模型回退策略集中到网关,并通过主模型超时验证切换行为。响应头和费用账本共同记录实际服务模型及尝试次数,便于发现 SDK 与网关重试叠加的问题。
AI 模型回退是否有用,取决于应用事后能否回答两个问题:
实际是哪个模型处理了请求?
网关一共尝试了多少次?
客户端的重试循环可能会掩盖这两个答案。应用最终收到了成功响应,但很难还原得到这个响应的过程。SDK 重试还可能与网关重试叠加,产生额外请求,让尝试次数变得具有误导性。
gateway-fallbacks Python 示例将这套容错策略交给 Telnyx AI Gateway。它配置主模型和回退模型,强制让主模型超时,再通过两种方式验证回退结果:
这个示例将管理、推理和观测分开:
Management plane Inference plane
api.telnyx.com/v2/llm_token_gateway llm.telnyx.com/v1
Telnyx account API key scoped token key
POST /token_groups GET /models
POST /token_keys POST /chat/completions
GET /spend/events |
GET /usage/summary v
| gateway retries and fallbacks
+----------------------+----------------+
|
v
Observation: x-ltg-served-model, x-ltg-attempts,
requested_model, model, attempts, cache_hit
管理平面负责 token group、token key、预算和用量报告,使用 Telnyx 账户 API key。
推理平面兼容 OpenAI,只使用为该 group 签发的 token key,因此应用代码不需要持有账户凭据。
示例配置了两个允许使用的模型别名,以及一组回退关系:
allowed_models = ["Kimi-K3", "GLM-5.3-Flash"]
fallbacks = {
"Kimi-K3": ["GLM-5.3-Flash"],
}
retries = {
"max_attempts": 2,
"retry_delay_ms": 250,
"backoff": "exponential",
}
group = client.llm_token_gateway.token_groups.create(
name="gateway-fallbacks-demo",
allowed_models=allowed_models,
fallbacks=fallbacks,
retries=retries,
max_budget=10,
budget_duration="1d",
idempotency_key=f"gateway-fallbacks-group-{uuid.uuid4()}",
).data
group 限定其 key 可以调用哪些模型,并定义发生失败时如何沿回退链切换。示例在发出 API 请求前,也会在本地验证相同的策略限制:
网关也会强制执行这些规则。policy.py 会故意提交一次无效的 max_attempts=9 更新,预期收到 HTTP 400,并且 group 不会被修改。
重试和模型回退由网关负责,因此 OpenAI 客户端会关闭自身的重试行为:
llm = OpenAI(
base_url="https://llm.telnyx.com/v1",
api_key=token_key,
max_retries=0,
)
这一点很关键,因为 SDK 的一次重试会在网关自身的尝试之外,再发起一个新请求。关闭 SDK 重试,才能让响应头、账本记录和计费都围绕同一套重试策略保持一致。
示例区分了两类失败:一类可以确定模型尚未开始处理,另一类则可能已经开始处理。
对于可以确定尚未执行模型工作的失败,例如请求分发前的错误、429 和 529,可以重试同一个模型。
对于处理状态不确定的失败,例如超时、408、500、502、503 和 504,则切换到下一个回退模型,因为原始请求可能已经到达 provider。
因上下文长度超限而被拒绝时,请求直接终止,因为在下一次尝试中发送同样超长的上下文,并不能解决输入问题。
等待 provider 出故障,不是一个实用的测试方案。示例改为构造一个受控的时限竞争场景。
inference.py 向 Kimi-K3 发送流式请求,将首个事件的等待时限设为 1 秒:
result = chat_completion(
token_key,
"Kimi-K3",
build_forced_failure_prompt(),
extra_headers={
"x-ltg-request-timeout": "1000",
"x-ltg-max-attempts": "1",
},
stream=True,
max_tokens=64,
)
生成的输入被刻意设计得很重,约有 22,000 个 token,并包含一个唯一 nonce,避免重复运行时依靠 provider 的 KV 缓存缩短 prefill 时间。目的是让主模型的首个事件无法在 1 秒内到达,而 GLM-5.3-Flash 作为回退模型完成请求。
provider 的延迟会随时间变化,因此示例并不保证一定能触发这种结果。脚本最多尝试 3 次;如果主模型在时限内响应,或者两次模型尝试都超时,脚本都会如实报告。
客户端从原始响应中读取两个响应头:
served_model = raw.headers.get("x-ltg-served-model")
attempts = raw.headers.get("x-ltg-attempts")
成功发生回退时,应当看到:
requested model: Kimi-K3
served model: GLM-5.3-Flash
x-ltg-attempts: 2 or more
SDK 响应中的 model 字段也有用,但网关响应头能在实时请求链路中明确展示路由决策。
下一步读取网关中与已签发 token key 对应的费用事件:
events = client.llm_token_gateway.spend.retrieve_events(
start_date=start_date,
end_date=end_date,
token_key_id=token_key_id,
page_number=1,
page_size=50,
)
for event in events.data:
print(
event.requested_model,
"->",
event.model,
"attempts:",
event.attempts,
"status:",
event.status,
"cache_hit:",
event.cache_hit,
)
当 requested_model 与 model 不同时,账本就提供了与响应头相对应的持久化证据。示例使用左闭右开的 UTC 日期范围和快照分页,即使事件集合发生变化,也能让报告保持可复现。
当账户拥有 llm_token_gateway.usage.read 权限时,GET /usage/summary 还会提供总量及按模型汇总的数据。如果该端点返回 403,示例会将其视为不影响流程继续的警告,因为费用事件账本仍然包含请求级别的证据。
网关支持在请求级别覆盖尝试次数、延迟、退避方式和超时设置:
extra_headers = {
"x-ltg-max-attempts": "1",
"x-ltg-retry-delay": "1000",
"x-ltg-backoff": "exponential",
}
这些控制项可以调整单次请求,而不必改写 token group 的策略。
示例还会将 cache_ttl 更新为 60 秒,并连续发送两次相同的 prompt。网关缓存采用尽力而为的方式,因此脚本不会凭空宣称缓存命中:如果重复请求由缓存提供响应,它会报告 x-ltg-attempts: 0;否则会提示你查看账本中的 cache_hit 字段。
每次更新和删除都遵循以下修改安全模式:
过期的 ETag 会导致请求返回 412,防止一个进程覆盖另一个进程刚刚更新的配置。
克隆仓库并安装锁定版本的依赖:
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/gateway-fallbacks
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
将你的 Telnyx 账户 API key 添加到 .env:
TELNYX_API_KEY=your_telnyx_api_key_here
PRIMARY_MODEL=Kimi-K3
FALLBACK_MODEL=GLM-5.3-Flash
发起网络请求前,先运行本地冒烟测试:
python -m pytest smoke_test.py -v
然后运行这套五步演示:
# Creates the group and key. The key secret is printed once.
python provision.py
export GATEWAY_TOKEN_KEY="<paste the secret>"
python inference.py
python ledger.py
python policy.py
python teardown.py
在线演示会产生真实的推理费用。示例将一天内的最高预算配置为 10 美元,但在自己的账户中运行前,你应该先检查策略。
provision.py 只会将 group 和 key 的 ID 存入 .gateway_state.json,绝不会把 token 密钥写入磁盘。teardown.py 会撤销 token key、删除 group、验证已撤销的 key 收到 HTTP 401,并移除本地状态文件。
这套实用模式并不局限于这两个模型:
这样一来,模型回退就不再只是一个假设,而是运维人员可以在请求期间查看、事后审计的实际行为。
Telnyx AI Gateway 概览
AI Gateway 快速入门
回退与重试控制
AI Gateway 用量报告
如需进一步采取措施,你可以考虑屏蔽此人和/或举报滥用行为。