"""节日需求流程配置。""" from __future__ import annotations import os from app.core.config import settings from app.festival_demand.exceptions import FestivalDemandError def _get_env(name: str, default: str = "") -> str: value = os.getenv(name) if value is None or value == "": return default return value def _get_env_int(name: str, default: int) -> int: raw = os.getenv(name) if raw is None or raw == "": return default try: return int(raw) except ValueError as exc: raise FestivalDemandError(f"invalid integer env {name}={raw!r}") from exc def _get_env_float(name: str, default: float) -> float: raw = os.getenv(name) if raw is None or raw == "": return default try: return float(raw) except ValueError as exc: raise FestivalDemandError(f"invalid float env {name}={raw!r}") from exc def _parse_cron_hours(value: str) -> str: hours = [item.strip() for item in value.split(",") if item.strip()] if not hours: raise FestivalDemandError("festival demand cron hours cannot be empty") normalized: list[str] = [] for hour in hours: try: hour_num = int(hour) except ValueError as exc: raise FestivalDemandError(f"invalid festival demand cron hour: {hour!r}") from exc if not 0 <= hour_num <= 23: raise FestivalDemandError(f"festival demand cron hour out of range: {hour_num}") normalized.append(str(hour_num)) return ",".join(normalized) def load_festival_demand_config() -> "FestivalDemandConfig": from app.festival_demand.types import FestivalDemandConfig llm_model = _get_env("FESTIVAL_DEMAND_LLM_MODEL", settings.festival_demand_llm_model) config = FestivalDemandConfig( cron_hours=_parse_cron_hours( _get_env("FESTIVAL_DEMAND_CRON_HOURS", settings.festival_demand_cron_hours) ), cron_minute=_get_env_int( "FESTIVAL_DEMAND_CRON_MINUTE", settings.festival_demand_cron_minute, ), llm_model=llm_model.strip() or settings.open_router_default_model, llm_max_attempts=_get_env_int( "FESTIVAL_DEMAND_LLM_MAX_ATTEMPTS", settings.festival_demand_llm_max_attempts, ), llm_retry_sleep_seconds=_get_env_float( "FESTIVAL_DEMAND_LLM_RETRY_SLEEP_SECONDS", settings.festival_demand_llm_retry_sleep_seconds, ), llm_max_tokens=_get_env_int( "FESTIVAL_DEMAND_LLM_MAX_TOKENS", settings.festival_demand_llm_max_tokens, ), llm_temperature=_get_env_float( "FESTIVAL_DEMAND_LLM_TEMPERATURE", settings.festival_demand_llm_temperature, ), demand_pool_source_table=_get_env( "DEMAND_POOL_SOURCE_TABLE", settings.demand_pool_source_table, ).strip(), demand_pool_strategy=_get_env( "FESTIVAL_DEMAND_POOL_STRATEGY", settings.festival_demand_pool_strategy, ).strip(), output_strategy=_get_env( "FESTIVAL_DEMAND_OUTPUT_STRATEGY", settings.festival_demand_output_strategy, ).strip(), match_batch_size=_get_env_int( "FESTIVAL_DEMAND_MATCH_BATCH_SIZE", settings.festival_demand_match_batch_size, ), ) if config.match_batch_size <= 0: raise FestivalDemandError("FESTIVAL_DEMAND_MATCH_BATCH_SIZE must be positive") return config