优化hash计算,只取前段,避免url路径影响
This commit is contained in:
+39
-13
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import time
|
||||
import hashlib
|
||||
from urllib.parse import urlparse # <--- 新增导入
|
||||
import litellm
|
||||
from litellm.integrations.custom_logger import CustomLogger
|
||||
from litellm.exceptions import ServiceUnavailableError, ContextWindowExceededError
|
||||
@@ -36,7 +37,7 @@ def dprint(msg):
|
||||
log(msg, level="INFO")
|
||||
|
||||
|
||||
dprint("Loading daily_limit.py module v19 (Specific Quotas & Docker Track)...")
|
||||
dprint("Loading daily_limit.py module v20 (Robust Hash Fix)...")
|
||||
|
||||
# ==========================================
|
||||
# Redis 与 限额配置
|
||||
@@ -46,10 +47,10 @@ REDIS_PORT = os.getenv("REDIS_PORT", "6379")
|
||||
REDIS_PASSWORD = os.getenv("REDIS_PASSWORD", None)
|
||||
|
||||
MODEL_QUOTAS = {
|
||||
"deepseek-v3-2-251201:38430740": 1500000,
|
||||
"doubao-seed-1-8-251228:38430740": 14000, # 测试限额
|
||||
"glm-4-7-251222:38430740": 1500000,
|
||||
"doubao-seed-1-8-251228:9fbb42b8": 1500000, # 测试重名
|
||||
"deepseek-v3-2-251201:ba0383d3": 1600000,
|
||||
"doubao-seed-1-8-251228:ba0383d3": 2000, # 测试限额
|
||||
"glm-4-7-251222:ba0383d3": 1800000,
|
||||
"doubao-seed-1-8-251228:d57edef4": 1500000, # 测试重名
|
||||
}
|
||||
|
||||
|
||||
@@ -70,20 +71,44 @@ def clean_model_name(name):
|
||||
|
||||
|
||||
def generate_api_base_hash(api_base):
|
||||
"""
|
||||
生成 api_base 的 Hash,强制忽略 URL 的路径部分。
|
||||
例如:
|
||||
'https://api.com/v1/' -> 'https://api.com'
|
||||
'https://api.com/v3' -> 'https://api.com'
|
||||
两者生成的 Hash 将完全一致。
|
||||
"""
|
||||
if not api_base:
|
||||
return "default"
|
||||
|
||||
# === 新增标准化代码 ===
|
||||
# 1. 去除首尾空格 (strip)
|
||||
# 2. 去除末尾的斜杠 (rstrip('/'))
|
||||
# 这样 '.../v3/' 和 '.../v3' 会生成相同的 Hash
|
||||
normalized_base = api_base.strip().rstrip('/')
|
||||
# ====================
|
||||
try:
|
||||
# 1. 预处理:去空格
|
||||
s = api_base.strip()
|
||||
|
||||
# 2. 解析 URL
|
||||
parsed = urlparse(s)
|
||||
|
||||
# 3. 提取 Scheme 和 Netloc (域名+端口)
|
||||
# 如果解析成功且包含 scheme 和 netloc,则重组
|
||||
if parsed.scheme and parsed.netloc:
|
||||
clean_base = f"{parsed.scheme}://{parsed.netloc}".lower()
|
||||
else:
|
||||
# 兜底:如果不是标准 URL,或者解析失败,尝试简单的去斜杠和小写化
|
||||
# 这种情况比较少见,通常 litellm 会校验 URL 格式
|
||||
clean_base = s.rstrip('/').lower()
|
||||
|
||||
except Exception:
|
||||
# 极端情况下的兜底
|
||||
clean_base = api_base.strip().rstrip('/').lower()
|
||||
|
||||
# 4. 计算 Hash
|
||||
h = hashlib.md5(clean_base.encode()).hexdigest()[:8]
|
||||
|
||||
h = hashlib.md5(api_base.encode()).hexdigest()[:8]
|
||||
if DEBUG_MODE:
|
||||
# Debugging hash mismatch
|
||||
print(f"🔍 [Hash Debug] Base='{api_base}' -> Hash='{h}'", flush=True)
|
||||
# 打印原始值和清洗后的值,方便确认
|
||||
print(f"🔍 [Hash Debug] Base='{api_base}' -> Clean='{clean_base}' -> Hash='{h}'", flush=True)
|
||||
|
||||
return h
|
||||
|
||||
|
||||
@@ -158,6 +183,7 @@ def soft_evict_from_router(target_upstream_model, target_api_base=None):
|
||||
continue
|
||||
|
||||
# Strict api_base matching if provided
|
||||
# ⚠️ 注意:这里比较的是原始字符串,为了确保精准匹配当前运行的实例
|
||||
if target_api_base and current_api_base != target_api_base:
|
||||
continue
|
||||
|
||||
|
||||
+28
-9
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import yaml
|
||||
import hashlib
|
||||
from urllib.parse import urlparse # ✅ 必须导入
|
||||
import re
|
||||
from typing import Dict, Any
|
||||
|
||||
@@ -63,23 +64,38 @@ def clean_model_name(name):
|
||||
|
||||
|
||||
def generate_api_base_hash(api_base):
|
||||
"""
|
||||
[同步更新] 生成 api_base 的 Hash,强制忽略 URL 的路径部分。
|
||||
保持与 daily_limit.py v20 逻辑完全一致。
|
||||
"""
|
||||
if not api_base:
|
||||
return "default"
|
||||
# Logic matches daily_limit.py v18
|
||||
|
||||
# === 新增标准化代码 ===
|
||||
# 1. 去除首尾空格 (strip)
|
||||
# 2. 去除末尾的斜杠 (rstrip('/'))
|
||||
# 这样 '.../v3/' 和 '.../v3' 会生成相同的 Hash
|
||||
normalized_base = api_base.strip().rstrip('/')
|
||||
# ====================
|
||||
try:
|
||||
# 1. 预处理:去空格
|
||||
s = api_base.strip()
|
||||
|
||||
# 2. 解析 URL
|
||||
parsed = urlparse(s)
|
||||
|
||||
return hashlib.md5(api_base.encode()).hexdigest()[:8]
|
||||
# 3. 提取 Scheme 和 Netloc (域名+端口)
|
||||
# 如果解析成功且包含 scheme 和 netloc,则重组
|
||||
if parsed.scheme and parsed.netloc:
|
||||
clean_base = f"{parsed.scheme}://{parsed.netloc}".lower()
|
||||
else:
|
||||
# 兜底:如果不是标准 URL,或者解析失败,尝试简单的去斜杠和小写化
|
||||
clean_base = s.rstrip('/').lower()
|
||||
|
||||
except Exception:
|
||||
# 极端情况下的兜底
|
||||
clean_base = api_base.strip().rstrip('/').lower()
|
||||
|
||||
# 4. 计算 Hash
|
||||
return hashlib.md5(clean_base.encode()).hexdigest()[:8]
|
||||
|
||||
|
||||
def main():
|
||||
print("🔍 Generating Daily Limit Keys from config.yaml...\n")
|
||||
print("🔍 Generating Daily Limit Keys from config.yaml (Robust Mode)...\n")
|
||||
|
||||
# 1. Load Env
|
||||
env_vars = load_env(ENV_FILE)
|
||||
@@ -119,10 +135,13 @@ def main():
|
||||
api_base_raw = litellm_params.get("api_base", "")
|
||||
|
||||
# Resolve env vars for hash generation
|
||||
# ⚠️ 这里非常重要:必须先解析出真实的 URL,再进行 Hash
|
||||
api_base_resolved = resolve_env_var(api_base_raw, env_vars)
|
||||
|
||||
# Generate components
|
||||
clean_upstream = clean_model_name(upstream_model)
|
||||
|
||||
# 使用同步后的 Hash 逻辑
|
||||
base_hash = generate_api_base_hash(api_base_resolved)
|
||||
|
||||
# Generate final key
|
||||
|
||||
Reference in New Issue
Block a user