Files
Semon Xue 5b18d378d7 Initial commit
- Modern ComfyUI FlexAI plugin with OpenAI SDK 1.x support
- Dual-mode image processing: generation (images.generate) + editing (images.edit)
- Support for 1-4 simultaneous image inputs in edit mode
- Multimodal text generation with vision-language understanding
- Multi-provider configuration system
- Comprehensive error handling with visual feedback
- Clean architecture with unified flexai: namespace
- Complete documentation in English and Chinese
2025-09-01 08:49:34 +08:00

104 lines
2.8 KiB
Python

"""Provider configuration utilities (suffix naming, simplified).
规则:
1. 多 provider: 使用 OPENAI_API_KEY_<token> 与可选 OPENAI_API_BASE_<token>
2. 可声明 OPENAI_PROVIDERS=token1,token2 来限定顺序; 若缺省则自动扫描 OPENAI_API_KEY_* 后缀。
3. 回退兼容单一: OPENAI_API_KEY / OPENAI_API_BASE。
示例:
OPENAI_API_KEY_default=sk_xxx
OPENAI_API_KEY_alt=sk_yyy
-> tokens = default, alt
或显式:
OPENAI_PROVIDERS=default,alt
OPENAI_API_KEY_default=sk_xxx
OPENAI_API_KEY_alt=sk_yyy
"""
from __future__ import annotations
import os
from dataclasses import dataclass
from typing import List, Dict
@dataclass
class Provider:
token: str # token 名(用于下拉显示)
api_key: str
base_url: str
_CACHE: List[Provider] | None = None
def _legacy_single_provider() -> List[Provider]:
"""Single provider fallback (OPENAI_* only)."""
api_key = os.getenv("OPENAI_API_KEY")
base = os.getenv("OPENAI_API_BASE") or "https://api.openai.com/v1"
if not api_key:
return []
return [Provider(token="default", api_key=api_key, base_url=base)]
def _parse_multi() -> List[Provider]:
providers_var = os.getenv("OPENAI_PROVIDERS")
tokens: List[str] = []
if providers_var:
tokens = [t.strip() for t in providers_var.split(',') if t.strip()]
else:
prefix = "OPENAI_API_KEY_"
for k in os.environ.keys():
if k.startswith(prefix):
suffix = k[len(prefix):].strip()
if suffix:
tokens.append(suffix)
tokens = sorted(set(tokens))
if not tokens:
return _legacy_single_provider()
providers: List[Provider] = []
for token in tokens:
key = os.getenv(f"OPENAI_API_KEY_{token}")
if not key:
continue
base = os.getenv(f"OPENAI_API_BASE_{token}") or "https://api.openai.com/v1"
providers.append(Provider(token=token, api_key=key, base_url=base))
if not providers:
return _legacy_single_provider()
return providers
def load_providers(force_reload: bool = False) -> List[Provider]:
global _CACHE
if _CACHE is None or force_reload:
_CACHE = _parse_multi()
return _CACHE
def get_provider_display_names() -> List[str]:
return [p.token for p in load_providers()]
def get_provider_by_name(name: str) -> Provider | None:
for p in load_providers():
if p.token == name:
return p
return None
def ensure_any_provider():
"""若没有任何 provider, 抛出友好错误."""
if not load_providers():
raise ValueError(
"未检测到 API 配置: 请在 .env 中设置 OPENAI_API_KEY= 或 使用 OPENAI_PROVIDERS=... 多组配置"
)
__all__ = [
"Provider",
"load_providers",
"get_provider_display_names",
"get_provider_by_name",
"ensure_any_provider",
]