CRUXEval Benchmark

repository·main·Indexed 41 days ago

https://github.com/facebookresearch/cruxeval

A benchmark for evaluating code reasoning, understanding, and execution in Python. It consists of 800 tasks divided into input prediction (CRUXEval-I) and output prediction (CRUXEval-O), featuring tools for running inference on HuggingFace and OpenAI models, as well as scoring scripts to calculate pass@1 and pass@5 metrics.

Tokens
2.6K
Snippets
10
Records
13
Agent score
52%

What's inside CRUXEval

  1. Understand the CRUXEval benchmark construction process

    main

    The CRUXEval benchmark is contained in cruxeval.jsonl and is constructed through a three-stage pipeline:

    1. Data Generation: Functions and test inputs are generated using Code Llama 34B. The process uses prompts from data_generating_prompt.jsonl (generated by generate_function_prompts.py) which request a Python function using a specific standard library function (from str, dict, or list) along with 5 test inputs. Diversity is improved using few-shot examples from diverse_fewshot_examples.py.

    2. Filtering: Generations are filtered via filter/analyze_ops.py to ensure problems are short, low-complexity, and solvable by humans in about a minute. Criteria include:

      • Compile time: Code length between 75-300 characters, all arguments used, no syntax errors, and valid assert f(input) == output statements.
      • Runtime: Execution under 2 seconds, no uncaught exceptions, no floating point operations or true division, and restricted argument sizes (integer arguments $\leq 3$, string/list argument lengths $\leq 3$).
      • Code Quality: No imports (e.g., os, random), must be deterministic, and must not have side effects (e.g., modifying __builtins__).
    3. Dataset Selection: 800 samples are randomly selected from the filtered set to form the final benchmark.

    The final dataset is available as cruxeval.jsonl or on HuggingFace Datasets.

  2. Install dependencies for CRUXEval

    main

    Depending on your use case, install the appropriate requirements file:

    • Full installation: pip install -r requirements.txt
    • Scoring only: pip install -r requirements-base.txt
    • OpenAI models: pip install -r requirements-openai.txt
    • HuggingFace inference: pip install -r requirements-inference.txt

    Tested with Python 3.9 and CUDA 12.1.

    pip install -r requirements.txt
  3. Score your own model generations

    main

    To evaluate model outputs, first prepare a JSON file (e.g., generations.json) where keys are sample IDs and values are lists of strings representing the model's predictions.

    Format for CRUXEval-I (Input Prediction):

    {
        "sample_0": ["f([1, 1, 1, 1, 3, 3])", "f([])"],
        "sample_799": ["f('~neqe-;ew22')", "f('~neqe-;ew22')"]
    }

    Evaluation Steps:

    1. Navigate to the evaluation directory.
    2. Run evaluate_generations.py using the --mode flag:
      • Use --mode input for CRUXEval-I.
      • Use --mode output for CRUXEval-O.

    Example Command:

    python evaluate_generations.py \
        --generations_path generations.json \
        --scored_results_path generations_scored.json \
        --mode input

    The output file at --scored_results_path will contain raw_generations, raw_scored_generations, and the overall pass_at_1 and pass_at_5 scores.

    python evaluate_generations.py \
        --generations_path generations.json \
        --scored_results_path generations_scored.json \
        --mode input
  4. Score a batch of models and tabulate results

    main

    To evaluate multiple models in parallel using SLURM:

    1. Use the scripts in the evaluation directory:
      • evaluate_all_predictions_input.sh (for CRUXEval-I)
      • evaluate_all_predictions_output.sh (for CRUXEval-O)
    2. You may need to update --output, --error, --partition, and run_names.
    3. Use evaluation/print_evaluation_directories.py to automatically find directories in model_generations to populate run_names.
    4. To view results in a table, run evaluation/read_results.py.

    Results (including pass@1 and pass@5) are stored in evaluation/evaluation_results.

    python evaluation/read_results.py
  5. Run inference on HuggingFace models

    main

    CRUXEval provides SLURM-compatible scripts for running inference on HuggingFace models.

    1. Navigate to the inference directory.
    2. Run ./scripts/run_input_prediction.sh (for CRUXEval-I) or ./scripts/run_output_prediction.sh (for CRUXEval-O).

    Configuration: You can modify the following parameters in the scripts:

    • --output, --error, --partition (SLURM settings)
    • GPUS, batch_size, n_samples, temperatures, models, dirs

    Post-Inference Steps:

    1. The script generates shards in inference/model_generations_raw/shard_i.json (where i is the GPU index).
    2. Run python combine_generations.py to merge shards into a single file located at ../model_generations/{MODEL_INFO}/generations.json.
    3. Use the scoring instructions to evaluate the resulting file.

    Version Note:

    • For WizardCoder: Use transformers==4.31.0 and vllm==0.1.4.
    • For all other models: Use transformers==4.36.2 and vllm==0.2.6.
    cd inference
    ./scripts/run_input_prediction.sh
  6. Run inference on OpenAI models

    main

    To run inference using OpenAI models:

    1. Set your API key in the environment:
      export OPENAI_API_KEY=YOUR_KEY
    2. Navigate to the openai directory.
    3. Run the inference script:
      python openai_run.py

    Generations will be saved to ../model_generations/{MODEL_INFO}/generations.json.

    export OPENAI_API_KEY=YOUR_KEY
    cd openai
    python openai_run.py
  7. Install CRUXEval

    main

    To use CRUXEval, clone the repository and navigate to the directory:

    git clone git@github.com:facebookresearch/cruxeval.git
    cd cruxeval
    git clone git@github.com:facebookresearch/cruxeval.git
    cd cruxeval
  8. Load CRUXEval data from a JSONL file

    main

    You can load the CRUXEval dataset locally by reading the data/cruxeval.jsonl file. Each line in the file is a JSON object containing the code, input, and output fields required for evaluation.

    import json
    data = [json.loads(l) for l in open("data/cruxeval.jsonl", "r").readlines()]
  9. Load CRUXEval data using HuggingFace Datasets

    main

    Alternatively, you can load the dataset directly from the HuggingFace Hub using the datasets library. The evaluation data is located in the test split of the cruxeval-org/cruxeval dataset.

    from datasets import load_dataset
    data = load_dataset("cruxeval-org/cruxeval")["test"]
  10. Verify code correctness with check_correctness

    main

    To evaluate if a piece of code correctly handles a specific input and produces the expected output, use the check_correctness function from evaluation.utils_execute.

    Construct a test string by appending an assert statement to the source code. The format should be: {code}\nassert f({input}) == {output}.

    Pass this string to check_correctness along with a timeout value (in seconds) to prevent infinite loops during execution.

    from evaluation.utils_execute import check_correctness
    
    # Example construction
    code_to_check = f"{code}\nassert f({input}) == {output}"
    
    # Execute verification
    result = check_correctness(code_to_check, timeout=3)
    print(result)
  11. Reference CLI arguments for inference

    main

    The following arguments are available when running inference/main.py:

    ArgumentTypeDefaultDescription
    --modelstringcodeparrot/codeparrot-smallModel repo name on HF Hub or local path
    --tensor_parallel_sizeint1Number of tensor parallel replicas
    --revisionstringNoneModel revision to use
    --use_auth_tokenflagFalseUse token from huggingface-cli login (for private models)
    --trust_remote_codeflagFalseExecute custom code from the model author
    --tasksstringNoneEvaluation tasks (supports wildcard patterns, but only one task is supported at a time)
    --instruction_tokensstringNoneComma-separated instruction tokens (e.g. <user_message>,<assistant_message>)
    --batch_sizeint1Batch size for evaluation on each worker
    --max_length_generationint1024Max length of generated sequence (prompt + generation)
    --precisionstringbf16Model precision: fp32, fp16, or bf16
    --shuffleflagFalseShuffle dataset before evaluation
    --limitintNoneOnly solve the first N samples
    --startint0Starting index of samples
    --endintNoneEnding index of samples
    --postprocessflagTruePostprocess model outputs before execution (disabled via this flag)
    --cotflagFalseWhether to use Chain of Thought
    --save_generationsflagFalseWhether to save code generations
    --save_generations_pathstringgenerations.jsonPath for saving code generations
    --save_referencesflagFalseWhether to save reference solutions/tests
    --save_references_pathstringreferences.jsonPath for saving reference solutions/tests