sipe5001's picture
Add Hugging Face Docker Space configuration
d3d0e0e
Raw
History Blame Contribute Delete
9.4 kB
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"
@dataclass(frozen=True, slots=True)
class DatasetConfig:
root_path: Path = field(default_factory=_default_dataset_root)
@dataclass(frozen=True, slots=True)
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)
@dataclass(frozen=True, slots=True)
class LoggingConfig:
log_debug: bool = False
@dataclass(frozen=True, slots=True)
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"
@dataclass(frozen=True, slots=True)
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
@dataclass(frozen=True, slots=True)
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
@dataclass(frozen=True, slots=True)
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={},
)