Add --limit-per-task (per-subset cap, evalscope --limit semantics; composable with --limit as intersection); execution-bench parity verified: official human-eval core 5/5 == our docker sandbox on same completions
This commit is contained in:
parent
89e721414f
commit
1da665fec4
@ -148,6 +148,7 @@ def _cmd_eval_run(args) -> int:
|
|||||||
|
|
||||||
report = asyncio.run(run_eval(
|
report = asyncio.run(run_eval(
|
||||||
ds, args.model, concurrency=args.concurrency, limit=args.limit,
|
ds, args.model, concurrency=args.concurrency, limit=args.limit,
|
||||||
|
limit_per_task=args.limit_per_task,
|
||||||
judge_spec=args.judge, env=args.env))
|
judge_spec=args.judge, env=args.env))
|
||||||
else:
|
else:
|
||||||
from evalharness.eval import evaluate
|
from evalharness.eval import evaluate
|
||||||
@ -262,7 +263,10 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
p.add_argument('--judge', default='', help='judge model spec for llm_judge recipes')
|
p.add_argument('--judge', default='', help='judge model spec for llm_judge recipes')
|
||||||
p.add_argument('--env', default='', help="agent environment (e.g. 'bfcl_mock') -> message pump")
|
p.add_argument('--env', default='', help="agent environment (e.g. 'bfcl_mock') -> message pump")
|
||||||
p.add_argument('--concurrency', type=int, default=32, help='parallel model calls (default 32)')
|
p.add_argument('--concurrency', type=int, default=32, help='parallel model calls (default 32)')
|
||||||
p.add_argument('--limit', type=int, help='evaluate only the first N samples')
|
p.add_argument('--limit', type=int, help='evaluate only the first N samples total')
|
||||||
|
p.add_argument('--limit-per-task', type=int,
|
||||||
|
help='first N samples PER subset/category (evalscope --limit semantics); '
|
||||||
|
'composable with --limit (intersection)')
|
||||||
p.add_argument('--out', help='save the EvalReport json here (single dataset)')
|
p.add_argument('--out', help='save the EvalReport json here (single dataset)')
|
||||||
p.add_argument('--out-dir', help='save reports/<name>.json + viz/<name>.txt + summary.md '
|
p.add_argument('--out-dir', help='save reports/<name>.json + viz/<name>.txt + summary.md '
|
||||||
'here (multi-dataset runs)')
|
'here (multi-dataset runs)')
|
||||||
|
|||||||
@ -35,6 +35,7 @@ async def generate_predictions(
|
|||||||
max_turns: int = 8,
|
max_turns: int = 8,
|
||||||
max_input_chars: int = 0,
|
max_input_chars: int = 0,
|
||||||
attach_context_keys: tuple = ('passage', 'context'),
|
attach_context_keys: tuple = ('passage', 'context'),
|
||||||
|
limit_per_task: Optional[int] = None,
|
||||||
few_shot_num: int = 0,
|
few_shot_num: int = 0,
|
||||||
few_shot_samples: Optional[List[Sample]] = None,
|
few_shot_samples: Optional[List[Sample]] = None,
|
||||||
few_shot_text: Optional[str] = None,
|
few_shot_text: Optional[str] = None,
|
||||||
@ -57,7 +58,7 @@ async def generate_predictions(
|
|||||||
if few_shot_text:
|
if few_shot_text:
|
||||||
parts.append(few_shot_text.strip()) # official exemplars, verbatim
|
parts.append(few_shot_text.strip()) # official exemplars, verbatim
|
||||||
elif few_shot_num and few_shot_samples:
|
elif few_shot_num and few_shot_samples:
|
||||||
letters_fs = 'ABCDEFGH'
|
letters_fs = 'ABCDEFGHIJ'
|
||||||
for fs in few_shot_samples[:few_shot_num]:
|
for fs in few_shot_samples[:few_shot_num]:
|
||||||
line = f'Question: {fs.input_text}'
|
line = f'Question: {fs.input_text}'
|
||||||
if fs.choices:
|
if fs.choices:
|
||||||
@ -73,7 +74,7 @@ async def generate_predictions(
|
|||||||
if sample.choices:
|
if sample.choices:
|
||||||
if prompt_style in ('strict_letter', 'auto'):
|
if prompt_style in ('strict_letter', 'auto'):
|
||||||
# evalscope/OpenAI-style contract: reply ONLY 'ANSWER: X'
|
# evalscope/OpenAI-style contract: reply ONLY 'ANSWER: X'
|
||||||
letters = 'ABCDEFGH'
|
letters = 'ABCDEFGHIJ'
|
||||||
opts = '\n'.join(f'{letters[i]}. {c}' for i, c in enumerate(sample.choices)
|
opts = '\n'.join(f'{letters[i]}. {c}' for i, c in enumerate(sample.choices)
|
||||||
if i < len(letters))
|
if i < len(letters))
|
||||||
question = (f'Answer the following multiple choice question. The entire '
|
question = (f'Answer the following multiple choice question. The entire '
|
||||||
@ -81,7 +82,7 @@ async def generate_predictions(
|
|||||||
f"'ANSWER: [LETTER]' (without quotes) where [LETTER] is one of "
|
f"'ANSWER: [LETTER]' (without quotes) where [LETTER] is one of "
|
||||||
f'{letters[:len(sample.choices)]}.\n\n{question}\n\n{opts}')
|
f'{letters[:len(sample.choices)]}.\n\n{question}\n\n{opts}')
|
||||||
else:
|
else:
|
||||||
letters = 'ABCDEFGH'
|
letters = 'ABCDEFGHIJ'
|
||||||
opts = '\n'.join(f'{letters[i]}. {c}' for i, c in enumerate(sample.choices)
|
opts = '\n'.join(f'{letters[i]}. {c}' for i, c in enumerate(sample.choices)
|
||||||
if i < len(letters))
|
if i < len(letters))
|
||||||
question = (f'{question}\n\n{opts}\n\n'
|
question = (f'{question}\n\n{opts}\n\n'
|
||||||
@ -141,12 +142,33 @@ async def generate_predictions(
|
|||||||
_progress(progress, done_count, len(samples), t0, total_usage)
|
_progress(progress, done_count, len(samples), t0, total_usage)
|
||||||
return {'raw': text, 'usage': out.usage.model_dump()}
|
return {'raw': text, 'usage': out.usage.model_dump()}
|
||||||
|
|
||||||
work = samples[:limit] if limit else samples
|
work = _apply_limits(samples, limit, limit_per_task)
|
||||||
preds = list(await asyncio.gather(*(one(s) for s in work)))
|
preds = list(await asyncio.gather(*(one(s) for s in work)))
|
||||||
usages = [p.get('usage', {}) for p in preds]
|
usages = [p.get('usage', {}) for p in preds]
|
||||||
return preds, usages, total_usage
|
return preds, usages, total_usage
|
||||||
|
|
||||||
|
|
||||||
|
def _apply_limits(samples: List[Sample], total: Optional[int],
|
||||||
|
per_task: Optional[int], dataset=None) -> List[Sample]:
|
||||||
|
"""total: cap the WHOLE run (ours semantics). per_task: cap each subset/
|
||||||
|
category (evalscope's --limit semantics) -- first N per group_key."""
|
||||||
|
if per_task:
|
||||||
|
seen: Dict[str, int] = {}
|
||||||
|
out = []
|
||||||
|
for s in samples:
|
||||||
|
key = str((s.metadata or {}).get('category')
|
||||||
|
or (s.metadata or {}).get('subject')
|
||||||
|
or (s.metadata or {}).get('test_category')
|
||||||
|
or getattr(getattr(dataset, 'spec', None), 'subset', 'default'))
|
||||||
|
if seen.get(key, 0) < per_task:
|
||||||
|
seen[key] = seen.get(key, 0) + 1
|
||||||
|
out.append(s)
|
||||||
|
samples = out
|
||||||
|
if total:
|
||||||
|
samples = samples[:total]
|
||||||
|
return samples
|
||||||
|
|
||||||
|
|
||||||
def _progress(progress: bool, done: int, total: int, t0: float, usage: Usage) -> None:
|
def _progress(progress: bool, done: int, total: int, t0: float, usage: Usage) -> None:
|
||||||
if progress and (done % 20 == 0 or done == total):
|
if progress and (done % 20 == 0 or done == total):
|
||||||
rate = done / max(time.time() - t0, 1e-6)
|
rate = done / max(time.time() - t0, 1e-6)
|
||||||
@ -168,6 +190,7 @@ async def run_eval(
|
|||||||
system: str = '',
|
system: str = '',
|
||||||
max_turns: int = 8,
|
max_turns: int = 8,
|
||||||
max_input_chars: int = 0,
|
max_input_chars: int = 0,
|
||||||
|
limit_per_task: Optional[int] = None,
|
||||||
few_shot_num: int = -1,
|
few_shot_num: int = -1,
|
||||||
prompt_style: str = 'strict_letter',
|
prompt_style: str = 'strict_letter',
|
||||||
) -> EvalReport:
|
) -> EvalReport:
|
||||||
@ -243,6 +266,7 @@ async def run_eval(
|
|||||||
adapter, samples, concurrency, progress=progress,
|
adapter, samples, concurrency, progress=progress,
|
||||||
gen_kwargs=gen_kwargs, env_factory=env_factory,
|
gen_kwargs=gen_kwargs, env_factory=env_factory,
|
||||||
system=system, max_turns=max_turns, max_input_chars=max_input_chars,
|
system=system, max_turns=max_turns, max_input_chars=max_input_chars,
|
||||||
|
limit_per_task=limit_per_task,
|
||||||
few_shot_num=few_shot_num,
|
few_shot_num=few_shot_num,
|
||||||
few_shot_samples=few_shot_samples, few_shot_text=few_shot_text,
|
few_shot_samples=few_shot_samples, few_shot_text=few_shot_text,
|
||||||
prompt_style=prompt_style)
|
prompt_style=prompt_style)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user