Score MultiPL-E pass@k from a per-run temp dir - #328
Open
shaurya416 wants to merge 1 commit into
Open
shaurya416 wants to merge 1 commit into
shaurya416 wants to merge 1 commit into
Conversation
process_results wrote each problem and its .results.json into tempfile.gettempdir(), then computed pass@k over every *.results.json found there. Files left by an earlier run, or by the previous multiple-<lang> task in the same invocation, were averaged into the score, because problem names are shared across languages and nothing removes the files. Use tempfile.mkdtemp() so each call writes to and globs a directory of its own. The files are still kept after the run, as before. Add tests that fail on the old behaviour.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #327
Cause
GeneralMultiPLE.process_resultswrites each problem and its<name>.results.jsonintotempfile.gettempdir()(/tmpon Linux) and then computes pass@k overPath(temp_dir).glob("*.results.json"). Nothing removes those files, and problem names are the same in every MultiPL-E language (HumanEval_0_has_close_elements, ...). So any results file already in the system temp dir is averaged into the score: files from an earlier run, or from the previous task when severalmultiple-<lang>tasks run in one invocation. For example, with--tasks multiple-js,multiple-d, the js results for problems that d does not have are still in the temp dir when d is scored.Change
temp_dir = tempfile.gettempdir()becomestemp_dir = tempfile.mkdtemp(), so eachprocess_resultscall writes into, and globs, a directory of its own. Nothing else changes: the files are still kept after the run and the existing "Saved N problems in ..." line prints the new directory.tests/test_multiple.pyadds tests forprocess_results. They build the task without loading the dataset, pointtempfile.tempdirat pytest'stmp_path(standing in for the shared system temp dir), and replaceevaluate_problemwith a function that writes a results file in the same format without running any code.Validation
The new test file was run twice from a scratch directory outside the repository, against a small package holding the verbatim source of
GeneralMultiPLEand the top-level imports ofmultiple.py(taken withast.get_source_segment, once from the file before this change and once after), plus the verbatimget_test_results_json_path,evaluate_problem,estimatorandfor_file. Python 3.12.4, pytest 9.1.1.test_single_run_mixed(1 of 2 problems pass, clean dir)test_single_run_all_pass_and_all_fail(same names run twice)test_several_samples_per_problem(n=10, expects pass@1 0.15, pass@10 0.5)test_leftover_results_file_is_left_alone(another run's file is not deleted)test_leftover_results_file_is_not_scored(1 failing problem + 1 leftover file){'pass@1': 0.5} == {'pass@1': 0.0}test_previous_task_in_same_process_is_not_scored(js 3 problems, then d 2 problems){'pass@1': 0.3333333333333333} == {'pass@1': 0.0}Totals: before 2 failed, 4 passed; after 6 passed.
Stand-ins used in that scratch package (everything not listed was verbatim repository text):
numpy: a small list-backedarray/ndarray(mean(axis=0),k / arr,1.0 - arr, iteration),arange,prod, plusisscalarandbool_, whichpytest.approxlooks up whenever a module namednumpyis loaded.tqdm.tqdm: returns its iterable.datasets.load_dataset: raises if called; the tests never call it.bigcode_eval.base.Task: an empty class.__init__.pyfiles are empty (the realbigcode_eval/tasks/__init__.pyimports every task), andfrom .containerized_eval import eval_string_scriptwas left out ofevaluation.py;evaluate_problemis replaced by the test anyway.flake8 7.4.1 (unpinned, as in CI, where the lint step is commented out), default settings:
tests/test_multiple.pyis clean;bigcode_eval/tasks/multiple.pyreports the same 19 existing warnings before and after.Not run: the new test inside the real package with the real dependencies (numpy, datasets, transformers), the existing suite in
tests/, any real MultiPL-E evaluation or code execution, the Docker image, and any formatter (the repository pins none and has no formatter config).Notes
tempfile.TemporaryDirectory()would also delete them, but that would remove the per-problem results people can read after a run, so I left it out.estimatorreturns 1.0 whenn - c < k, so a stale file with fewer samples thankcounts as a pass) can no longer come from leftovers, because the glob only sees this run's files.for_fileitself is unchanged.