Download src/config.py from nvikou/vitrina: direct link, hf CLI and curl.
- Browser
- Download file 3.69 kB
-
https://huggingface.co/spaces/nvikou/vitrina/resolve/main/src/config.py
- Command line
-
hf download hf://spaces/nvikou/vitrina/src/config.py
-
curl -L -o config.py https://huggingface.co/spaces/nvikou/vitrina/resolve/main/src/config.py
3.69 kB
| """Конфигурация приложения. Всё читается из переменных окружения. | |
| На Hugging Face Spaces значения задаются в Settings → Variables and secrets. | |
| Локально — через .env (см. .env.example). | |
| """ | |
| from __future__ import annotations | |
| import os | |
| from dataclasses import dataclass, field | |
| from pathlib import Path | |
| try: # локальный запуск: подхватываем .env, если он есть | |
| from dotenv import load_dotenv | |
| load_dotenv(override=False) | |
| except ImportError: # на Spaces переменные приходят из окружения | |
| pass | |
| APP_NAME = "Витрина" | |
| APP_TAGLINE = "Иллюстрации и тексты карточек товаров для маркетплейсов" | |
| _TRUE = {"1", "true", "yes", "on", "да"} | |
| def _flag(name: str, default: bool = False) -> bool: | |
| raw = os.getenv(name) | |
| return default if raw is None else raw.strip().lower() in _TRUE | |
| def _int(name: str, default: int) -> int: | |
| try: | |
| return int(os.getenv(name, default)) | |
| except (TypeError, ValueError): | |
| return default | |
| class Settings: | |
| # --- ключи (могут быть пустыми: тогда пользователь вводит свой в интерфейсе) --- | |
| openai_api_key: str = field(default_factory=lambda: os.getenv("OPENAI_API_KEY", "").strip()) | |
| groq_api_key: str = field(default_factory=lambda: os.getenv("GROQ_API_KEY", "").strip()) | |
| openai_base_url: str | None = field( | |
| default_factory=lambda: os.getenv("OPENAI_BASE_URL", "").strip() or None | |
| ) | |
| # --- модели --- | |
| # Названия моделей у провайдеров меняются. Всё вынесено в env, | |
| # чтобы поменять их без правки кода. | |
| image_model: str = field(default_factory=lambda: os.getenv("OPENAI_IMAGE_MODEL", "gpt-image-1")) | |
| image_model_fallback: str = field( | |
| default_factory=lambda: os.getenv("OPENAI_IMAGE_MODEL_FALLBACK", "dall-e-3") | |
| ) | |
| groq_text_model: str = field( | |
| default_factory=lambda: os.getenv("GROQ_TEXT_MODEL", "llama-3.3-70b-versatile") | |
| ) | |
| groq_vision_model: str = field( | |
| default_factory=lambda: os.getenv( | |
| "GROQ_VISION_MODEL", "meta-llama/llama-4-scout-17b-16e-instruct" | |
| ) | |
| ) | |
| # --- лимиты --- | |
| max_images: int = field(default_factory=lambda: _int("MAX_IMAGES", 4)) | |
| request_timeout: int = field(default_factory=lambda: _int("REQUEST_TIMEOUT", 180)) | |
| max_retries: int = field(default_factory=lambda: _int("MAX_RETRIES", 3)) | |
| # --- поведение --- | |
| allow_user_keys: bool = field(default_factory=lambda: _flag("ALLOW_USER_KEYS", True)) | |
| enable_queue_concurrency: int = field(default_factory=lambda: _int("CONCURRENCY", 2)) | |
| output_dir: Path = field(default_factory=lambda: Path(os.getenv("OUTPUT_DIR", "outputs"))) | |
| log_level: str = field(default_factory=lambda: os.getenv("LOG_LEVEL", "INFO").upper()) | |
| def resolve_openai_key(self, user_key: str | None) -> str: | |
| """Ключ пользователя приоритетнее серверного, если это разрешено.""" | |
| if self.allow_user_keys and user_key and user_key.strip(): | |
| return user_key.strip() | |
| return self.openai_api_key | |
| def resolve_groq_key(self, user_key: str | None) -> str: | |
| if self.allow_user_keys and user_key and user_key.strip(): | |
| return user_key.strip() | |
| return self.groq_api_key | |
| settings = Settings() | |
| settings.output_dir.mkdir(parents=True, exist_ok=True) | |