diff --git a/volc_limit_sync.py b/volc_limit_sync.py index c485672..125068a 100644 --- a/volc_limit_sync.py +++ b/volc_limit_sync.py @@ -95,7 +95,6 @@ REGION = "cn-beijing" # Daemon Config BUFFER = 300000 # User requested 30w buffer CHECK_INTERVAL = 10 -THRESHOLD = 300000 # 前置闸门预留量:请求开始判定 usage + reserve >= limit 即 429。 # reserve 优先取本次请求自带 max_tokens(真实上限,零采集损失), @@ -572,6 +571,14 @@ def restore_blocked_models(): clean_model = clean_model_name(upstream_model) original_api_base = backup.get("api_base") + # 只恢复监控内的火山条目(clean + 端点 hash),与 soft_evict/请求闸门口径一致, + # 避免按 clean 名误恢复同名不同端点(如 newapi 渠道)被踢的条目 + if MONITORED_MODEL_PAIRS and ( + clean_model, + generate_api_base_hash(params.get("api_base", "")), + ) not in MONITORED_MODEL_PAIRS: + continue + # Check Quota # Need current usage to calculate dynamic limit correctly? # get_effective_limit handles fetching usage if None passed. @@ -697,6 +704,14 @@ def startup_audit(): if not clean_model: continue + # 只审计监控内的火山模型(clean + 端点 hash),与请求闸门口径一致, + # 避免误判同名非监控渠道(如 newapi 别名模型)超限而误踢 + if MONITORED_MODEL_PAIRS and ( + clean_model, + generate_api_base_hash(api_base), + ) not in MONITORED_MODEL_PAIRS: + continue + # 2. Check Limit & Usage # We use effective limit logic which checks both static and dynamic effective_limit = get_effective_limit(clean_model, api_base) @@ -1233,6 +1248,28 @@ def _maybe_trigger_daily_consume(): log(f"❌ 消耗任务调度失败: {e}", level="ERROR") +def compute_sync_interval(min_remaining, is_idle): + """按最小正剩余余额 + 空闲状态计算同步间隔(秒)。""" + # 余额分档退化:余额驱动的"慢速档"已无意义(日返还模型下余额高 = 常态, + # 返还/过期/消耗随时发生,慢同步只制造检测延迟窗口)。 + # 仅保留"低余额加密":<10万 5min、<30万 10min(返还解锁/扣费检测要紧); + # ≥30万 统一 30min,不再细分。真正的慢同步 = is_idle(base×4,上限 60min)。 + if min_remaining < 100_000: + base_interval = 300 # 紧急 5 minutes + elif min_remaining < 300_000: + base_interval = 600 # 低余额 10 minutes + else: + base_interval = 1800 # 常规 30 minutes + + if is_idle: + interval = min(base_interval * 4, 3600) + if interval < 300: + interval = 300 + else: + interval = base_interval + return interval + + def active_monitor_loop(): # Config Discovery MONITORED_MODELS = discover_monitored_models() @@ -1267,7 +1304,7 @@ def active_monitor_loop(): "Starting Active Monitor Loop (Safety-Margin + Idle Awareness) / 正在启动主动监控循环 (安全余量 + 空闲感知)...", flush=True, ) - print(f"Buffer / 缓冲: {BUFFER}, Threshold / 阈值: {THRESHOLD}", flush=True) + print(f"Buffer / 缓冲: {BUFFER}", flush=True) while True: try: @@ -1318,41 +1355,10 @@ def active_monitor_loop(): (now - idle_start_time) > IDLE_THRESHOLD ) - # Dynamic Interval - # Logic: Adjust intervals based on distance from BUFFER - # User specified thresholds (Distance < X): - # < 10w -> 2min (120s) - # < 30w -> 5min (300s) - # < 50w -> 10min (600s) - # < 80w -> 30min (1800s) - # < 100w -> 60min (3600s) - # >= 100w -> 60min (3600s) - - # Determine Base Sync Interval based on global risk (Optimized for Hourly Latency) - # Since API updates are hourly, frequent polling provides no new info and wastes resources. - # We trust Redis Usage for real-time gating. - # < 100k -> 5 min (Emergency check for the update moment) - # < 300k -> 10 min - # < 500k -> 20 min - # < 800k -> 45 min - # >= 800k -> 60 min - # 余额分档退化:余额驱动的"慢速档"已无意义(日返还模型下余额高 = 常态, - # 返还/过期/消耗随时发生,慢同步只制造检测延迟窗口)。 - # 仅保留"低余额加密":<10万 5min、<30万 10min(返还解锁/扣费检测要紧); - # ≥30万 统一 30min,不再细分。真正的慢同步 = is_idle(下方 base×4,上限 60min)。 - if global_min_remaining < 100_000: - base_interval = 300 # 紧急 5 minutes - elif global_min_remaining < 300_000: - base_interval = 600 # 低余额 10 minutes - else: - base_interval = 1800 # 常规 30 minutes - - if is_idle: - current_sync_interval = min(base_interval * 4, 3600) - if current_sync_interval < 300: - current_sync_interval = 300 - else: - current_sync_interval = base_interval + # Dynamic Interval: 按最小正剩余余额分档(见 compute_sync_interval) + current_sync_interval = compute_sync_interval( + global_min_remaining, is_idle + ) # ===================================================== # 🚀 Per-Model Burst Detection (精细化突发流量检测) @@ -1566,8 +1572,10 @@ def active_monitor_loop(): mode_icon = "🚨 低余额模式" else: mode_icon = "ℹ️ 常规模式" + # 用本次同步后的新 Min Rem 重算,避免"旧 interval + 新 Min Rem"混打误导 + next_interval = compute_sync_interval(global_min_remaining, is_idle) print( - f"{mode_icon}: 下一次同步 {current_sync_interval}s (Min Rem: {int(global_min_remaining):,}, {'空闲' if is_idle else '活跃'}) / 同步间隔 {current_sync_interval}s", + f"{mode_icon}: 下一次同步 {next_interval}s (Min Rem: {int(global_min_remaining):,}, {'空闲' if is_idle else '活跃'}) / 同步间隔 {next_interval}s", flush=True, )