Spaces:
Sleeping
Sleeping
File size: 15,257 Bytes
a8c0fef |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 |
"""
Configuration constants for the Geminicli2api proxy server.
Centralizes all configuration to avoid duplication across modules.
"""
import os
from typing import Any, Optional
# Client Configuration
# 需要自动封禁的错误码 (默认值,可通过环境变量或配置覆盖)
AUTO_BAN_ERROR_CODES = [401, 403]
# Default Safety Settings for Google API
DEFAULT_SAFETY_SETTINGS = [
{"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_CIVIC_INTEGRITY", "threshold": "BLOCK_NONE"}
]
# Helper function to get base model name from any variant
def get_base_model_name(model_name):
"""Convert variant model name to base model name."""
# Remove all possible suffixes in order
suffixes = ["-maxthinking", "-nothinking", "-search"]
for suffix in suffixes:
if model_name.endswith(suffix):
return model_name[:-len(suffix)]
return model_name
# Helper function to check if model uses search grounding
def is_search_model(model_name):
"""Check if model name indicates search grounding should be enabled."""
return "-search" in model_name
# Helper function to check if model uses no thinking
def is_nothinking_model(model_name):
"""Check if model name indicates thinking should be disabled."""
return "-nothinking" in model_name
# Helper function to check if model uses max thinking
def is_maxthinking_model(model_name):
"""Check if model name indicates maximum thinking budget should be used."""
return "-maxthinking" in model_name
# Helper function to get thinking budget for a model
def get_thinking_budget(model_name):
"""Get the appropriate thinking budget for a model based on its name and variant."""
if is_nothinking_model(model_name):
return 128 # Limited thinking for pro
elif is_maxthinking_model(model_name):
return 32768
else:
# Default thinking budget for regular models
return -1 # Default for all models
# Helper function to check if thinking should be included in output
def should_include_thoughts(model_name):
"""Check if thoughts should be included in the response."""
if is_nothinking_model(model_name):
# For nothinking mode, still include thoughts if it's a pro model
base_model = get_base_model_name(model_name)
return "gemini-2.5-pro" in base_model
else:
# For all other modes, include thoughts
return True
# Dynamic Configuration System - Optimized for memory efficiency
async def get_config_value(key: str, default: Any = None, env_var: Optional[str] = None) -> Any:
"""Get configuration value with priority: ENV > Storage > default."""
# Priority 1: Environment variable
if env_var and os.getenv(env_var):
return os.getenv(env_var)
# Priority 2: Storage system
try:
from src.storage_adapter import get_storage_adapter
storage_adapter = await get_storage_adapter()
value = await storage_adapter.get_config(key)
# 检查值是否存在(不是None),允许空字符串、0、False等有效值
if value is not None:
return value
except Exception as e:
# Debug: print import/storage errors
# print(f"Config storage error for key {key}: {e}")
pass
return default
# Configuration getters - all async
async def get_proxy_config():
"""Get proxy configuration."""
proxy_url = await get_config_value("proxy", env_var="PROXY")
return proxy_url if proxy_url else None
async def get_calls_per_rotation() -> int:
"""Get calls per rotation setting."""
env_value = os.getenv("CALLS_PER_ROTATION")
if env_value:
try:
return int(env_value)
except ValueError:
pass
return int(await get_config_value("calls_per_rotation", 100))
async def get_auto_ban_enabled() -> bool:
"""Get auto ban enabled setting."""
env_value = os.getenv("AUTO_BAN")
if env_value:
return env_value.lower() in ("true", "1", "yes", "on")
return bool(await get_config_value("auto_ban_enabled", False))
async def get_auto_ban_error_codes() -> list:
"""
Get auto ban error codes.
Environment variable: AUTO_BAN_ERROR_CODES (comma-separated, e.g., "400,403")
TOML config key: auto_ban_error_codes
Default: [400, 403]
"""
env_value = os.getenv("AUTO_BAN_ERROR_CODES")
if env_value:
try:
return [int(code.strip()) for code in env_value.split(",") if code.strip()]
except ValueError:
pass
codes = await get_config_value("auto_ban_error_codes")
if codes and isinstance(codes, list):
return codes
return AUTO_BAN_ERROR_CODES
async def get_retry_429_max_retries() -> int:
"""Get max retries for 429 errors."""
env_value = os.getenv("RETRY_429_MAX_RETRIES")
if env_value:
try:
return int(env_value)
except ValueError:
pass
return int(await get_config_value("retry_429_max_retries", 5))
async def get_retry_429_enabled() -> bool:
"""Get 429 retry enabled setting."""
env_value = os.getenv("RETRY_429_ENABLED")
if env_value:
return env_value.lower() in ("true", "1", "yes", "on")
return bool(await get_config_value("retry_429_enabled", True))
async def get_retry_429_interval() -> float:
"""Get 429 retry interval in seconds."""
env_value = os.getenv("RETRY_429_INTERVAL")
if env_value:
try:
return float(env_value)
except ValueError:
pass
return float(await get_config_value("retry_429_interval", 1))
# Model name lists for different features
BASE_MODELS = [
"gemini-2.5-pro-preview-06-05",
"gemini-2.5-pro",
"gemini-2.5-pro-preview-05-06",
"gemini-2.5-flash",
]
def get_available_models(router_type="openai"):
"""
Get available models with feature prefixes.
Args:
router_type: "openai" or "gemini"
Returns:
List of model names with feature prefixes
"""
models = []
for base_model in BASE_MODELS:
# 基础模型
models.append(base_model)
# 假流式模型 (前缀格式)
models.append(f"假流式/{base_model}")
# 流式抗截断模型 (仅在流式传输时有效,前缀格式)
models.append(f"流式抗截断/{base_model}")
# 支持thinking模式后缀与功能前缀组合
for thinking_suffix in ["-maxthinking", "-nothinking", "-search"]:
# 基础模型 + thinking后缀
models.append(f"{base_model}{thinking_suffix}")
# 假流式 + thinking后缀
models.append(f"假流式/{base_model}{thinking_suffix}")
# 流式抗截断 + thinking后缀
models.append(f"流式抗截断/{base_model}{thinking_suffix}")
return models
def is_fake_streaming_model(model_name: str) -> bool:
"""Check if model name indicates fake streaming should be used."""
return model_name.startswith("假流式/")
def is_anti_truncation_model(model_name: str) -> bool:
"""Check if model name indicates anti-truncation should be used."""
return model_name.startswith("流式抗截断/")
def get_base_model_from_feature_model(model_name: str) -> str:
"""Get base model name from feature model name."""
# Remove feature prefixes
for prefix in ["假流式/", "流式抗截断/"]:
if model_name.startswith(prefix):
return model_name[len(prefix):]
return model_name
async def get_anti_truncation_max_attempts() -> int:
"""
Get maximum attempts for anti-truncation continuation.
Environment variable: ANTI_TRUNCATION_MAX_ATTEMPTS
TOML config key: anti_truncation_max_attempts
Default: 3
"""
env_value = os.getenv("ANTI_TRUNCATION_MAX_ATTEMPTS")
if env_value:
try:
return int(env_value)
except ValueError:
pass
return int(await get_config_value("anti_truncation_max_attempts", 3))
# Server Configuration
async def get_server_host() -> str:
"""
Get server host setting.
Environment variable: HOST
TOML config key: host
Default: 0.0.0.0
"""
return str(await get_config_value("host", "0.0.0.0", "HOST"))
async def get_server_port() -> int:
"""
Get server port setting.
Environment variable: PORT
TOML config key: port
Default: 7861
"""
env_value = os.getenv("PORT")
if env_value:
try:
return int(env_value)
except ValueError:
pass
return int(await get_config_value("port", 7861))
async def get_api_password() -> str:
"""
Get API password setting for chat endpoints.
Environment variable: API_PASSWORD
TOML config key: api_password
Default: Uses PASSWORD env var for compatibility, otherwise 'pwd'
"""
# 优先使用 API_PASSWORD,如果没有则使用通用 PASSWORD 保证兼容性
api_password = await get_config_value("api_password", None, "API_PASSWORD")
if api_password is not None:
return str(api_password)
# 兼容性:使用通用密码
return str(await get_config_value("password", "pwd", "PASSWORD"))
async def get_panel_password() -> str:
"""
Get panel password setting for web interface.
Environment variable: PANEL_PASSWORD
TOML config key: panel_password
Default: Uses PASSWORD env var for compatibility, otherwise 'pwd'
"""
# 优先使用 PANEL_PASSWORD,如果没有则使用通用 PASSWORD 保证兼容性
panel_password = await get_config_value("panel_password", None, "PANEL_PASSWORD")
if panel_password is not None:
return str(panel_password)
# 兼容性:使用通用密码
return str(await get_config_value("password", "pwd", "PASSWORD"))
async def get_server_password() -> str:
"""
Get server password setting (deprecated, use get_api_password or get_panel_password).
Environment variable: PASSWORD
TOML config key: password
Default: pwd
"""
return str(await get_config_value("password", "pwd", "PASSWORD"))
async def get_credentials_dir() -> str:
"""
Get credentials directory setting.
Environment variable: CREDENTIALS_DIR
TOML config key: credentials_dir
Default: ./creds
"""
return str(await get_config_value("credentials_dir", "./creds", "CREDENTIALS_DIR"))
async def get_code_assist_endpoint() -> str:
"""
Get Code Assist endpoint setting.
Environment variable: CODE_ASSIST_ENDPOINT
TOML config key: code_assist_endpoint
Default: https://cloudcode-pa.googleapis.com
"""
return str(await get_config_value("code_assist_endpoint", "https://cloudcode-pa.googleapis.com", "CODE_ASSIST_ENDPOINT"))
async def get_auto_load_env_creds() -> bool:
"""
Get auto load environment credentials setting.
Environment variable: AUTO_LOAD_ENV_CREDS
TOML config key: auto_load_env_creds
Default: False
"""
env_value = os.getenv("AUTO_LOAD_ENV_CREDS")
if env_value:
return env_value.lower() in ("true", "1", "yes", "on")
return bool(await get_config_value("auto_load_env_creds", False))
async def get_compatibility_mode_enabled() -> bool:
"""
Get compatibility mode setting.
兼容性模式:启用后所有system消息全部转换成user,停用system_instructions。
该选项可能会降低模型理解能力,但是能避免流式空回的情况。
Environment variable: COMPATIBILITY_MODE
TOML config key: compatibility_mode_enabled
Default: True
"""
env_value = os.getenv("COMPATIBILITY_MODE")
if env_value:
return env_value.lower() in ("true", "1", "yes", "on")
return bool(await get_config_value("compatibility_mode_enabled", True))
async def get_oauth_proxy_url() -> str:
"""
Get OAuth proxy URL setting.
用于Google OAuth2认证的代理URL。
Environment variable: OAUTH_PROXY_URL
TOML config key: oauth_proxy_url
Default: https://oauth2.googleapis.com
"""
return str(await get_config_value("oauth_proxy_url", "https://oauth2.googleapis.com", "OAUTH_PROXY_URL"))
async def get_googleapis_proxy_url() -> str:
"""
Get Google APIs proxy URL setting.
用于Google APIs调用的代理URL。
Environment variable: GOOGLEAPIS_PROXY_URL
TOML config key: googleapis_proxy_url
Default: https://www.googleapis.com
"""
return str(await get_config_value("googleapis_proxy_url", "https://www.googleapis.com", "GOOGLEAPIS_PROXY_URL"))
async def get_resource_manager_api_url() -> str:
"""
Get Google Cloud Resource Manager API URL setting.
用于Google Cloud Resource Manager API的URL。
Environment variable: RESOURCE_MANAGER_API_URL
TOML config key: resource_manager_api_url
Default: https://cloudresourcemanager.googleapis.com
"""
return str(await get_config_value("resource_manager_api_url", "https://cloudresourcemanager.googleapis.com", "RESOURCE_MANAGER_API_URL"))
async def get_service_usage_api_url() -> str:
"""
Get Google Cloud Service Usage API URL setting.
用于Google Cloud Service Usage API的URL。
Environment variable: SERVICE_USAGE_API_URL
TOML config key: service_usage_api_url
Default: https://serviceusage.googleapis.com
"""
return str(await get_config_value("service_usage_api_url", "https://serviceusage.googleapis.com", "SERVICE_USAGE_API_URL"))
# MongoDB Configuration
async def get_mongodb_uri() -> str:
"""
Get MongoDB connection URI setting.
MongoDB连接URI,用于分布式部署时的数据存储。
设置此项后将不再使用本地/creds和TOML文件。
Environment variable: MONGODB_URI
TOML config key: mongodb_uri
Default: None (使用本地文件存储)
示例格式:
- mongodb://username:password@localhost:27017/database
- mongodb+srv://username:password@cluster.mongodb.net/database
"""
return str(await get_config_value("mongodb_uri", "", "MONGODB_URI"))
async def get_mongodb_database() -> str:
"""
Get MongoDB database name setting.
MongoDB数据库名称。
Environment variable: MONGODB_DATABASE
TOML config key: mongodb_database
Default: gcli2api
"""
return str(await get_config_value("mongodb_database", "gcli2api", "MONGODB_DATABASE"))
async def is_mongodb_mode() -> bool:
"""
Check if MongoDB mode is enabled.
检查是否启用了MongoDB模式。
如果配置了MongoDB URI,则启用MongoDB模式,不再使用本地文件。
Returns:
bool: True if MongoDB mode is enabled, False otherwise
"""
mongodb_uri = await get_mongodb_uri()
return bool(mongodb_uri and mongodb_uri.strip()) |