Spaces:
Running
Running
| """ | |
| Konfiguracja aplikacji. | |
| Wykorzystuje Pydantic Settings do zarządzania zmiennymi środowiskowymi. | |
| """ | |
| from functools import lru_cache | |
| from pydantic_settings import BaseSettings, SettingsConfigDict | |
| class Settings(BaseSettings): | |
| """ | |
| Ustawienia aplikacji ładowane ze zmiennych środowiskowych. | |
| """ | |
| model_config = SettingsConfigDict( | |
| env_file=(".env", "backend/.env"), | |
| env_file_encoding="utf-8", | |
| case_sensitive=False, | |
| extra="ignore" | |
| ) | |
| # MongoDB | |
| mongodb_url: str = "" | |
| mongodb_db_name: str = "sentimentSummary" | |
| # App Mode | |
| app_mode: str = "full" # "full" = monolith, "api" = API-only (no frontend) | |
| # App Settings | |
| debug: bool = False | |
| cors_origins: str = "http://localhost:5173,http://localhost:3000" | |
| # Cache Settings | |
| cache_ttl_hours: int = 24 | |
| cache_ttl_short_hours: int = 12 # frequently updated games | |
| cache_ttl_long_hours: int = 168 # stable games (7 days) | |
| cache_ttl_worker_managed_hours: int = 1440 # 60 days to preserve stale fallback results | |
| cache_ttl_on_demand_hours: int = 1440 # 60 days to preserve stale fallback results | |
| # Incremental Analysis | |
| incremental_enabled: bool = True | |
| incremental_max_stored_ids: int = 5000 | |
| incremental_max_gap_days: int = 90 # fall back to full analysis after this many days without reviews | |
| recent_sample_limit: int = 1000 | |
| niche_cache_max_age_days: int = 60 | |
| analysis_freshness_max_age_days: int = 60 | |
| patch_context_max_age_days: int = 90 | |
| dlc_min_reviews_for_analysis: int = 50 | |
| dlc_visible_in_search: bool = False # Temporary policy: hide DLC from autocomplete/suggestions | |
| dlc_worker_analysis_enabled: bool = False # Temporary policy: exclude DLC from worker-managed analysis | |
| # Steam API Settings | |
| review_batch_size: int = 100 | |
| steam_review_language: str = "schinese" # Review fetch scope; product analyzes Simplified Chinese Steam reviews. | |
| steam_region: str = "CN" # CN, US, etc. | |
| # Steam API Retry | |
| steam_retry_max_attempts: int = 3 | |
| steam_retry_base_delay: float = 1.0 # doubles each retry | |
| steam_retry_max_delay: float = 10.0 # cap | |
| # Steam API Error Cache TTL (seconds) | |
| steam_error_cache_ttl_404: int = 3600 # 1h | |
| steam_error_cache_ttl_429: int = 300 # 5min | |
| # Sampling Settings - Statistical sampling parameters | |
| sample_top_helpful: int = 50 | |
| sample_confidence_level: float = 0.95 | |
| sample_margin_of_error: float = 0.02 | |
| sample_max_reviews: int = 3000 | |
| sample_minority_min: int = 100 | |
| # NLP Settings - Analysis Parameters | |
| text_max_length: int = 512 | |
| sentiment_positive_threshold: float = 0.1 | |
| sentiment_negative_threshold: float = -0.1 | |
| topic_min_mentions: int = 5 | |
| # NLP Settings - Deduplication Cache | |
| dedup_cache_maxsize: int = 10000 | |
| # NLP Settings - Performance & Logic | |
| nlp_onnx_intra_threads: int = 2 | |
| nlp_onnx_inter_threads: int = 2 | |
| nlp_negation_window: int = 3 | |
| # Prediction Settings | |
| prediction_retention_threshold_pos: float = 0.2 | |
| prediction_retention_threshold_neg: float = -0.2 | |
| # Community Highlights | |
| highlights_ngram_min: int = 2 | |
| highlights_ngram_max: int = 5 | |
| highlights_min_mentions: int = 3 | |
| highlights_max_doc_freq_ratio: float = 0.4 | |
| highlights_top_n_general: int = 15 | |
| highlights_top_n_per_topic: int = 5 | |
| # Worker — Pre-cache | |
| worker_trigger_token: str = "" | |
| precache_enabled: bool = False | |
| precache_top_n_games: int = 500 | |
| precache_batch_delay_seconds: int = 10 | |
| precache_checkpoints_hours: str = "6,12,24,72,168,336" | |
| precache_max_analyses_per_cycle: int = 50 | |
| # Worker — Priority Games | |
| steam_priority_categories: str = "top_sellers,new_releases,specials" | |
| steam_priority_regions: str = "CN,US" | |
| steam_priority_grace_days: int = 3 | |
| steam_priority_categories_url: str = "https://store.steampowered.com/api/featuredcategories" | |
| steam_bootstrap_max_per_cycle: int = 20 | |
| steam_bootstrap_delay: float = 1.5 | |
| # Worker — News Scan | |
| news_refresh_window_hours: int = 6 | |
| news_initial_count: int = 20 | |
| news_incremental_count: int = 5 | |
| # Worker — Game Sync | |
| game_sync_enabled: bool = False | |
| game_sync_steamspy_delay: float = 61.0 | |
| game_sync_details_delay: float = 1.1 | |
| game_sync_top_n_details: int = 500 | |
| game_sync_cn_enrichment_delay: float = 1.5 | |
| game_sync_cn_enrichment_limit: int = 200 | |
| game_sync_app_type_enrichment_delay: float = 1.5 | |
| game_sync_app_type_enrichment_limit: int = 200 | |
| # Logging (both Live API and Worker) | |
| worker_log_dir: str = "/data/worker_logs" | |
| worker_log_fallback_dir: str = "/tmp/worker_logs" | |
| worker_log_max_bytes: int = 5_000_000 # 5 MB per file | |
| worker_log_backup_count: int = 3 # 3 rotated files = 20 MB max | |
| nlp_verbose_logging: bool = False # re-enable NLP debug logs to stdout | |
| nlp_debug_log_max_bytes: int = 2_000_000 # 2 MB per file | |
| errors_log_max_bytes: int = 2_000_000 # 2 MB per file | |
| # Rate Limiting | |
| rate_limit_analyze: str = "10/minute" | |
| rate_limit_default: str = "30/minute" | |
| # NLP Settings - Hugging Face Models | |
| # Using specialized Chinese model (RoBERTa-JD) - 90% accuracy on product reviews | |
| hf_sentiment_model: str = "uer/roberta-base-finetuned-jd-binary-chinese" | |
| def cors_origins_list(self) -> list[str]: | |
| """Zwraca listę dozwolonych originów CORS.""" | |
| return [origin.strip() for origin in self.cors_origins.split(",")] | |
| def precache_checkpoints_list(self) -> list[int]: | |
| """Parse checkpoint hours from comma-separated string.""" | |
| return sorted(int(h.strip()) for h in self.precache_checkpoints_hours.split(",")) | |
| def steam_priority_categories_list(self) -> list[str]: | |
| return [c.strip() for c in self.steam_priority_categories.split(",") if c.strip()] | |
| def steam_priority_regions_list(self) -> list[str]: | |
| return [r.strip() for r in self.steam_priority_regions.split(",") if r.strip()] | |
| def get_settings() -> Settings: | |
| """Zwraca singleton instancji Settings.""" | |
| return Settings() | |
| settings = get_settings() | |