初始化空白分支文件

This commit is contained in:
root
2026-01-28 14:55:06 +08:00
commit f77f7ba6de
5 changed files with 905 additions and 0 deletions
+153
View File
@@ -0,0 +1,153 @@
import os
import yaml
import hashlib
import re
from typing import Dict, Any
# ==========================================
# 🛠️ 配置
# ==========================================
CONFIG_FILE = "config.yaml"
ENV_FILE = ".env"
def load_env(env_path: str) -> Dict[str, str]:
"""读取 .env 文件并返回字典"""
env_vars = {}
if not os.path.exists(env_path):
print(f"⚠️ Warning: {env_path} not found. Env var substitution might fail.")
return env_vars
with open(env_path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#"):
continue
try:
key, value = line.split("=", 1)
env_vars[key.strip()] = value.strip().strip('"').strip("'")
except ValueError:
continue
return env_vars
def resolve_env_var(value: str, env_vars: Dict[str, str]) -> str:
"""
处理环境变量替换,支持以下两种格式:
1. ${VAR_NAME} - 标准格式
2. os.environ/VAR_NAME - LiteLLM 特有格式
"""
if not isinstance(value, str):
return value
# 1. 处理 os.environ/VAR_NAME 格式
if value.startswith("os.environ/"):
var_name = value.replace("os.environ/", "")
return env_vars.get(var_name, os.getenv(var_name, value))
# 2. 处理 ${VAR_NAME} 或 $VAR_NAME 格式
pattern = re.compile(r"\$\{?([A-Z0-9_]+)\}?")
def replace_match(match):
var_name = match.group(1)
# 优先从 .env 读取,其次从系统环境变量读取
return env_vars.get(var_name, os.getenv(var_name, match.group(0)))
return pattern.sub(replace_match, value)
def clean_model_name(name):
if not name:
return ""
return name.replace("openai/", "").replace("azure/", "").replace("anthropic/", "")
def generate_api_base_hash(api_base):
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('/')
# ====================
return hashlib.md5(api_base.encode()).hexdigest()[:8]
def main():
print("🔍 Generating Daily Limit Keys from config.yaml...\n")
# 1. Load Env
env_vars = load_env(ENV_FILE)
# 2. Load Config
if not os.path.exists(CONFIG_FILE):
print(f"❌ Error: {CONFIG_FILE} not found!")
return
try:
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
config = yaml.safe_load(f)
except Exception as e:
print(f"❌ Error parsing yaml: {e}")
return
model_list = config.get("model_list", [])
if not model_list:
print("⚠️ No models found in config.yaml")
return
results = []
seen_keys = set()
# Table Header
# Model Alias | Upstream Model | API Base (Env/URL) | Generated Key
header = f"{'Model Name (Alias)':<25} | {'Upstream Model':<30} | {'API Base (Env/URL)':<40} | {'Generated Key'}"
print(header)
print("-" * len(header))
for model in model_list:
litellm_params = model.get("litellm_params", {})
# Get raw values
model_alias = model.get("model_name", "unknown")
upstream_model = litellm_params.get("model", "")
api_base_raw = litellm_params.get("api_base", "")
# Resolve env vars for hash generation
api_base_resolved = resolve_env_var(api_base_raw, env_vars)
# Generate components
clean_upstream = clean_model_name(upstream_model)
base_hash = generate_api_base_hash(api_base_resolved)
# Generate final key
final_key = f"{clean_upstream}:{base_hash}"
# Deduplicate
if final_key in seen_keys:
continue
seen_keys.add(final_key)
# Truncate api_base_raw if it's too long for display
display_api_base = api_base_raw
if len(display_api_base) > 37:
display_api_base = display_api_base[:34] + "..."
print(f"{model_alias:<25} | {clean_upstream:<30} | {display_api_base:<40} | {final_key}")
results.append(f'"{final_key}": 1500000')
print("\n📋 [Copy & Paste into daily_limit.py MODEL_QUOTAS]:")
print("-" * 50)
print("MODEL_QUOTAS = {")
print(",\n".join(f" {item}" for item in results))
print("}")
print("-" * 50)
if __name__ == "__main__":
main()