77
88
99def find_eval_sets (root : Path ) -> List [Path ]:
10- """Return directories that contain a meta_env.json (one set per job)."""
10+ """Return directories that contain a meta_env.json (one set per job).
11+
12+ New structure: each downloaded artifact is placed under
13+ eval_results/<artifact-name>/ with flat files inside, e.g.:
14+ - meta_env.json
15+ - SUMMARY.md
16+ - results_*.json
17+
18+ We first check immediate child directories for meta_env.json to avoid
19+ descending unnecessarily. If nothing is found (backward compatibility),
20+ fall back to recursive search.
21+ """
1122 out : List [Path ] = []
23+ # Prefer immediate children (one directory per artifact)
24+ try :
25+ for d in root .iterdir ():
26+ if d .is_dir () and (d / 'meta_env.json' ).exists ():
27+ out .append (d )
28+ except Exception :
29+ pass
30+ if out :
31+ return out
32+ # Fallback: recursive (legacy structure)
1233 for p in root .rglob ('meta_env.json' ):
1334 out .append (p .parent )
1435 return out
@@ -23,32 +44,49 @@ def load_json(path: Path) -> Optional[Dict[str, Any]]:
2344
2445
2546def detect_eval_jsons (d : Path ) -> Tuple [Optional [Path ], Optional [Path ]]:
26- """Return (lm_eval_json, lighteval_json) if present (latest by mtime)."""
27- lm : List [Tuple [float , Path ]] = []
28- le : List [Tuple [float , Path ]] = []
29- for p in d .rglob ('*.json' ):
30- if p .name == 'meta_env.json' :
31- continue
32- data = load_json (p )
33- if not isinstance (data , dict ):
34- continue
35- # Heuristics similar to utils/lm_eval_to_md.py
36- if 'lm_eval_version' in data or 'pretty_env_info' in data :
37- try :
38- lm .append ((p .stat ().st_mtime , p ))
39- except Exception :
40- lm .append ((0 , p ))
41- elif 'config_general' in data and 'results' in data :
42- try :
43- le .append ((p .stat ().st_mtime , p ))
44- except Exception :
45- le .append ((0 , p ))
46- elif 'results' in data :
47- # Fallback: treat as lm-eval JSON
48- try :
49- lm .append ((p .stat ().st_mtime , p ))
50- except Exception :
51- lm .append ((0 , p ))
47+ """Return (lm_eval_json, lighteval_json) if present (latest by mtime).
48+
49+ New structure places result JSONs flat in the artifact directory. We
50+ first check only the immediate directory for JSONs, then fall back to
51+ recursive search for backward compatibility.
52+ """
53+ def scan_jsons (paths : List [Path ]) -> Tuple [List [Tuple [float , Path ]], List [Tuple [float , Path ]]]:
54+ lm : List [Tuple [float , Path ]] = []
55+ le : List [Tuple [float , Path ]] = []
56+ for p in paths :
57+ if p .name == 'meta_env.json' :
58+ continue
59+ data = load_json (p )
60+ if not isinstance (data , dict ):
61+ continue
62+ # Heuristics similar to utils/lm_eval_to_md.py
63+ if 'lm_eval_version' in data or 'pretty_env_info' in data :
64+ try :
65+ lm .append ((p .stat ().st_mtime , p ))
66+ except Exception :
67+ lm .append ((0 , p ))
68+ elif 'config_general' in data and 'results' in data :
69+ try :
70+ le .append ((p .stat ().st_mtime , p ))
71+ except Exception :
72+ le .append ((0 , p ))
73+ elif 'results' in data :
74+ # Fallback: treat as lm-eval JSON
75+ try :
76+ lm .append ((p .stat ().st_mtime , p ))
77+ except Exception :
78+ lm .append ((0 , p ))
79+ return lm , le
80+
81+ # 1) Prefer immediate JSONs (flat structure)
82+ immediate_jsons = list (d .glob ('results*.json' )) + [p for p in d .glob ('*.json' ) if p .name != 'meta_env.json' ]
83+ lm , le = scan_jsons (immediate_jsons )
84+
85+ # 2) If nothing found, fallback to deep scan (legacy)
86+ if not lm and not le :
87+ deep_jsons = list (d .rglob ('*.json' ))
88+ lm , le = scan_jsons (deep_jsons )
89+
5290 lm_path = sorted (lm , key = lambda x : x [0 ])[- 1 ][1 ] if lm else None
5391 le_path = sorted (le , key = lambda x : x [0 ])[- 1 ][1 ] if le else None
5492 return lm_path , le_path
0 commit comments