feat: add configurable account selection strategies

Refactor account selection into a strategy pattern with three options:
- Sticky: cache-optimized, stays on same account until rate-limited
- Round-robin: load-balanced, rotates every request
- Hybrid (default): smart distribution using health scores, token buckets, and LRU

The hybrid strategy uses multiple signals for optimal account selection:
health tracking for reliability, client-side token buckets for rate limiting,
and LRU freshness to prefer rested accounts.

Includes WebUI settings for strategy selection and unit tests.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Badri Narayanan S
2026-01-18 03:48:43 +05:30
parent 973234372b
commit 5ae19a5b72
31 changed files with 2721 additions and 353 deletions

View File

@@ -237,6 +237,18 @@ window.translations.zh = {
defaultCooldownDesc: "当 API 未提供重置时间时的备用冷却时间。",
maxWaitThreshold: "最大等待阈值",
maxWaitDesc: "如果所有账号的限流时间超过此阈值,立即返回错误而非等待。",
// 错误处理调优
errorHandlingTuning: "错误处理调优",
rateLimitDedupWindow: "限流去重窗口",
rateLimitDedupWindowDesc: "当多个请求同时触发限流时,防止并发重试风暴。",
maxConsecutiveFailures: "最大连续失败次数",
maxConsecutiveFailuresDesc: "触发扩展冷却前允许的连续失败次数。",
extendedCooldown: "扩展冷却时间",
extendedCooldownDesc: "达到最大连续失败后应用的冷却时长。",
capacityRetryDelay: "容量重试延迟",
capacityRetryDelayDesc: "模型容量耗尽(非配额)时重试前的延迟。",
maxCapacityRetries: "最大容量重试次数",
maxCapacityRetriesDesc: "容量耗尽时在切换账号前的最大重试次数。",
saveConfigServer: "保存配置",
serverRestartAlert: "配置已保存至 {path}。部分更改可能需要重启服务器。",
changePassword: "修改 WebUI 密码",
@@ -329,4 +341,17 @@ window.translations.zh = {
// mustBeAtMost: "{fieldName} must be at most {max}",
// cannotBeEmpty: "{fieldName} cannot be empty",
// mustBeTrueOrFalse: "Value must be true or false",
// Account Selection Strategy translations
accountSelectionStrategy: "账户选择策略",
selectionStrategy: "选择策略",
strategyStickyLabel: "固定 (缓存优化)",
strategyRoundRobinLabel: "轮询 (负载均衡)",
strategyHybridLabel: "混合 (智能分配)",
strategyStickyDesc: "保持使用同一账户直到被限速。最适合提示词缓存。",
strategyRoundRobinDesc: "每次请求轮换到下一个账户。最大吞吐量。",
strategyHybridDesc: "基于健康度、令牌和新鲜度的智能选择。",
strategyUpdated: "策略已更新为: {strategy}",
failedToUpdateStrategy: "更新策略失败",
invalidStrategy: "选择了无效的策略",
};