Spaces:
Running
Running
File size: 6,003 Bytes
9c84f9d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | """๋ฐ์ดํฐ์
ํ์ผ์์ ํ์คํฌ๋ฅผ ๋ฐ๊ฒฌํ๋ค โ ๋งค๋ํ์คํธ์ ์์ผ๋ก ์ ์ง ์๋๋ค.
์: ํ์คํฌ๋ ์ฌ์ค์ "๋ฐ์ดํฐ์
ํ์ผ + ์ฑ์ ์ค์ "์ธ๋ฐ, ํ์ผ์ด ์๋ค๋ ์ฌ์ค์
`project.yaml` ์ ํ ์ค์ฉ ์ฎ๊ฒจ ์ ์ด ์๋ค(chosun-proofreading ์ 59์ค). ์์ผ๋ก
์ฎ๊ฒจ ์ ๋ ๋ชฉ๋ก์ ๋ฐ๋์ ์๋ณธ๊ณผ ๊ฐ๋ผ์ง๋ค โ ์ค์ ๋ก ๋ฐ์ดํฐ์
์ด ์ฌ๋ผ์ง ๋ค์๋
๋งค๋ํ์คํธ์๋ง ๋จ์ ์ ๋ น ํ์คํฌ ๋ ๊ฐ(`critical-issue`ยท`edge-case`)๊ฐ ์๊ฒผ๊ณ ,
`solar-eval tasks list` ์๋ ๋ณด์ด์ง๋ง ๋๋ฆฌ๋ฉด ์ฃฝ๋ ์ํ๋ก ๋ฐฉ์น๋๋ค.
๋ฐ๊ฒฌ ๊ท์น์ ํ์ผ ์ด๋ฆ์์ ํ์คํฌ ์ด๋ฆ์ ๋ง๋ ๋ค:
discover:
- glob: critical_issue/*_v2.jsonl # datasets/ ๊ธฐ์ค ์๋ glob
name: ci-v2-{stem} # {stem} = ํ์ผ stem, '_' โ '-'
strip_suffix: _v2 # stem ์์ ๋จผ์ ๋ผ๋ ๊ผฌ๋ฆฌํ
**๋ช
์ ํ์คํฌ๊ฐ ์ด๊ธด๋ค.** ์ด๋ฏธ `tasks:` ์ ์๋ dataset_path ๋ ๋ฐ๊ฒฌ ๋์์์
๋น ์ง๋ฏ๋ก, ๊ท์น์ ์ ๋ง๋ ์ด๋ฆ(`paragraph`, `yul-ryul`)์ ์์ ๊ทธ๋๋ก ์ ์ด ๋๋ฉด
๋๋ค. ๊ณผ๊ฑฐ run ์ด ๊ทธ ์ด๋ฆ์ผ๋ก ๊ธฐ๋ก๋ผ ์์ด ์ด๋ฆ์ ๋ฐ๊พธ๋ฉด evalhub ์์ ๊ณ๋ณด๊ฐ
๋์ด์ง๊ธฐ ๋๋ฌธ์, ์ด ์ฐ์ ์์๋ ํํ ๋์์ด ์๋๋ค.
"""
import logging
from pathlib import Path
from typing import Any
logger = logging.getLogger(__name__)
#: `name` ํ
ํ๋ฆฟ์์ ํ์ผ stem ์ผ๋ก ์นํ๋๋ ์๋ฆฌํ์์.
STEM_PLACEHOLDER = "{stem}"
class TaskDiscoveryError(ValueError):
"""๋ฐ๊ฒฌ ๊ท์น์ด ์๋ชป๋์ ๋ โ ์กฐ์ฉํ ๋น ๋ชฉ๋ก์ ๋ง๋ค์ง ์๋๋ค."""
def discover_tasks(config: dict[str, Any], data_root: Path | str | None) -> list[dict[str, Any]]:
"""`discover:` ๊ท์น์ผ๋ก ํ์คํฌ ๋ชฉ๋ก์ ๋ง๋ ๋ค.
Args:
config: project.yaml dict. `discover`, `dataset.repo`, `tasks` ๋ฅผ ์ฝ๋๋ค.
data_root: ๋ฐ์ดํฐ ๋ฃจํธ(projects_dir). `dataset.repo` ๊ฐ ์ด ์๋์ ์๋ค.
Returns:
์๋ก ๋ฐ๊ฒฌ๋ ํ์คํฌ dict ๋ชฉ๋ก (๋ช
์ ํ์คํฌ์ ์ค๋ณต๋์ง ์๋ ๊ฒ๋ง).
`discover` ๊ฐ ์์ผ๋ฉด ๋น ๋ชฉ๋ก.
Raises:
TaskDiscoveryError: ๊ท์น์ `glob`/`name` ์ด ์๊ฑฐ๋ ์ด๋ฆ์ด ์ถฉ๋ํ ๋.
"""
rules = config.get("discover")
if not rules:
return []
if not isinstance(rules, list):
raise TaskDiscoveryError("`discover` must be a list of rules")
dataset_root = _dataset_root(config, data_root)
if dataset_root is None or not dataset_root.is_dir():
logger.warning(
"Task discovery skipped for %s: dataset root not found (%s)",
config.get("name"),
dataset_root,
)
return []
claimed_paths = {
t.get("dataset_path") for t in config.get("tasks", []) or [] if isinstance(t, dict)
}
claimed_names = {t.get("name") for t in config.get("tasks", []) or [] if isinstance(t, dict)}
discovered: list[dict[str, Any]] = []
seen_names: dict[str, str] = {}
for rule in rules:
discovered.extend(_apply_rule(rule, dataset_root, claimed_paths, claimed_names, seen_names))
return sorted(discovered, key=lambda t: t["name"])
def _apply_rule(
rule: Any,
dataset_root: Path,
claimed_paths: set[Any],
claimed_names: set[Any],
seen_names: dict[str, str],
) -> list[dict[str, Any]]:
"""๊ท์น ํ๋๋ฅผ ์ ์ฉํด ํ์คํฌ๋ฅผ ๋ง๋ ๋ค."""
if not isinstance(rule, dict):
raise TaskDiscoveryError(f"discover rule must be a mapping, got {type(rule).__name__}")
pattern = rule.get("glob")
name_template = rule.get("name")
if not pattern or not name_template:
raise TaskDiscoveryError(f"discover rule needs `glob` and `name`: {rule!r}")
if STEM_PLACEHOLDER not in name_template:
raise TaskDiscoveryError(
f"discover `name` must contain {STEM_PLACEHOLDER}: {name_template!r}"
)
strip_suffix = rule.get("strip_suffix") or ""
extra = {k: v for k, v in rule.items() if k not in ("glob", "name", "strip_suffix")}
tasks: list[dict[str, Any]] = []
matches = sorted(dataset_root.glob(pattern))
if not matches:
logger.warning("discover rule matched no files: %s (under %s)", pattern, dataset_root)
for file in matches:
if not file.is_file():
continue
dataset_path = file.relative_to(dataset_root).as_posix()
if dataset_path in claimed_paths:
continue # ๋ช
์ ํ์คํฌ๊ฐ ์ด๋ฏธ ๊ฐ๋ฆฌํค๋ ํ์ผ โ ์ด๋ฆ ๊ณ๋ณด๋ฅผ ์งํจ๋ค
task_name = _task_name(file.stem, strip_suffix, name_template)
if task_name in claimed_names:
continue
previous = seen_names.get(task_name)
if previous is not None and previous != dataset_path:
raise TaskDiscoveryError(
f"discover produced duplicate task name {task_name!r} "
f"for {previous} and {dataset_path}"
)
seen_names[task_name] = dataset_path
tasks.append({"name": task_name, "dataset_path": dataset_path, **extra})
return tasks
def _task_name(stem: str, strip_suffix: str, template: str) -> str:
"""ํ์ผ stem โ ํ์คํฌ ์ด๋ฆ. ๊ผฌ๋ฆฌํ๋ฅผ ๋ผ๊ณ `_` ๋ฅผ `-` ๋ก ๋ฐ๊พผ๋ค."""
if strip_suffix and stem.endswith(strip_suffix):
stem = stem[: -len(strip_suffix)]
return template.replace(STEM_PLACEHOLDER, stem.replace("_", "-"))
def _dataset_root(config: dict[str, Any], data_root: Path | str | None) -> Path | None:
"""`dataset.repo` ๋ฅผ ๋ฐ์ดํฐ ๋ฃจํธ ๊ธฐ์ค์ผ๋ก ํผ๋ค. ์๊ฒฉ(HF) ๋ฐ์ดํฐ์
์ ์ค์บํ์ง ์๋๋ค."""
dataset = config.get("dataset") or {}
if dataset.get("source") not in (None, "local"):
return None
repo = dataset.get("repo")
if not repo:
return None
repo_path = Path(repo)
if repo_path.is_absolute():
return repo_path
if data_root is None:
return None
return Path(data_root) / repo_path
|