Spaces:
Running
Running
| from __future__ import annotations | |
| import os | |
| from dataclasses import dataclass, field | |
| from pathlib import Path | |
| import yaml | |
| PROJECT_ROOT = Path(__file__).resolve().parents[2] | |
| def _default_dataset_root() -> Path: | |
| return PROJECT_ROOT / "data" / "public" / "input" | |
| def _default_run_output_dir() -> Path: | |
| return PROJECT_ROOT / "artifacts" / "runs" | |
| class DatasetConfig: | |
| root_path: Path = field(default_factory=_default_dataset_root) | |
| class AgentConfig: | |
| # OpenAI-style config | |
| model: str = "gpt-4.1-mini" | |
| api_base: str = "https://api.openai.com/v1" | |
| api_key: str = "" | |
| max_steps: int = 16 | |
| temperature: float = 0.0 | |
| # Azure OpenAI-style (NIQ) config | |
| azure_endpoint: str = "" | |
| azure_api_key: str = "" | |
| azure_api_version: str = "" | |
| azure_deployment: str = "" | |
| azure_custom_headers: dict[str, str] = field(default_factory=dict) | |
| class LoggingConfig: | |
| log_debug: bool = False | |
| class EvaluationConfig: | |
| """Phase 15: Run + evaluation workflow configuration.""" | |
| enabled: bool = False | |
| gold_root: Path | None = None | |
| run_after_execution: bool = False | |
| fail_if_ground_truth_missing: bool = False | |
| lambda_penalty: float = 0.1 | |
| mode: str = "standard" | |
| class FeatureFlagConfig: | |
| """Feature flags for experimental capabilities.""" | |
| # False: use existing architecture (baseline) | |
| # True: use multi-agent architecture (Adaptive Analyst Team) | |
| # Supports side-by-side evaluation when both values are tested. | |
| enable_adaptive_analyst_team: bool = True # ENABLED for KDD Creative Track | |
| class RunConfig: | |
| output_dir: Path = field(default_factory=_default_run_output_dir) | |
| run_id: str | None = None | |
| max_workers: int = 4 | |
| task_timeout_seconds: int = 600 | |
| class AppConfig: | |
| dataset: DatasetConfig = field(default_factory=DatasetConfig) | |
| agent: AgentConfig = field(default_factory=AgentConfig) | |
| run: RunConfig = field(default_factory=RunConfig) | |
| logging: LoggingConfig = field(default_factory=LoggingConfig) | |
| evaluation: EvaluationConfig = field(default_factory=EvaluationConfig) | |
| feature_flags: FeatureFlagConfig = field(default_factory=FeatureFlagConfig) | |
| def _path_value(raw_value: str | None, default_value: Path) -> Path: | |
| if not raw_value: | |
| return default_value | |
| candidate = Path(raw_value) | |
| if candidate.is_absolute(): | |
| return candidate | |
| return (PROJECT_ROOT / candidate).resolve() | |
| def load_app_config(config_path: Path) -> AppConfig: | |
| payload = yaml.safe_load(config_path.read_text()) or {} | |
| dataset_defaults = DatasetConfig() | |
| agent_defaults = AgentConfig() | |
| run_defaults = RunConfig() | |
| logging_defaults = LoggingConfig() | |
| evaluation_defaults = EvaluationConfig() | |
| dataset_payload = payload.get("dataset", {}) | |
| agent_payload = payload.get("agent", {}) | |
| run_payload = payload.get("run", {}) | |
| logging_payload = payload.get("logging", {}) | |
| evaluation_payload = payload.get("evaluation", {}) | |
| dataset_config = DatasetConfig( | |
| root_path=_path_value(dataset_payload.get("root_path"), dataset_defaults.root_path), | |
| ) | |
| # Parse custom headers for Azure | |
| azure_custom_headers = {} | |
| if "azure_custom_headers" in agent_payload: | |
| azure_custom_headers = dict(agent_payload.get("azure_custom_headers", {})) | |
| # Load from environment variables if not specified in config | |
| azure_endpoint = str(agent_payload.get("azure_endpoint", agent_defaults.azure_endpoint)) | |
| if not azure_endpoint: | |
| azure_endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT", "") | |
| azure_api_key = str(agent_payload.get("azure_api_key", agent_defaults.azure_api_key)) | |
| if not azure_api_key: | |
| azure_api_key = os.environ.get("AZURE_OPENAI_API_KEY", "") | |
| azure_api_version = str(agent_payload.get("azure_api_version", agent_defaults.azure_api_version)) | |
| if not azure_api_version: | |
| azure_api_version = os.environ.get("AZURE_OPENAI_API_VERSION", "") | |
| azure_deployment = str(agent_payload.get("azure_deployment", agent_defaults.azure_deployment)) | |
| if not azure_deployment: | |
| azure_deployment = os.environ.get("AZURE_OPENAI_DEPLOYMENT", "") | |
| # Load custom header from environment if specified | |
| if not azure_custom_headers: | |
| niq_consumer = os.environ.get("X_NIQ_CIS_CONSUMER", "") | |
| if niq_consumer: | |
| azure_custom_headers["X-NIQ-CIS-CONSUMER"] = niq_consumer | |
| # Load OpenAI config from environment if not specified | |
| api_key = str(agent_payload.get("api_key", agent_defaults.api_key)) | |
| if not api_key: | |
| api_key = os.environ.get("OPENAI_API_KEY", "") | |
| agent_config = AgentConfig( | |
| model=str(agent_payload.get("model", agent_defaults.model)), | |
| api_base=str(agent_payload.get("api_base", agent_defaults.api_base)), | |
| api_key=api_key, | |
| max_steps=int(agent_payload.get("max_steps", agent_defaults.max_steps)), | |
| temperature=float(agent_payload.get("temperature", agent_defaults.temperature)), | |
| # Azure config | |
| azure_endpoint=azure_endpoint, | |
| azure_api_key=azure_api_key, | |
| azure_api_version=azure_api_version, | |
| azure_deployment=azure_deployment, | |
| azure_custom_headers=azure_custom_headers, | |
| ) | |
| raw_run_id = run_payload.get("run_id") | |
| run_id = run_defaults.run_id | |
| if raw_run_id is not None: | |
| normalized_run_id = str(raw_run_id).strip() | |
| run_id = normalized_run_id or None | |
| run_config = RunConfig( | |
| output_dir=_path_value(run_payload.get("output_dir"), run_defaults.output_dir), | |
| run_id=run_id, | |
| max_workers=int(run_payload.get("max_workers", run_defaults.max_workers)), | |
| task_timeout_seconds=int(run_payload.get("task_timeout_seconds", run_defaults.task_timeout_seconds)), | |
| ) | |
| logging_config = LoggingConfig( | |
| log_debug=bool(logging_payload.get("log_debug", logging_defaults.log_debug)), | |
| ) | |
| # Parse evaluation config | |
| eval_mode = str(evaluation_payload.get("mode", evaluation_defaults.mode)) | |
| if eval_mode not in {"standard", "verbose", "research"}: | |
| raise ValueError( | |
| f"Invalid evaluation mode: {eval_mode!r}. " | |
| "Must be one of: standard, verbose, research" | |
| ) | |
| eval_gold_root = evaluation_payload.get("gold_root") | |
| eval_gold_root_path: Path | None = None | |
| if eval_gold_root is not None: | |
| eval_gold_root_path = _path_value(str(eval_gold_root), Path(".")) | |
| evaluation_config = EvaluationConfig( | |
| enabled=bool(evaluation_payload.get("enabled", evaluation_defaults.enabled)), | |
| gold_root=eval_gold_root_path, | |
| run_after_execution=bool(evaluation_payload.get("run_after_execution", evaluation_defaults.run_after_execution)), | |
| fail_if_ground_truth_missing=bool(evaluation_payload.get("fail_if_ground_truth_missing", evaluation_defaults.fail_if_ground_truth_missing)), | |
| lambda_penalty=float(evaluation_payload.get("lambda_penalty", evaluation_defaults.lambda_penalty)), | |
| mode=eval_mode, | |
| ) | |
| feature_flags_payload = payload.get("feature_flags", {}) | |
| feature_flag_defaults = FeatureFlagConfig() | |
| # Also check environment variable override | |
| aat_env = os.environ.get("ENABLE_ADAPTIVE_ANALYST_TEAM", "").lower() | |
| enable_aat = bool(feature_flags_payload.get( | |
| "enable_adaptive_analyst_team", | |
| feature_flag_defaults.enable_adaptive_analyst_team, | |
| )) | |
| if aat_env in ("1", "true", "yes"): | |
| enable_aat = True | |
| elif aat_env in ("0", "false", "no"): | |
| enable_aat = False | |
| feature_flags_config = FeatureFlagConfig(enable_adaptive_analyst_team=enable_aat) | |
| return AppConfig( | |
| dataset=dataset_config, | |
| agent=agent_config, | |
| run=run_config, | |
| logging=logging_config, | |
| evaluation=evaluation_config, | |
| feature_flags=feature_flags_config, | |
| ) | |
| def load_agent_config_from_env() -> AgentConfig: | |
| """ | |
| Load agent configuration from environment variables (for evaluation system). | |
| This function is used during competition evaluation when the container | |
| receives MODEL_API_URL, MODEL_API_KEY, and MODEL_NAME from the evaluation system. | |
| Required environment variables: | |
| - MODEL_API_URL: OpenAI-compatible API endpoint | |
| - MODEL_API_KEY: API key for authentication | |
| - MODEL_NAME: Model name (default: qwen3.5-35b-a3b) | |
| Returns: | |
| AgentConfig with settings from environment variables | |
| """ | |
| model_api_url = os.getenv("MODEL_API_URL", "") | |
| model_api_key = os.getenv("MODEL_API_KEY", "") | |
| model_name = os.getenv("MODEL_NAME", "qwen3.5-35b-a3b") | |
| if not model_api_url: | |
| raise ValueError("MODEL_API_URL environment variable is required") | |
| if not model_api_key: | |
| raise ValueError("MODEL_API_KEY environment variable is required") | |
| return AgentConfig( | |
| model=model_name, | |
| api_base=model_api_url, | |
| api_key=model_api_key, | |
| max_steps=16, | |
| temperature=0.0, | |
| azure_endpoint="", | |
| azure_api_key="", | |
| azure_api_version="", | |
| azure_deployment="", | |
| azure_custom_headers={}, | |
| ) |