优化hash计算,只取前段,避免url路径影响
This commit is contained in:
+39
-13
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from urllib.parse import urlparse # <--- 新增导入
|
||||||
import litellm
|
import litellm
|
||||||
from litellm.integrations.custom_logger import CustomLogger
|
from litellm.integrations.custom_logger import CustomLogger
|
||||||
from litellm.exceptions import ServiceUnavailableError, ContextWindowExceededError
|
from litellm.exceptions import ServiceUnavailableError, ContextWindowExceededError
|
||||||
@@ -36,7 +37,7 @@ def dprint(msg):
|
|||||||
log(msg, level="INFO")
|
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 与 限额配置
|
# Redis 与 限额配置
|
||||||
@@ -46,10 +47,10 @@ REDIS_PORT = os.getenv("REDIS_PORT", "6379")
|
|||||||
REDIS_PASSWORD = os.getenv("REDIS_PASSWORD", None)
|
REDIS_PASSWORD = os.getenv("REDIS_PASSWORD", None)
|
||||||
|
|
||||||
MODEL_QUOTAS = {
|
MODEL_QUOTAS = {
|
||||||
"deepseek-v3-2-251201:38430740": 1500000,
|
"deepseek-v3-2-251201:ba0383d3": 1600000,
|
||||||
"doubao-seed-1-8-251228:38430740": 14000, # 测试限额
|
"doubao-seed-1-8-251228:ba0383d3": 2000, # 测试限额
|
||||||
"glm-4-7-251222:38430740": 1500000,
|
"glm-4-7-251222:ba0383d3": 1800000,
|
||||||
"doubao-seed-1-8-251228:9fbb42b8": 1500000, # 测试重名
|
"doubao-seed-1-8-251228:d57edef4": 1500000, # 测试重名
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -70,20 +71,44 @@ def clean_model_name(name):
|
|||||||
|
|
||||||
|
|
||||||
def generate_api_base_hash(api_base):
|
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:
|
if not api_base:
|
||||||
return "default"
|
return "default"
|
||||||
|
|
||||||
# === 新增标准化代码 ===
|
try:
|
||||||
# 1. 去除首尾空格 (strip)
|
# 1. 预处理:去空格
|
||||||
# 2. 去除末尾的斜杠 (rstrip('/'))
|
s = api_base.strip()
|
||||||
# 这样 '.../v3/' 和 '.../v3' 会生成相同的 Hash
|
|
||||||
normalized_base = api_base.strip().rstrip('/')
|
# 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:
|
if DEBUG_MODE:
|
||||||
# Debugging hash mismatch
|
# 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
|
return h
|
||||||
|
|
||||||
|
|
||||||
@@ -158,6 +183,7 @@ def soft_evict_from_router(target_upstream_model, target_api_base=None):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Strict api_base matching if provided
|
# Strict api_base matching if provided
|
||||||
|
# ⚠️ 注意:这里比较的是原始字符串,为了确保精准匹配当前运行的实例
|
||||||
if target_api_base and current_api_base != target_api_base:
|
if target_api_base and current_api_base != target_api_base:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
+28
-9
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
import yaml
|
import yaml
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from urllib.parse import urlparse # ✅ 必须导入
|
||||||
import re
|
import re
|
||||||
from typing import Dict, Any
|
from typing import Dict, Any
|
||||||
|
|
||||||
@@ -63,23 +64,38 @@ def clean_model_name(name):
|
|||||||
|
|
||||||
|
|
||||||
def generate_api_base_hash(api_base):
|
def generate_api_base_hash(api_base):
|
||||||
|
"""
|
||||||
|
[同步更新] 生成 api_base 的 Hash,强制忽略 URL 的路径部分。
|
||||||
|
保持与 daily_limit.py v20 逻辑完全一致。
|
||||||
|
"""
|
||||||
if not api_base:
|
if not api_base:
|
||||||
return "default"
|
return "default"
|
||||||
# Logic matches daily_limit.py v18
|
|
||||||
|
|
||||||
# === 新增标准化代码 ===
|
try:
|
||||||
# 1. 去除首尾空格 (strip)
|
# 1. 预处理:去空格
|
||||||
# 2. 去除末尾的斜杠 (rstrip('/'))
|
s = api_base.strip()
|
||||||
# 这样 '.../v3/' 和 '.../v3' 会生成相同的 Hash
|
|
||||||
normalized_base = api_base.strip().rstrip('/')
|
|
||||||
# ====================
|
|
||||||
|
|
||||||
|
# 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():
|
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
|
# 1. Load Env
|
||||||
env_vars = load_env(ENV_FILE)
|
env_vars = load_env(ENV_FILE)
|
||||||
@@ -119,10 +135,13 @@ def main():
|
|||||||
api_base_raw = litellm_params.get("api_base", "")
|
api_base_raw = litellm_params.get("api_base", "")
|
||||||
|
|
||||||
# Resolve env vars for hash generation
|
# Resolve env vars for hash generation
|
||||||
|
# ⚠️ 这里非常重要:必须先解析出真实的 URL,再进行 Hash
|
||||||
api_base_resolved = resolve_env_var(api_base_raw, env_vars)
|
api_base_resolved = resolve_env_var(api_base_raw, env_vars)
|
||||||
|
|
||||||
# Generate components
|
# Generate components
|
||||||
clean_upstream = clean_model_name(upstream_model)
|
clean_upstream = clean_model_name(upstream_model)
|
||||||
|
|
||||||
|
# 使用同步后的 Hash 逻辑
|
||||||
base_hash = generate_api_base_hash(api_base_resolved)
|
base_hash = generate_api_base_hash(api_base_resolved)
|
||||||
|
|
||||||
# Generate final key
|
# Generate final key
|
||||||
|
|||||||
Reference in New Issue
Block a user