Spaces:
Running
Running
Download solar_eval/cli/config.py from dev-strender/proofread-demo: direct link, hf CLI and curl.
- Browser
- Download file 7.05 kB
-
https://huggingface.co/spaces/dev-strender/proofread-demo/resolve/483134ace86f21c444532ef540c77505aadb29b9/solar_eval/cli/config.py
- Command line
-
hf download hf://spaces/dev-strender/proofread-demo@483134ace86f21c444532ef540c77505aadb29b9/solar_eval/cli/config.py
-
curl -L -o config.py https://huggingface.co/spaces/dev-strender/proofread-demo/resolve/483134ace86f21c444532ef540c77505aadb29b9/solar_eval/cli/config.py
7.05 kB
| """CLI configuration from YAML file and environment variables.""" | |
| import logging | |
| import os | |
| from pathlib import Path | |
| from typing import Any | |
| import yaml | |
| DEFAULT_CONFIG_PATH = Path.home() / ".upstage-cloud-dev" / "solar-eval-config.yaml" | |
| logger = logging.getLogger(__name__) | |
| def default_projects_dir() -> Path: | |
| """CBS 공용 데이터 홈 아래의 프로젝트 루트 (huggingface 캐시와 같은 방식). | |
| - 기본값: ``~/.cache/cbs-data/solar-eval-projects`` | |
| - ``CBS_DATA_HOME`` 이 설정되면 데이터 홈 자체를 옮긴다: ``$CBS_DATA_HOME/solar-eval-projects`` | |
| - ``XDG_CACHE_HOME`` 이 설정되면 캐시 루트로 존중한다: ``$XDG_CACHE_HOME/cbs-data/solar-eval-projects`` | |
| """ | |
| data_home = os.environ.get("CBS_DATA_HOME") | |
| if data_home: | |
| return Path(data_home).expanduser() / "solar-eval-projects" | |
| cache_root = os.environ.get("XDG_CACHE_HOME", "~/.cache") | |
| return Path(cache_root).expanduser() / "cbs-data" / "solar-eval-projects" | |
| def find_repo_root() -> Path | None: | |
| """이 패키지가 harness 레포 체크아웃 안에 vendored 되어 있으면 레포 루트를 찾는다. | |
| ``SOLAR_EVAL_CONFIG_ROOT`` 환경변수가 있으면 그 경로를 쓴다 (테스트/특수 환경용). | |
| 레포 밖 standalone 설치면 None — 이때는 데이터 홈 단일 루트로 동작한다. | |
| """ | |
| override = os.environ.get("SOLAR_EVAL_CONFIG_ROOT") | |
| if override: | |
| path = Path(override).expanduser() | |
| return path if path.is_dir() else None | |
| for parent in Path(__file__).resolve().parents: | |
| if (parent / "pnpm-workspace.yaml").is_file(): | |
| return parent | |
| return None | |
| def discover_config_dirs(repo_root: Path | None) -> dict[str, Path]: | |
| """레포의 ``accounts/*/*/03-evaluation/project.yaml`` 에서 프로젝트명 → config 디렉토리 맵. | |
| hydra/DVC 식 분리의 발견 단계: config(project.yaml·prompts·pipelines)는 git 이 정본, | |
| datasets/artifacts 는 데이터 홈이 정본이다. | |
| """ | |
| if repo_root is None: | |
| return {} | |
| found: dict[str, Path] = {} | |
| for manifest in sorted(repo_root.glob("accounts/*/*/03-evaluation/project.yaml")): | |
| try: | |
| with open(manifest) as f: | |
| doc = yaml.safe_load(f) | |
| except Exception as e: | |
| logger.warning("Failed to read %s: %s", manifest, e) | |
| continue | |
| name = doc.get("name") if isinstance(doc, dict) else None | |
| if isinstance(name, str) and name: | |
| found[name] = manifest.parent | |
| return found | |
| def _load_yaml_config(config_path: Path | None = None) -> dict[str, Any]: | |
| """YAML 설정 파일 로드. 파일 없으면 빈 dict 반환.""" | |
| path = config_path or Path(os.environ.get("SOLAR_EVAL_CONFIG", str(DEFAULT_CONFIG_PATH))) | |
| if not path.is_file(): | |
| return {} | |
| try: | |
| with open(path) as f: | |
| data = yaml.safe_load(f) | |
| return data if isinstance(data, dict) else {} | |
| except Exception as e: | |
| logger.warning("Failed to load config from %s: %s", path, e) | |
| return {} | |
| class CLIConfig: | |
| """Configuration for the Solar Eval CLI. | |
| Priority (low → high): | |
| 1. Hard-coded defaults (projects_dir: ~/.cache/cbs-data/solar-eval-projects) | |
| 2. YAML config file (~/.upstage-cloud-dev/solar-eval-config.yaml) | |
| 3. Environment variables (SOLAR_EVAL_URL, CBS_DATA_HOME, SOLAR_EVAL_PROJECTS, etc.) | |
| 4. CLI options (--remote, etc.) | |
| """ | |
| def __init__(self, config_path: Path | None = None) -> None: | |
| yaml_cfg = _load_yaml_config(config_path) | |
| yaml_remote = yaml_cfg.get("remote_url") or yaml_cfg.get("remote") | |
| self.remote_url: str | None = os.environ.get("SOLAR_EVAL_URL", yaml_remote) | |
| yaml_timeout = yaml_cfg.get("timeout", 300) | |
| self.timeout = int(os.environ.get("SOLAR_EVAL_TIMEOUT", yaml_timeout)) | |
| # SOLAR_EVAL_PROJECTS(구체) > CBS_DATA_HOME(데이터 홈) > YAML projects_dir > 캐시 기본값 | |
| env_projects = os.environ.get("SOLAR_EVAL_PROJECTS") | |
| yaml_projects = yaml_cfg.get("projects_dir") | |
| if env_projects: | |
| self.projects_dir = Path(env_projects).expanduser() | |
| explicit_root = True | |
| elif os.environ.get("CBS_DATA_HOME") or not yaml_projects: | |
| self.projects_dir = default_projects_dir() | |
| explicit_root = False | |
| else: | |
| self.projects_dir = Path(yaml_projects).expanduser() | |
| explicit_root = True | |
| # config 오버레이 (hydra/W&B/DVC 패턴): 표준 데이터 홈에서는 레포의 | |
| # accounts/*/*/03-evaluation 이 config 정본이다. 명시적으로 지정된 루트 | |
| # (SOLAR_EVAL_PROJECTS·YAML projects_dir·--projects-dir)는 과거 아카이브 등 | |
| # 자급자족 트리를 가리키는 용도이므로 오버레이하지 않는다. | |
| self.repo_root: Path | None = None if explicit_root else find_repo_root() | |
| self.config_dirs: dict[str, Path] = discover_config_dirs(self.repo_root) | |
| # Load provider API keys from YAML (env vars take precedence) | |
| upstage_cfg = yaml_cfg.get("upstage", {}) | |
| if upstage_cfg.get("api_key") and not os.environ.get("UPSTAGE_API_KEY"): | |
| os.environ["UPSTAGE_API_KEY"] = upstage_cfg["api_key"] | |
| openai_cfg = yaml_cfg.get("openai", {}) | |
| if openai_cfg.get("api_key") and not os.environ.get("OPENAI_API_KEY"): | |
| os.environ["OPENAI_API_KEY"] = openai_cfg["api_key"] | |
| def is_remote(self) -> bool: | |
| return self.remote_url is not None | |
| def override_projects_dir(self, path: Path) -> None: | |
| """``--projects-dir`` 플래그: 지정한 루트를 자급자족 아카이브로 쓴다 (오버레이 해제).""" | |
| self.projects_dir = path | |
| self.repo_root = None | |
| self.config_dirs = {} | |
| def is_repo_managed(self, project: str) -> bool: | |
| """이 프로젝트의 config 정본이 레포(accounts)에 있는가.""" | |
| return project in self.config_dirs | |
| def config_dir(self, project: str) -> Path: | |
| """config(project.yaml·prompts·pipelines) 루트 — 레포 관리면 레포 쪽, 아니면 데이터 홈.""" | |
| return self.config_dirs.get(project) or self.projects_dir / project | |
| def data_dir(self, project: str) -> Path: | |
| """data(datasets·artifacts) 루트 — 항상 데이터 홈.""" | |
| return self.projects_dir / project | |
| def artifacts_dir(self, project: str) -> Path: | |
| """Run 산출물 디렉토리 — 항상 데이터 홈에 쓴다.""" | |
| return self.data_dir(project) / "artifacts" | |
| def prompts_dir(self, project: str) -> Path: | |
| """프롬프트 디렉토리 — 레포 관리 프로젝트면 git 쪽이 정본.""" | |
| return self.config_dir(project) / "prompts" | |
| def pipelines_dir(self, project: str) -> Path: | |
| """파이프라인 디렉토리 — 레포 관리 프로젝트면 git 쪽이 정본.""" | |
| return self.config_dir(project) / "pipelines" | |
| config = CLIConfig() | |