Files

45 lines
1.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""多 Provider 自动 failover(Hermes 融合:源自 error_classifier / credential_pool 思路)。
当主 Provider 的错误类型属于「换一家就能好」的类别(认证失败/限流/连接/超时/
模型不存在/余额不足)时,自动切到下一个启用的 Provider 重试一次;
模型不存在的用目标 Provider 的默认模型。
"""
from __future__ import annotations
from sqlmodel import Session, select
from .models import ModelProvider
# 这些错误换 Provider 有意义;auth/balance 属于账号问题,换一家确实能好
FAILOVER_KINDS = frozenset({
"auth", "rate_limit", "connection", "timeout", "model_not_found", "balance",
})
def failover_candidates(session: Session, current_provider_id: int) -> list[ModelProvider]:
"""按 id 升序返回其他启用的 Provider(排除当前)。"""
rows = session.exec(select(ModelProvider).order_by(ModelProvider.id)).all()
return [p for p in rows
if p.id != current_provider_id and getattr(p, "enabled", False)]
def should_failover(kind: str) -> bool:
return kind in FAILOVER_KINDS
def failover_target(session: Session, current_provider_id: int,
current_model: str) -> tuple[ModelProvider, str] | None:
"""选一个 failover 目标:(Provider, 模型)。优先沿用同名模型,否则用其默认模型。"""
for provider in failover_candidates(session, current_provider_id):
models = list(provider.models or [])
if current_model in models:
return provider, current_model
if provider.default_model and provider.default_model in models:
return provider, provider.default_model
if models:
return provider, models[0]
return None
__all__ = ["FAILOVER_KINDS", "failover_candidates", "failover_target", "should_failover"]