mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-04-29 03:00:45 -04:00
Compare commits
1 Commits
kjain14-ma
...
openhands-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38f1b56172 |
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
@@ -10,6 +10,12 @@ updates:
|
||||
pre-commit:
|
||||
patterns:
|
||||
- "pre-commit"
|
||||
llama:
|
||||
patterns:
|
||||
- "llama*"
|
||||
chromadb:
|
||||
patterns:
|
||||
- "chromadb"
|
||||
browsergym:
|
||||
patterns:
|
||||
- "browsergym*"
|
||||
|
||||
2
.github/workflows/dummy-agent-test.yml
vendored
2
.github/workflows/dummy-agent-test.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
python-version: '3.12'
|
||||
cache: 'poetry'
|
||||
- name: Install Python dependencies using Poetry
|
||||
run: poetry install --without evaluation
|
||||
run: poetry install --without evaluation,llama-index
|
||||
- name: Build Environment
|
||||
run: make build
|
||||
- name: Run tests
|
||||
|
||||
41
.github/workflows/ghcr-build.yml
vendored
41
.github/workflows/ghcr-build.yml
vendored
@@ -41,10 +41,8 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3.6.0
|
||||
uses: docker/setup-qemu-action@v3.4.0
|
||||
with:
|
||||
image: tonistiigi/binfmt:latest
|
||||
- name: Login to GHCR
|
||||
@@ -56,22 +54,22 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Lowercase Repository Owner
|
||||
run: |
|
||||
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
|
||||
- name: Build and push app image
|
||||
if: "!github.event.pull_request.head.repo.fork"
|
||||
run: |
|
||||
./containers/build.sh -i openhands -o ${{ env.REPO_OWNER }} --push
|
||||
./containers/build.sh -i openhands -o ${{ github.repository_owner }} --push
|
||||
- name: Build app image
|
||||
if: "github.event.pull_request.head.repo.fork"
|
||||
run: |
|
||||
./containers/build.sh -i openhands -o ${{ env.REPO_OWNER }} --load
|
||||
./containers/build.sh -i openhands -o ${{ github.repository_owner }} --load
|
||||
- name: Get hash in App Image
|
||||
id: get_hash_in_app_image
|
||||
run: |
|
||||
# Lowercase the repository owner
|
||||
export REPO_OWNER=${{ github.repository_owner }}
|
||||
REPO_OWNER=$(echo $REPO_OWNER | tr '[:upper:]' '[:lower:]')
|
||||
# Run the build script in the app image
|
||||
docker run -e SANDBOX_USER_ID=0 -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/${{ env.REPO_OWNER }}/openhands:${{ env.RELEVANT_SHA }} /bin/bash -c "mkdir -p containers/runtime; python3 openhands/runtime/utils/runtime_build.py --base_image ${{ env.BASE_IMAGE_FOR_HASH_EQUIVALENCE_TEST }} --build_folder containers/runtime --force_rebuild" 2>&1 | tee docker-outputs.txt
|
||||
docker run -e SANDBOX_USER_ID=0 -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/${REPO_OWNER}/openhands:${{ env.RELEVANT_SHA }} /bin/bash -c "mkdir -p containers/runtime; python3 openhands/runtime/utils/runtime_build.py --base_image ${{ env.BASE_IMAGE_FOR_HASH_EQUIVALENCE_TEST }} --build_folder containers/runtime --force_rebuild" 2>&1 | tee docker-outputs.txt
|
||||
# Get the hash from the build script
|
||||
hash_from_app_image=$(cat docker-outputs.txt | grep "Hash for docker build directory" | awk -F "): " '{print $2}' | uniq | head -n1)
|
||||
echo "hash_from_app_image=$hash_from_app_image" >> $GITHUB_OUTPUT
|
||||
@@ -92,10 +90,8 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3.6.0
|
||||
uses: docker/setup-qemu-action@v3.4.0
|
||||
with:
|
||||
image: tonistiigi/binfmt:latest
|
||||
- name: Login to GHCR
|
||||
@@ -126,19 +122,16 @@ jobs:
|
||||
run: make install-python-dependencies
|
||||
- name: Create source distribution and Dockerfile
|
||||
run: poetry run python3 openhands/runtime/utils/runtime_build.py --base_image ${{ matrix.base_image.image }} --build_folder containers/runtime --force_rebuild
|
||||
- name: Lowercase Repository Owner
|
||||
run: |
|
||||
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
|
||||
- name: Build and push runtime image ${{ matrix.base_image.image }}
|
||||
if: github.event.pull_request.head.repo.fork != true
|
||||
run: |
|
||||
./containers/build.sh -i runtime -o ${{ env.REPO_OWNER }} --push -t ${{ matrix.base_image.tag }}
|
||||
./containers/build.sh -i runtime -o ${{ github.repository_owner }} --push -t ${{ matrix.base_image.tag }}
|
||||
# Forked repos can't push to GHCR, so we need to upload the image as an artifact
|
||||
- name: Build runtime image ${{ matrix.base_image.image }} for fork
|
||||
if: github.event.pull_request.head.repo.fork
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
tags: ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }}
|
||||
tags: ghcr.io/all-hands-ai/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image.tag }}
|
||||
outputs: type=docker,dest=/tmp/runtime-${{ matrix.base_image.tag }}.tar
|
||||
context: containers/runtime
|
||||
- name: Upload runtime image for fork
|
||||
@@ -158,8 +151,6 @@ jobs:
|
||||
base_image: ['nikolaik']
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Cache Poetry dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
@@ -242,9 +233,6 @@ jobs:
|
||||
run: pipx install poetry
|
||||
- name: Install Python dependencies using Poetry
|
||||
run: make install-python-dependencies
|
||||
- name: Lowercase Repository Owner
|
||||
run: |
|
||||
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
|
||||
- name: Run docker runtime tests
|
||||
run: |
|
||||
# We install pytest-xdist in order to run tests across CPUs
|
||||
@@ -253,7 +241,8 @@ jobs:
|
||||
# Install to be able to retry on failures for flaky tests
|
||||
poetry run pip install pytest-rerunfailures
|
||||
|
||||
image_name=ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image }}
|
||||
image_name=ghcr.io/${{ github.repository_owner }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image }}
|
||||
image_name=$(echo $image_name | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
TEST_RUNTIME=docker \
|
||||
SANDBOX_USER_ID=$(id -u) \
|
||||
@@ -307,9 +296,6 @@ jobs:
|
||||
run: pipx install poetry
|
||||
- name: Install Python dependencies using Poetry
|
||||
run: make install-python-dependencies
|
||||
- name: Lowercase Repository Owner
|
||||
run: |
|
||||
echo REPO_OWNER=$(echo ${{ github.repository_owner }} | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV
|
||||
- name: Run runtime tests
|
||||
run: |
|
||||
# We install pytest-xdist in order to run tests across CPUs
|
||||
@@ -318,7 +304,8 @@ jobs:
|
||||
# Install to be able to retry on failures for flaky tests
|
||||
poetry run pip install pytest-rerunfailures
|
||||
|
||||
image_name=ghcr.io/${{ env.REPO_OWNER }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image }}
|
||||
image_name=ghcr.io/${{ github.repository_owner }}/runtime:${{ env.RELEVANT_SHA }}-${{ matrix.base_image }}
|
||||
image_name=$(echo $image_name | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
TEST_RUNTIME=docker \
|
||||
SANDBOX_USER_ID=$(id -u) \
|
||||
|
||||
77
.github/workflows/integration-runner.yml
vendored
77
.github/workflows/integration-runner.yml
vendored
@@ -40,11 +40,6 @@ jobs:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: "poetry"
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.x'
|
||||
|
||||
- name: Comment on PR if 'integration-test' label is present
|
||||
if: github.event_name == 'pull_request' && github.event.label.name == 'integration-test'
|
||||
uses: KeisukeYamashita/create-comment@v1
|
||||
@@ -54,7 +49,7 @@ jobs:
|
||||
Hi! I started running the integration tests on your PR. You will receive a comment with the results shortly.
|
||||
|
||||
- name: Install Python dependencies using Poetry
|
||||
run: poetry install --without evaluation
|
||||
run: poetry install --without evaluation,llama-index
|
||||
|
||||
- name: Configure config.toml for testing with Haiku
|
||||
env:
|
||||
@@ -117,6 +112,68 @@ jobs:
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Run DelegatorAgent tests for Haiku, limited to t01 and t02
|
||||
- name: Wait a little bit (again)
|
||||
run: sleep 5
|
||||
|
||||
- name: Configure config.toml for testing DelegatorAgent (Haiku)
|
||||
env:
|
||||
LLM_MODEL: "litellm_proxy/claude-3-5-haiku-20241022"
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }}
|
||||
MAX_ITERATIONS: 30
|
||||
run: |
|
||||
echo "[llm.eval]" > config.toml
|
||||
echo "model = \"$LLM_MODEL\"" >> config.toml
|
||||
echo "api_key = \"$LLM_API_KEY\"" >> config.toml
|
||||
echo "base_url = \"$LLM_BASE_URL\"" >> config.toml
|
||||
echo "temperature = 0.0" >> config.toml
|
||||
|
||||
- name: Run integration test evaluation for DelegatorAgent (Haiku)
|
||||
env:
|
||||
SANDBOX_FORCE_REBUILD_RUNTIME: True
|
||||
run: |
|
||||
poetry run ./evaluation/integration_tests/scripts/run_infer.sh llm.eval HEAD DelegatorAgent '' 30 $N_PROCESSES "t01_fix_simple_typo,t02_add_bash_hello" 'delegator_haiku_run'
|
||||
|
||||
# Find and export the delegator test results
|
||||
REPORT_FILE_DELEGATOR_HAIKU=$(find evaluation/evaluation_outputs/outputs/integration_tests/DelegatorAgent/*haiku*_maxiter_30_N* -name "report.md" -type f | head -n 1)
|
||||
echo "REPORT_FILE_DELEGATOR_HAIKU: $REPORT_FILE_DELEGATOR_HAIKU"
|
||||
echo "INTEGRATION_TEST_REPORT_DELEGATOR_HAIKU<<EOF" >> $GITHUB_ENV
|
||||
cat $REPORT_FILE_DELEGATOR_HAIKU >> $GITHUB_ENV
|
||||
echo >> $GITHUB_ENV
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
|
||||
# -------------------------------------------------------------
|
||||
# Run DelegatorAgent tests for DeepSeek, limited to t01 and t02
|
||||
- name: Wait a little bit (again)
|
||||
run: sleep 5
|
||||
|
||||
- name: Configure config.toml for testing DelegatorAgent (DeepSeek)
|
||||
env:
|
||||
LLM_MODEL: "litellm_proxy/deepseek-chat"
|
||||
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
|
||||
LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }}
|
||||
MAX_ITERATIONS: 30
|
||||
run: |
|
||||
echo "[llm.eval]" > config.toml
|
||||
echo "model = \"$LLM_MODEL\"" >> config.toml
|
||||
echo "api_key = \"$LLM_API_KEY\"" >> config.toml
|
||||
echo "base_url = \"$LLM_BASE_URL\"" >> config.toml
|
||||
echo "temperature = 0.0" >> config.toml
|
||||
- name: Run integration test evaluation for DelegatorAgent (DeepSeek)
|
||||
env:
|
||||
SANDBOX_FORCE_REBUILD_RUNTIME: True
|
||||
run: |
|
||||
poetry run ./evaluation/integration_tests/scripts/run_infer.sh llm.eval HEAD DelegatorAgent '' 30 $N_PROCESSES "t01_fix_simple_typo,t02_add_bash_hello" 'delegator_deepseek_run'
|
||||
|
||||
# Find and export the delegator test results
|
||||
REPORT_FILE_DELEGATOR_DEEPSEEK=$(find evaluation/evaluation_outputs/outputs/integration_tests/DelegatorAgent/deepseek*_maxiter_30_N* -name "report.md" -type f | head -n 1)
|
||||
echo "REPORT_FILE_DELEGATOR_DEEPSEEK: $REPORT_FILE_DELEGATOR_DEEPSEEK"
|
||||
echo "INTEGRATION_TEST_REPORT_DELEGATOR_DEEPSEEK<<EOF" >> $GITHUB_ENV
|
||||
cat $REPORT_FILE_DELEGATOR_DEEPSEEK >> $GITHUB_ENV
|
||||
echo >> $GITHUB_ENV
|
||||
echo "EOF" >> $GITHUB_ENV
|
||||
# -------------------------------------------------------------
|
||||
# Run VisualBrowsingAgent tests for DeepSeek, limited to t05 and t06
|
||||
- name: Wait a little bit (again)
|
||||
run: sleep 5
|
||||
@@ -151,7 +208,7 @@ jobs:
|
||||
run: |
|
||||
TIMESTAMP=$(date +'%y-%m-%d-%H-%M')
|
||||
cd evaluation/evaluation_outputs/outputs # Change to the outputs directory
|
||||
tar -czvf ../../../integration_tests_${TIMESTAMP}.tar.gz integration_tests/CodeActAgent/* integration_tests/VisualBrowsingAgent/* # Only include the actual result directories
|
||||
tar -czvf ../../../integration_tests_${TIMESTAMP}.tar.gz integration_tests/CodeActAgent/* integration_tests/DelegatorAgent/* integration_tests/VisualBrowsingAgent/* # Only include the actual result directories
|
||||
|
||||
- name: Upload evaluation results as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -192,6 +249,12 @@ jobs:
|
||||
**Integration Tests Report (DeepSeek)**
|
||||
DeepSeek LLM Test Results:
|
||||
${{ env.INTEGRATION_TEST_REPORT_DEEPSEEK }}
|
||||
---
|
||||
**Integration Tests Report Delegator (Haiku)**
|
||||
${{ env.INTEGRATION_TEST_REPORT_DELEGATOR_HAIKU }}
|
||||
---
|
||||
**Integration Tests Report Delegator (DeepSeek)**
|
||||
${{ env.INTEGRATION_TEST_REPORT_DELEGATOR_DEEPSEEK }}
|
||||
---
|
||||
**Integration Tests Report VisualBrowsing (DeepSeek)**
|
||||
${{ env.INTEGRATION_TEST_REPORT_VISUALBROWSING_DEEPSEEK }}
|
||||
|
||||
4
.github/workflows/py-unit-tests.yml
vendored
4
.github/workflows/py-unit-tests.yml
vendored
@@ -44,11 +44,11 @@ jobs:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'poetry'
|
||||
- name: Install Python dependencies using Poetry
|
||||
run: poetry install --without evaluation
|
||||
run: poetry install --without evaluation,llama-index
|
||||
- name: Build Environment
|
||||
run: make build
|
||||
- name: Run Tests
|
||||
run: poetry run pytest --forked -n auto --cov=openhands --cov-report=xml -svv ./tests/unit
|
||||
run: poetry run pytest --forked -n auto --cov=openhands --cov-report=xml -svv ./tests/unit --ignore=tests/unit/test_long_term_memory.py
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
env:
|
||||
|
||||
55
CITATION.cff
55
CITATION.cff
@@ -1,55 +0,0 @@
|
||||
cff-version: 1.2.0
|
||||
message: "If you use this software, please cite it using the following metadata."
|
||||
title: "OpenHands: An Open Platform for AI Software Developers as Generalist Agents"
|
||||
authors:
|
||||
- family-names: Wang
|
||||
given-names: Xingyao
|
||||
- family-names: Li
|
||||
given-names: Boxuan
|
||||
- family-names: Song
|
||||
given-names: Yufan
|
||||
- family-names: Xu
|
||||
given-names: Frank F.
|
||||
- family-names: Tang
|
||||
given-names: Xiangru
|
||||
- family-names: Zhuge
|
||||
given-names: Mingchen
|
||||
- family-names: Pan
|
||||
given-names: Jiayi
|
||||
- family-names: Song
|
||||
given-names: Yueqi
|
||||
- family-names: Li
|
||||
given-names: Bowen
|
||||
- family-names: Singh
|
||||
given-names: Jaskirat
|
||||
- family-names: Tran
|
||||
given-names: Hoang H.
|
||||
- family-names: Li
|
||||
given-names: Fuqiang
|
||||
- family-names: Ma
|
||||
given-names: Ren
|
||||
- family-names: Zheng
|
||||
given-names: Mingzhang
|
||||
- family-names: Qian
|
||||
given-names: Bill
|
||||
- family-names: Shao
|
||||
given-names: Yanjun
|
||||
- family-names: Muennighoff
|
||||
given-names: Niklas
|
||||
- family-names: Zhang
|
||||
given-names: Yizhe
|
||||
- family-names: Hui
|
||||
given-names: Binyuan
|
||||
- family-names: Lin
|
||||
given-names: Junyang
|
||||
- family-names: Brennan
|
||||
given-names: Robert
|
||||
- family-names: Peng
|
||||
given-names: Hao
|
||||
- family-names: Ji
|
||||
given-names: Heng
|
||||
- family-names: Neubig
|
||||
given-names: Graham
|
||||
year: 2024
|
||||
doi: "10.48550/arXiv.2407.16741"
|
||||
url: "https://arxiv.org/abs/2407.16741"
|
||||
@@ -100,7 +100,7 @@ poetry run pytest ./tests/unit/test_*.py
|
||||
To reduce build time (e.g., if no changes were made to the client-runtime component), you can use an existing Docker container image by
|
||||
setting the SANDBOX_RUNTIME_CONTAINER_IMAGE environment variable to the desired Docker image.
|
||||
|
||||
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.28-nikolaik`
|
||||
Example: `export SANDBOX_RUNTIME_CONTAINER_IMAGE=ghcr.io/all-hands-ai/runtime:0.26-nikolaik`
|
||||
|
||||
## Develop inside Docker container
|
||||
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
These are the procedures and guidelines on how issues are triaged in this repo by the maintainers.
|
||||
|
||||
## General
|
||||
* All issues must be tagged with **enhancement**, **bug** or **troubleshooting/help**.
|
||||
* Issues may be tagged with what it relates to (**agent quality**, **frontend**, **resolver**, etc.).
|
||||
* Most issues must be tagged with **enhancement** or **bug**.
|
||||
* Issues may be tagged with what it relates to (**backend**, **frontend**, **agent quality**, etc.).
|
||||
|
||||
## Severity
|
||||
* **Low**: Minor issues or affecting single user.
|
||||
* **Medium**: Affecting multiple users.
|
||||
* **High**: High visibility issues or affecting many users.
|
||||
* **Critical**: Affecting all users or potential security issues.
|
||||
|
||||
## Effort
|
||||
@@ -19,14 +18,8 @@ These are the procedures and guidelines on how issues are triaged in this repo b
|
||||
|
||||
## Not Enough Information
|
||||
* User is asked to provide more information (logs, how to reproduce, etc.) when the issue is not clear.
|
||||
* If an issue is unclear and the author does not provide more information or respond to a request,
|
||||
the issue may be closed as **not planned** (Usually after a week).
|
||||
* If an issue is unclear and the author does not provide more information or respond to a request, the issue may be closed as **not planned** (Usually after a week).
|
||||
|
||||
## Multiple Requests/Fixes in One Issue
|
||||
* These issues will be narrowed down to one request/fix so the issue is more easily tracked and fixed.
|
||||
* Issues may be broken down into multiple issues if required.
|
||||
|
||||
## Stale and Auto Closures
|
||||
* In order to keep a maintainable backlog, issues that have no activity within 30 days are automatically marked as **Stale**.
|
||||
* If issues marked as **Stale** continue to have no activity for 7 more days, they will automatically be closed as not planned.
|
||||
* Issues may be reopened by maintainers if deemed important.
|
||||
|
||||
31
Makefile
31
Makefile
@@ -133,7 +133,7 @@ install-python-dependencies:
|
||||
export HNSWLIB_NO_NATIVE=1; \
|
||||
poetry run pip install chroma-hnswlib; \
|
||||
fi
|
||||
@poetry install
|
||||
@poetry install --without llama-index
|
||||
@if [ -f "/etc/manjaro-release" ]; then \
|
||||
echo "$(BLUE)Detected Manjaro Linux. Installing Playwright dependencies...$(RESET)"; \
|
||||
poetry run pip install playwright; \
|
||||
@@ -265,6 +265,35 @@ setup-config-prompts:
|
||||
@read -p "Enter your LLM base URL [mostly used for local LLMs, leave blank if not needed - example: http://localhost:5001/v1/]: " llm_base_url; \
|
||||
if [[ ! -z "$$llm_base_url" ]]; then echo "base_url=\"$$llm_base_url\"" >> $(CONFIG_FILE).tmp; fi
|
||||
|
||||
@echo "Enter your LLM Embedding Model"; \
|
||||
echo "Choices are:"; \
|
||||
echo " - openai"; \
|
||||
echo " - azureopenai"; \
|
||||
echo " - Embeddings available only with OllamaEmbedding:"; \
|
||||
echo " - llama2"; \
|
||||
echo " - mxbai-embed-large"; \
|
||||
echo " - nomic-embed-text"; \
|
||||
echo " - all-minilm"; \
|
||||
echo " - stable-code"; \
|
||||
echo " - bge-m3"; \
|
||||
echo " - bge-large"; \
|
||||
echo " - paraphrase-multilingual"; \
|
||||
echo " - snowflake-arctic-embed"; \
|
||||
echo " - Leave blank to default to 'BAAI/bge-small-en-v1.5' via huggingface"; \
|
||||
read -p "> " llm_embedding_model; \
|
||||
echo "embedding_model=\"$$llm_embedding_model\"" >> $(CONFIG_FILE).tmp; \
|
||||
if [ "$$llm_embedding_model" = "llama2" ] || [ "$$llm_embedding_model" = "mxbai-embed-large" ] || [ "$$llm_embedding_model" = "nomic-embed-text" ] || [ "$$llm_embedding_model" = "all-minilm" ] || [ "$$llm_embedding_model" = "stable-code" ]; then \
|
||||
read -p "Enter the local model URL for the embedding model (will set llm.embedding_base_url): " llm_embedding_base_url; \
|
||||
echo "embedding_base_url=\"$$llm_embedding_base_url\"" >> $(CONFIG_FILE).tmp; \
|
||||
elif [ "$$llm_embedding_model" = "azureopenai" ]; then \
|
||||
read -p "Enter the Azure endpoint URL (will overwrite llm.base_url): " llm_base_url; \
|
||||
echo "base_url=\"$$llm_base_url\"" >> $(CONFIG_FILE).tmp; \
|
||||
read -p "Enter the Azure LLM Embedding Deployment Name: " llm_embedding_deployment_name; \
|
||||
echo "embedding_deployment_name=\"$$llm_embedding_deployment_name\"" >> $(CONFIG_FILE).tmp; \
|
||||
read -p "Enter the Azure API Version: " llm_api_version; \
|
||||
echo "api_version=\"$$llm_api_version\"" >> $(CONFIG_FILE).tmp; \
|
||||
fi
|
||||
|
||||
|
||||
# Develop in container
|
||||
docker-dev:
|
||||
|
||||
10
README.md
10
README.md
@@ -12,7 +12,7 @@
|
||||
<a href="https://codecov.io/github/All-Hands-AI/OpenHands?branch=main"><img alt="CodeCov" src="https://img.shields.io/codecov/c/github/All-Hands-AI/OpenHands?style=for-the-badge&color=blue"></a>
|
||||
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/LICENSE"><img src="https://img.shields.io/github/license/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="MIT License"></a>
|
||||
<br/>
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ngejmfw6-9gW4APWOC9XUp1n~SiQ6iw"><img src="https://img.shields.io/badge/Slack-Join%20Us-red?logo=slack&logoColor=white&style=for-the-badge" alt="Join our Slack community"></a>
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ypg5jweb-d~6hObZDbXi_HEL8PDrbHg"><img src="https://img.shields.io/badge/Slack-Join%20Us-red?logo=slack&logoColor=white&style=for-the-badge" alt="Join our Slack community"></a>
|
||||
<a href="https://discord.gg/ESHStjSjD4"><img src="https://img.shields.io/badge/Discord-Join%20Us-purple?logo=discord&logoColor=white&style=for-the-badge" alt="Join our Discord community"></a>
|
||||
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/CREDITS.md"><img src="https://img.shields.io/badge/Project-Credits-blue?style=for-the-badge&color=FFE165&logo=github&logoColor=white" alt="Credits"></a>
|
||||
<br/>
|
||||
@@ -43,17 +43,17 @@ See the [Running OpenHands](https://docs.all-hands.dev/modules/usage/installatio
|
||||
system requirements and more information.
|
||||
|
||||
```bash
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik
|
||||
|
||||
docker run -it --rm --pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-e LOG_ALL_EVENTS=true \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v ~/.openhands-state:/.openhands-state \
|
||||
-p 3000:3000 \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--name openhands-app \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.28
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.26
|
||||
```
|
||||
|
||||
You'll find OpenHands running at [http://localhost:3000](http://localhost:3000)!
|
||||
@@ -96,7 +96,7 @@ troubleshooting resources, and advanced configuration options.
|
||||
OpenHands is a community-driven project, and we welcome contributions from everyone. We do most of our communication
|
||||
through Slack, so this is the best place to start, but we also are happy to have you contact us on Discord or Github:
|
||||
|
||||
- [Join our Slack workspace](https://join.slack.com/t/openhands-ai/shared_invite/zt-2ngejmfw6-9gW4APWOC9XUp1n~SiQ6iw) - Here we talk about research, architecture, and future development.
|
||||
- [Join our Slack workspace](https://join.slack.com/t/openhands-ai/shared_invite/zt-2ypg5jweb-d~6hObZDbXi_HEL8PDrbHg) - Here we talk about research, architecture, and future development.
|
||||
- [Join our Discord server](https://discord.gg/ESHStjSjD4) - This is a community-run server for general discussion, questions, and feedback.
|
||||
- [Read or post Github Issues](https://github.com/All-Hands-AI/OpenHands/issues) - Check out the issues we're working on, or add your own ideas.
|
||||
|
||||
|
||||
@@ -95,11 +95,6 @@ workspace_base = "./workspace"
|
||||
# List of allowed file extensions for uploads
|
||||
#file_uploads_allowed_extensions = [".*"]
|
||||
|
||||
# Whether to enable the default LLM summarizing condenser when no condenser is specified in config
|
||||
# When true, a LLMSummarizingCondenserConfig will be used as the default condenser
|
||||
# When false, a NoOpCondenserConfig (no summarization) will be used
|
||||
#enable_default_condenser = true
|
||||
|
||||
#################################### LLM #####################################
|
||||
# Configuration for LLM models (group name starts with 'llm')
|
||||
# use 'llm' for the default LLM config
|
||||
@@ -132,6 +127,15 @@ api_key = ""
|
||||
# Custom LLM provider
|
||||
#custom_llm_provider = ""
|
||||
|
||||
# Embedding API base URL
|
||||
#embedding_base_url = ""
|
||||
|
||||
# Embedding deployment name
|
||||
#embedding_deployment_name = ""
|
||||
|
||||
# Embedding model to use
|
||||
embedding_model = "local"
|
||||
|
||||
# Maximum number of characters in an observation's content
|
||||
#max_message_chars = 10000
|
||||
|
||||
@@ -218,6 +222,9 @@ codeact_enable_llm_editor = false
|
||||
# whether the IPython tool is enabled
|
||||
codeact_enable_jupyter = true
|
||||
|
||||
# Name of the micro agent to use for this agent
|
||||
#micro_agent_name = ""
|
||||
|
||||
# Memory enabled
|
||||
#memory_enabled = false
|
||||
|
||||
@@ -287,69 +294,6 @@ llm_config = 'gpt3'
|
||||
# The security analyzer to use (For Headless / CLI only - In Web this is overridden by Session Init)
|
||||
#security_analyzer = ""
|
||||
|
||||
#################################### Condenser #################################
|
||||
# Condensers control how conversation history is managed and compressed when
|
||||
# the context grows too large. Each agent uses one condenser configuration.
|
||||
##############################################################################
|
||||
[condenser]
|
||||
# The type of condenser to use. Available options:
|
||||
# - "noop": No condensing, keeps full history (default)
|
||||
# - "observation_masking": Keeps full event structure but masks older observations
|
||||
# - "recent": Keeps only recent events and discards older ones
|
||||
# - "llm": Uses an LLM to summarize conversation history
|
||||
# - "amortized": Intelligently forgets older events while preserving important context
|
||||
# - "llm_attention": Uses an LLM to prioritize most relevant context
|
||||
type = "noop"
|
||||
|
||||
# Examples for each condenser type (uncomment and modify as needed):
|
||||
|
||||
# 1. NoOp Condenser - No additional settings needed
|
||||
#type = "noop"
|
||||
|
||||
# 2. Observation Masking Condenser
|
||||
#type = "observation_masking"
|
||||
# Number of most-recent events where observations will not be masked
|
||||
#attention_window = 100
|
||||
|
||||
# 3. Recent Events Condenser
|
||||
#type = "recent"
|
||||
# Number of initial events to always keep (typically includes task description)
|
||||
#keep_first = 1
|
||||
# Maximum number of events to keep in history
|
||||
#max_events = 100
|
||||
|
||||
# 4. LLM Summarizing Condenser
|
||||
#type = "llm"
|
||||
# Reference to an LLM config to use for summarization
|
||||
#llm_config = "condenser"
|
||||
# Number of initial events to always keep (typically includes task description)
|
||||
#keep_first = 1
|
||||
# Maximum size of history before triggering summarization
|
||||
#max_size = 100
|
||||
|
||||
# 5. Amortized Forgetting Condenser
|
||||
#type = "amortized"
|
||||
# Number of initial events to always keep (typically includes task description)
|
||||
#keep_first = 1
|
||||
# Maximum size of history before triggering forgetting
|
||||
#max_size = 100
|
||||
|
||||
# 6. LLM Attention Condenser
|
||||
#type = "llm_attention"
|
||||
# Reference to an LLM config to use for attention scoring
|
||||
#llm_config = "condenser"
|
||||
# Number of initial events to always keep (typically includes task description)
|
||||
#keep_first = 1
|
||||
# Maximum size of history before triggering attention mechanism
|
||||
#max_size = 100
|
||||
|
||||
# Example of a custom LLM configuration for condensers that require an LLM
|
||||
# If not provided, it falls back to the default LLM
|
||||
#[llm.condenser]
|
||||
#model = "gpt-4o"
|
||||
#temperature = 0.1
|
||||
#max_tokens = 1024
|
||||
|
||||
#################################### Eval ####################################
|
||||
# Configuration for the evaluation, please refer to the specific evaluation
|
||||
# plugin for the available options
|
||||
|
||||
@@ -26,7 +26,7 @@ RUN apt-get update -y \
|
||||
|
||||
COPY ./pyproject.toml ./poetry.lock ./
|
||||
RUN touch README.md
|
||||
RUN export POETRY_CACHE_DIR && poetry install --without evaluation --no-root && rm -rf $POETRY_CACHE_DIR
|
||||
RUN export POETRY_CACHE_DIR && poetry install --without evaluation,llama-index --no-root && rm -rf $POETRY_CACHE_DIR
|
||||
|
||||
FROM python:3.12.3-slim AS openhands-app
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ services:
|
||||
- BACKEND_HOST=${BACKEND_HOST:-"0.0.0.0"}
|
||||
- SANDBOX_API_HOSTNAME=host.docker.internal
|
||||
#
|
||||
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/all-hands-ai/runtime:0.28-nikolaik}
|
||||
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-ghcr.io/all-hands-ai/runtime:0.26-nikolaik}
|
||||
- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234}
|
||||
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
|
||||
ports:
|
||||
|
||||
@@ -7,7 +7,7 @@ services:
|
||||
image: openhands:latest
|
||||
container_name: openhands-app-${DATE:-}
|
||||
environment:
|
||||
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik}
|
||||
- SANDBOX_RUNTIME_CONTAINER_IMAGE=${SANDBOX_RUNTIME_CONTAINER_IMAGE:-docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik}
|
||||
#- SANDBOX_USER_ID=${SANDBOX_USER_ID:-1234} # enable this only if you want a specific non-root sandbox user but you will have to manually adjust permissions of openhands-state for this user
|
||||
- WORKSPACE_MOUNT_PATH=${WORKSPACE_BASE:-$PWD/workspace}
|
||||
ports:
|
||||
|
||||
@@ -333,6 +333,12 @@ Pour les configurations de développement, vous pouvez également définir des c
|
||||
|
||||
Les options de configuration de l'agent sont définies dans les sections `[agent]` et `[agent.<agent_name>]` du fichier `config.toml`.
|
||||
|
||||
**Configuration du micro-agent**
|
||||
- `micro_agent_name`
|
||||
- Type : `str`
|
||||
- Valeur par défaut : `""`
|
||||
- Description : Nom du micro-agent à utiliser pour cet agent
|
||||
|
||||
**Configuration de la mémoire**
|
||||
- `memory_enabled`
|
||||
- Type : `bool`
|
||||
|
||||
@@ -42,11 +42,10 @@ Créez un fichier ```config.toml``` dans le répertoire OpenHands et entrez ces
|
||||
[core]
|
||||
workspace_base="./workspace"
|
||||
run_as_openhands=true
|
||||
[sandbox]
|
||||
base_container_image="image_personnalisée"
|
||||
sandbox_base_container_image="image_personnalisée"
|
||||
```
|
||||
|
||||
> Assurez-vous que ```base_container_image``` est défini sur le nom de votre image personnalisée précédente.
|
||||
> Assurez-vous que ```sandbox_base_container_image``` est défini sur le nom de votre image personnalisée précédente.
|
||||
|
||||
## Exécution
|
||||
|
||||
@@ -83,15 +82,14 @@ dockerfile_content = (
|
||||
## Dépannage / Erreurs
|
||||
|
||||
### Erreur: ```useradd: UID 1000 est non unique```
|
||||
Si vous voyez cette erreur dans la sortie de la console, il s'agit du fait que OpenHands essaie de créer le utilisateur openhands dans le sandbox avec un ID d'utilisateur de 1000, cependant cet ID d'utilisateur est déjà utilisé dans l'image (pour une raison inconnue). Pour résoudre ce problème, changez la valeur du champ user_id dans le fichier config.toml en une valeur différente:
|
||||
Si vous voyez cette erreur dans la sortie de la console, il s'agit du fait que OpenHands essaie de créer le utilisateur openhands dans le sandbox avec un ID d'utilisateur de 1000, cependant cet ID d'utilisateur est déjà utilisé dans l'image (pour une raison inconnue). Pour résoudre ce problème, changez la valeur du champ sandbox_user_id dans le fichier config.toml en une valeur différente:
|
||||
|
||||
```toml
|
||||
[core]
|
||||
workspace_base="./workspace"
|
||||
run_as_openhands=true
|
||||
[sandbox]
|
||||
base_container_image="image_personnalisée"
|
||||
user_id="1001"
|
||||
sandbox_base_container_image="image_personnalisée"
|
||||
sandbox_user_id="1001"
|
||||
```
|
||||
|
||||
### Erreurs de port d'utilisation
|
||||
|
||||
@@ -52,7 +52,7 @@ LLM_API_KEY="sk_test_12345"
|
||||
```bash
|
||||
docker run -it \
|
||||
--pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-e SANDBOX_USER_ID=$(id -u) \
|
||||
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
|
||||
-e LLM_API_KEY=$LLM_API_KEY \
|
||||
@@ -61,7 +61,7 @@ docker run -it \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--name openhands-app-$(date +%Y%m%d%H%M%S) \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
|
||||
python -m openhands.core.cli
|
||||
```
|
||||
|
||||
|
||||
@@ -44,13 +44,12 @@ Tout d'abord, assurez-vous de pouvoir exécuter OpenHands en suivant les instruc
|
||||
|
||||
### Spécifier l'Image de Base du Sandbox
|
||||
|
||||
Dans le fichier `config.toml` dans le répertoire OpenHands, définissez `base_container_image` sur l'image que vous souhaitez utiliser. Cela peut être une image que vous avez déjà extraite ou une que vous avez construite :
|
||||
Dans le fichier `config.toml` dans le répertoire OpenHands, définissez `sandbox_base_container_image` sur l'image que vous souhaitez utiliser. Cela peut être une image que vous avez déjà extraite ou une que vous avez construite :
|
||||
|
||||
```bash
|
||||
[core]
|
||||
...
|
||||
[sandbox]
|
||||
base_container_image="custom-image"
|
||||
sandbox_base_container_image="custom-image"
|
||||
```
|
||||
|
||||
### Exécution
|
||||
|
||||
@@ -46,7 +46,7 @@ LLM_API_KEY="sk_test_12345"
|
||||
```bash
|
||||
docker run -it \
|
||||
--pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-e SANDBOX_USER_ID=$(id -u) \
|
||||
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
|
||||
-e LLM_API_KEY=$LLM_API_KEY \
|
||||
@@ -56,6 +56,6 @@ docker run -it \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--name openhands-app-$(date +%Y%m%d%H%M%S) \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
|
||||
python -m openhands.core.main -t "write a bash script that prints hi" --no-auto-continue
|
||||
```
|
||||
|
||||
@@ -13,16 +13,16 @@
|
||||
La façon la plus simple d'exécuter OpenHands est avec Docker.
|
||||
|
||||
```bash
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik
|
||||
|
||||
docker run -it --rm --pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-e LOG_ALL_EVENTS=true \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-p 3000:3000 \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--name openhands-app \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.28
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.26
|
||||
```
|
||||
|
||||
Vous pouvez également exécuter OpenHands en mode [headless scriptable](https://docs.all-hands.dev/modules/usage/how-to/headless-mode), en tant que [CLI interactive](https://docs.all-hands.dev/modules/usage/how-to/cli-mode), ou en utilisant l'[Action GitHub OpenHands](https://docs.all-hands.dev/modules/usage/how-to/github-action).
|
||||
|
||||
@@ -42,7 +42,7 @@ Explorez le code source d'OpenHands sur [GitHub](https://github.com/All-Hands-AI
|
||||
/>
|
||||
</a>
|
||||
<br></br>
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ngejmfw6-9gW4APWOC9XUp1n~SiQ6iw">
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ypg5jweb-d~6hObZDbXi_HEL8PDrbHg">
|
||||
<img
|
||||
src="https://img.shields.io/badge/Slack-Join%20Us-red?logo=slack&logoColor=white&style=for-the-badge"
|
||||
alt="Join our Slack community"
|
||||
|
||||
@@ -13,7 +13,7 @@ C'est le Runtime par défaut qui est utilisé lorsque vous démarrez OpenHands.
|
||||
|
||||
```
|
||||
docker run # ...
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
# ...
|
||||
```
|
||||
|
||||
@@ -328,6 +328,12 @@ LLM(大语言模型)配置选项在 `config.toml` 文件的 `[llm]` 部分中定
|
||||
|
||||
Agent 配置选项在 `config.toml` 文件的 `[agent]` 和 `[agent.<agent_name>]` 部分中定义。
|
||||
|
||||
**Microagent 配置**
|
||||
- `micro_agent_name`
|
||||
- 类型: `str`
|
||||
- 默认值: `""`
|
||||
- 描述: 用于此 agent 的 micro agent 名称
|
||||
|
||||
**内存配置**
|
||||
- `memory_enabled`
|
||||
- 类型: `bool`
|
||||
|
||||
@@ -58,11 +58,10 @@ docker build -t custom_image .
|
||||
[core]
|
||||
workspace_base="./workspace"
|
||||
run_as_openhands=true
|
||||
[sandbox]
|
||||
base_container_image="custom_image"
|
||||
sandbox_base_container_image="custom_image"
|
||||
```
|
||||
|
||||
对于 `base_container_image` 的值, 您可以选择以下任意一项:
|
||||
对于 `sandbox_base_container_image` 的值, 您可以选择以下任意一项:
|
||||
1. 在上一步中您构建的自定义镜像的名称(例如,`“custom_image”`)
|
||||
2. 从 Docker Hub 拉取的镜像(例如,`“node:20”`,如果你需要一个预装 `Node.js` 的沙箱环境)
|
||||
|
||||
@@ -84,15 +83,14 @@ base_container_image="custom_image"
|
||||
|
||||
### 错误:```useradd: UID 1000 is not unique```
|
||||
|
||||
如果在控制台输出中看到此错误,说明 OpenHands 尝试在沙箱中以 UID 1000 创建 openhands 用户,但该 UID 已经被映像中的其他部分使用(不知何故)。要解决这个问题,请更改 config.toml 文件中的 user_id 字段为不同的值:
|
||||
如果在控制台输出中看到此错误,说明 OpenHands 尝试在沙箱中以 UID 1000 创建 openhands 用户,但该 UID 已经被映像中的其他部分使用(不知何故)。要解决这个问题,请更改 config.toml 文件中的 sandbox_user_id 字段为不同的值:
|
||||
|
||||
```
|
||||
[core]
|
||||
workspace_base="./workspace"
|
||||
run_as_openhands=true
|
||||
[sandbox]
|
||||
base_container_image="custom_image"
|
||||
user_id="1001"
|
||||
sandbox_base_container_image="custom_image"
|
||||
sandbox_user_id="1001"
|
||||
```
|
||||
|
||||
### 端口使用错误
|
||||
|
||||
@@ -50,7 +50,7 @@ LLM_API_KEY="sk_test_12345"
|
||||
```bash
|
||||
docker run -it \
|
||||
--pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-e SANDBOX_USER_ID=$(id -u) \
|
||||
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
|
||||
-e LLM_API_KEY=$LLM_API_KEY \
|
||||
@@ -59,7 +59,7 @@ docker run -it \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--name openhands-app-$(date +%Y%m%d%H%M%S) \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
|
||||
python -m openhands.core.cli
|
||||
```
|
||||
|
||||
|
||||
@@ -42,13 +42,12 @@ docker build -t custom-image .
|
||||
|
||||
### 指定基础沙箱镜像
|
||||
|
||||
在 OpenHands 目录中的 `config.toml` 文件中,将 `base_container_image` 设置为你要使用的镜像。这可以是你已经拉取的镜像或你构建的镜像:
|
||||
在 OpenHands 目录中的 `config.toml` 文件中,将 `sandbox_base_container_image` 设置为你要使用的镜像。这可以是你已经拉取的镜像或你构建的镜像:
|
||||
|
||||
```bash
|
||||
[core]
|
||||
...
|
||||
[sandbox]
|
||||
base_container_image="custom-image"
|
||||
sandbox_base_container_image="custom-image"
|
||||
```
|
||||
|
||||
### 运行
|
||||
|
||||
@@ -47,7 +47,7 @@ LLM_API_KEY="sk_test_12345"
|
||||
```bash
|
||||
docker run -it \
|
||||
--pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-e SANDBOX_USER_ID=$(id -u) \
|
||||
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
|
||||
-e LLM_API_KEY=$LLM_API_KEY \
|
||||
@@ -57,6 +57,6 @@ docker run -it \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--name openhands-app-$(date +%Y%m%d%H%M%S) \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
|
||||
python -m openhands.core.main -t "write a bash script that prints hi" --no-auto-continue
|
||||
```
|
||||
|
||||
@@ -11,16 +11,16 @@
|
||||
在 Docker 中运行 OpenHands 是最简单的方式。
|
||||
|
||||
```bash
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik
|
||||
|
||||
docker run -it --rm --pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-e LOG_ALL_EVENTS=true \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-p 3000:3000 \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--name openhands-app \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.28
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.26
|
||||
```
|
||||
|
||||
你也可以在可脚本化的[无头模式](https://docs.all-hands.dev/modules/usage/how-to/headless-mode)下运行 OpenHands,作为[交互式 CLI](https://docs.all-hands.dev/modules/usage/how-to/cli-mode),或使用 [OpenHands GitHub Action](https://docs.all-hands.dev/modules/usage/how-to/github-action)。
|
||||
|
||||
@@ -42,7 +42,7 @@ OpenHands 是一个**自主 AI 软件工程师**,能够执行复杂的工程
|
||||
/>
|
||||
</a>
|
||||
<br></br>
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ngejmfw6-9gW4APWOC9XUp1n~SiQ6iw">
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ypg5jweb-d~6hObZDbXi_HEL8PDrbHg">
|
||||
<img
|
||||
src="https://img.shields.io/badge/Slack-Join%20Us-red?logo=slack&logoColor=white&style=for-the-badge"
|
||||
alt="Join our Slack community"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
```
|
||||
docker run # ...
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
# ...
|
||||
```
|
||||
|
||||
@@ -4,30 +4,18 @@ The GitHub Resolver automates code fixes and provides intelligent assistance for
|
||||
|
||||
## Setup
|
||||
|
||||
The Cloud GitHub Resolver is available automatically when you
|
||||
The Cloud Github Resolver is available automatically when you
|
||||
[grant OpenHands Cloud repository access](./openhands-cloud.md#adding-repositories).
|
||||
|
||||
## Usage
|
||||
|
||||
After granting OpenHands Cloud repository access, you can use the Cloud GitHub Resolver on the issues and pull requests
|
||||
on the repository.
|
||||
|
||||
### Issues
|
||||
|
||||
On your repository, label an issue with `openhands`. OpenHands will:
|
||||
1. Comment on the issue to let you know it is working on it.
|
||||
- You can click on the link to track the progress on OpenHands Cloud.
|
||||
2. Open a pull request if it determines that the issue has been successfully resolved.
|
||||
3. Comment on the issue with a summary of the performed tasks and a link to the pull request.
|
||||
|
||||
On your repository, label an issue with `openhands`. OpenHands will attempt to fix the issue.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
To get OpenHands to work on pull requests, use `@openhands` in top level or inline comments to:
|
||||
In order to get OpenHands to work on pull requests, use `@openhands` in top level or single inline comments to:
|
||||
- Ask questions
|
||||
- Request updates
|
||||
- Get code explanations
|
||||
|
||||
OpenHands will:
|
||||
1. Comment on the PR to let you know it is working on it.
|
||||
2. Perform the task.
|
||||
|
||||
@@ -12,16 +12,14 @@ instructions on how to access it.
|
||||
|
||||
After visiting OpenHands Cloud, you will be asked to connect with your GitHub account:
|
||||
1. After reading and accepting the terms of service, click `Connect to GitHub`.
|
||||
2. Review the permissions requested by OpenHands and then click `Authorize OpenHands AI`.
|
||||
2. Review the permissions requested by OpenHands and then click `Authorize OpenHands by All Hands AI`.
|
||||
- OpenHands will require some permissions from your GitHub account. To read more about these permissions,
|
||||
you can click the `Learn more` link on the GitHub authorize page.
|
||||
|
||||
## Repository Access
|
||||
|
||||
### Adding Repository Access
|
||||
## Adding Repositories
|
||||
|
||||
You can grant OpenHands specific repository access:
|
||||
1. Click the `Select a GitHub project` dropdown, select `Add more repositories...`.
|
||||
1. Under the `Select a GitHub project` dropdown, select `Add more repositories...`.
|
||||
2. Select the organization, then choose the specific repositories to grant OpenHands access to.
|
||||
- Openhands requests short-lived tokens (8-hour expiry) with these permissions:
|
||||
- Actions: Read and write
|
||||
@@ -36,10 +34,6 @@ You can grant OpenHands specific repository access:
|
||||
- Repository access for a user is granted based on:
|
||||
- Granted permission for the repository.
|
||||
- User's GitHub permissions (owner/collaborator).
|
||||
3. Click on `Install & Authorize`.
|
||||
|
||||
### Modifying Repository Access
|
||||
|
||||
You can modify repository access at any time by:
|
||||
* Using the same `Select a GitHub project > Add more repositories` workflow, or
|
||||
* Visiting the Settings page and selecting `Configure GitHub Repositories` under the `GitHub Settings` section.
|
||||
You can manage repository access any time by following the above workflow or visiting the Settings page and selecting
|
||||
`Configure GitHub Repositories` under the `GitHub Settings` section.
|
||||
|
||||
@@ -197,6 +197,21 @@ For development setups, you can also define custom named LLM configurations. See
|
||||
- Default: `""`
|
||||
- Description: Custom LLM provider
|
||||
|
||||
### Embeddings
|
||||
- `embedding_base_url`
|
||||
- Type: `str`
|
||||
- Default: `""`
|
||||
- Description: Embedding API base URL
|
||||
|
||||
- `embedding_deployment_name`
|
||||
- Type: `str`
|
||||
- Default: `""`
|
||||
- Description: Embedding deployment name
|
||||
|
||||
- `embedding_model`
|
||||
- Type: `str`
|
||||
- Default: `"local"`
|
||||
- Description: Embedding model to use
|
||||
|
||||
### Message Handling
|
||||
- `max_message_chars`
|
||||
@@ -281,6 +296,23 @@ For development setups, you can also define custom named LLM configurations. See
|
||||
|
||||
The agent configuration options are defined in the `[agent]` and `[agent.<agent_name>]` sections of the `config.toml` file.
|
||||
|
||||
### Microagent Configuration
|
||||
- `micro_agent_name`
|
||||
- Type: `str`
|
||||
- Default: `""`
|
||||
- Description: Name of the micro agent to use for this agent
|
||||
|
||||
### Memory Configuration
|
||||
- `memory_enabled`
|
||||
- Type: `bool`
|
||||
- Default: `false`
|
||||
- Description: Whether long-term memory (embeddings) is enabled
|
||||
|
||||
- `memory_max_threads`
|
||||
- Type: `int`
|
||||
- Default: `3`
|
||||
- Description: The maximum number of threads indexing at the same time for embeddings
|
||||
|
||||
### LLM Configuration
|
||||
- `llm_config`
|
||||
- Type: `str`
|
||||
@@ -353,11 +385,6 @@ To use these with the docker command, pass in `-e SANDBOX_<option>`. Example: `-
|
||||
- Default: `false`
|
||||
- Description: Use host network
|
||||
|
||||
- `runtime_binding_address`
|
||||
- Type: `str`
|
||||
- Default: `0.0.0.0`
|
||||
- Description: The binding address for the runtime ports. It specifies which network interface on the host machine Docker should bind the runtime ports to.
|
||||
|
||||
### Linting and Plugins
|
||||
- `enable_auto_lint`
|
||||
- Type: `bool`
|
||||
|
||||
@@ -36,7 +36,7 @@ At this time, we will follow the following release process:
|
||||
1. All people who contributed public feedback will receive an email describing the data release and being given an opportunity to opt out.
|
||||
2. The person or people in charge of the data release will perform quality control of the data, removing low-quality feedback,
|
||||
removing email submitter email addresses, and attempting to remove any sensitive information.
|
||||
3. The data will be released publicly under the MIT license through commonly used sites such as GitHub or Hugging Face.
|
||||
3. The data will be released publicly under the MIT license through commonly used sites such as github or Hugging Face.
|
||||
|
||||
### What if I want my data deleted?
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ To run OpenHands in CLI mode with Docker:
|
||||
```bash
|
||||
docker run -it \
|
||||
--pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-e SANDBOX_USER_ID=$(id -u) \
|
||||
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
|
||||
-e LLM_API_KEY=$LLM_API_KEY \
|
||||
@@ -45,7 +45,7 @@ docker run -it \
|
||||
-v ~/.openhands-state:/.openhands-state \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--name openhands-app-$(date +%Y%m%d%H%M%S) \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
|
||||
python -m openhands.core.cli
|
||||
```
|
||||
|
||||
|
||||
@@ -60,14 +60,13 @@ First, ensure you can run OpenHands by following the instructions in [Developmen
|
||||
|
||||
### Specify the Base Sandbox Image
|
||||
|
||||
In the `config.toml` file within the OpenHands directory, set the `base_container_image` to the image you want to use.
|
||||
In the `config.toml` file within the OpenHands directory, set the `sandbox_base_container_image` to the image you want to use.
|
||||
This can be an image you’ve already pulled or one you’ve built:
|
||||
|
||||
```bash
|
||||
[core]
|
||||
...
|
||||
[sandbox]
|
||||
base_container_image="custom-image"
|
||||
sandbox_base_container_image="custom-image"
|
||||
```
|
||||
|
||||
### Additional Configuration Options
|
||||
|
||||
@@ -39,7 +39,7 @@ You can provide custom directions for OpenHands by following the [README for the
|
||||
|
||||
### Custom configurations
|
||||
|
||||
GitHub resolver will automatically check for valid [repository secrets](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions?tool=webui#creating-secrets-for-a-repository) or [repository variables](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#creating-configuration-variables-for-a-repository) to customize its behavior.
|
||||
Github resolver will automatically check for valid [repository secrets](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions?tool=webui#creating-secrets-for-a-repository) or [repository variables](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#creating-configuration-variables-for-a-repository) to customize its behavior.
|
||||
The customization options you can set are:
|
||||
|
||||
| **Attribute name** | **Type** | **Purpose** | **Example** |
|
||||
|
||||
@@ -32,7 +32,7 @@ To run OpenHands in Headless mode with Docker:
|
||||
```bash
|
||||
docker run -it \
|
||||
--pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-e SANDBOX_USER_ID=$(id -u) \
|
||||
-e WORKSPACE_MOUNT_PATH=$WORKSPACE_BASE \
|
||||
-e LLM_API_KEY=$LLM_API_KEY \
|
||||
@@ -43,7 +43,7 @@ docker run -it \
|
||||
-v ~/.openhands-state:/.openhands-state \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--name openhands-app-$(date +%Y%m%d%H%M%S) \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.28 \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.26 \
|
||||
python -m openhands.core.main -t "write a bash script that prints hi"
|
||||
```
|
||||
|
||||
|
||||
@@ -58,17 +58,17 @@ A system with a modern processor and a minimum of **4GB RAM** is recommended to
|
||||
The easiest way to run OpenHands is in Docker.
|
||||
|
||||
```bash
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik
|
||||
docker pull docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik
|
||||
|
||||
docker run -it --rm --pull=always \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-e LOG_ALL_EVENTS=true \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
-v ~/.openhands-state:/.openhands-state \
|
||||
-p 3000:3000 \
|
||||
--add-host host.docker.internal:host-gateway \
|
||||
--name openhands-app \
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.28
|
||||
docker.all-hands.dev/all-hands-ai/openhands:0.26
|
||||
```
|
||||
|
||||
You'll find OpenHands running at http://localhost:3000!
|
||||
@@ -76,7 +76,7 @@ You'll find OpenHands running at http://localhost:3000!
|
||||
You can also [connect OpenHands to your local filesystem](https://docs.all-hands.dev/modules/usage/runtimes#connecting-to-your-filesystem),
|
||||
run OpenHands in a scriptable [headless mode](https://docs.all-hands.dev/modules/usage/how-to/headless-mode),
|
||||
interact with it via a [friendly CLI](https://docs.all-hands.dev/modules/usage/how-to/cli-mode),
|
||||
or run it on tagged issues with [a GitHub action](https://docs.all-hands.dev/modules/usage/how-to/github-action).
|
||||
or run it on tagged issues with [a github action](https://docs.all-hands.dev/modules/usage/how-to/github-action).
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
@@ -31,11 +31,17 @@ You will need your ChatGPT deployment name which can be found on the deployments
|
||||
- `Base URL` to your Azure API Base URL (e.g. `https://example-endpoint.openai.azure.com`)
|
||||
- `API Key` to your Azure API key
|
||||
|
||||
## Embeddings
|
||||
|
||||
OpenHands uses llama-index for embeddings. You can find their documentation on Azure [here](https://docs.llamaindex.ai/en/stable/api_reference/embeddings/azure_openai/).
|
||||
|
||||
### Azure OpenAI Configuration
|
||||
|
||||
When running OpenHands, set the following environment variable using `-e` in the
|
||||
When running OpenHands, set the following environment variables using `-e` in the
|
||||
[docker run command](/modules/usage/installation#start-the-app):
|
||||
|
||||
```
|
||||
LLM_EMBEDDING_MODEL="azureopenai"
|
||||
LLM_EMBEDDING_DEPLOYMENT_NAME="<your-embedding-deployment-name>" # e.g. "TextEmbedding...<etc>"
|
||||
LLM_API_VERSION="<api-version>" # e.g. "2024-02-15-preview"
|
||||
```
|
||||
|
||||
@@ -10,16 +10,13 @@ We also support "remote" runtimes, which are typically managed by third-parties.
|
||||
They can make setup a bit simpler and more scalable, especially
|
||||
if you're running many OpenHands conversations in parallel (e.g. to do evaluation).
|
||||
|
||||
Additionally, we provide a "local" runtime that runs directly on your machine without Docker,
|
||||
which can be useful in controlled environments like CI pipelines.
|
||||
|
||||
## Docker Runtime
|
||||
This is the default Runtime that's used when you start OpenHands. You might notice
|
||||
some flags being passed to `docker run` that make this possible:
|
||||
|
||||
```
|
||||
docker run # ...
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.28-nikolaik \
|
||||
-e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:0.26-nikolaik \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
# ...
|
||||
```
|
||||
@@ -59,12 +56,11 @@ any files that are mounted into its workspace.
|
||||
This setup can cause some issues with file permissions (hence the `SANDBOX_USER_ID` variable)
|
||||
but seems to work well on most systems.
|
||||
|
||||
## OpenHands Remote Runtime
|
||||
## All Hands Runtime
|
||||
The All Hands Runtime is currently in beta. You can request access by joining
|
||||
the #remote-runtime-limited-beta channel on Slack ([see the README](https://github.com/All-Hands-AI/OpenHands?tab=readme-ov-file#-how-to-join-the-community) for an invite).
|
||||
|
||||
OpenHands Remote Runtime is currently in beta (read [here](https://runtime.all-hands.dev/) for more details), it allows you to launch runtimes in parallel in the cloud.
|
||||
Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply if you want to try this out!
|
||||
|
||||
To use the OpenHands Remote Runtime, set the following environment variables when
|
||||
To use the All Hands Runtime, set the following environment variables when
|
||||
starting OpenHands:
|
||||
|
||||
```bash
|
||||
@@ -88,99 +84,3 @@ docker run # ...
|
||||
-e MODAL_API_TOKEN_ID="your-id" \
|
||||
-e MODAL_API_TOKEN_SECRET="your-secret" \
|
||||
```
|
||||
|
||||
## Daytona Runtime
|
||||
|
||||
Another option is using [Daytona](https://www.daytona.io/) as a runtime provider:
|
||||
|
||||
### Step 1: Retrieve Your Daytona API Key
|
||||
1. Visit the [Daytona Dashboard](https://app.daytona.io/dashboard/keys).
|
||||
2. Click **"Create Key"**.
|
||||
3. Enter a name for your key and confirm the creation.
|
||||
4. Once the key is generated, copy it.
|
||||
|
||||
### Step 2: Set Your API Key as an Environment Variable
|
||||
Run the following command in your terminal, replacing `<your-api-key>` with the actual key you copied:
|
||||
```bash
|
||||
export DAYTONA_API_KEY="<your-api-key>"
|
||||
```
|
||||
|
||||
This step ensures that OpenHands can authenticate with the Daytona platform when it runs.
|
||||
|
||||
### Step 3: Run OpenHands Locally Using Docker
|
||||
To start the latest version of OpenHands on your machine, execute the following command in your terminal:
|
||||
```bash
|
||||
bash -i <(curl -sL https://get.daytona.io/openhands)
|
||||
```
|
||||
|
||||
#### What This Command Does:
|
||||
- Downloads the latest OpenHands release script.
|
||||
- Runs the script in an interactive Bash session.
|
||||
- Automatically pulls and runs the OpenHands container using Docker.
|
||||
|
||||
Once executed, OpenHands should be running locally and ready for use.
|
||||
|
||||
For more details and manual initialization, view the entire [README.md](https://github.com/All-Hands-AI/OpenHands/blob/main/openhands/runtime/impl/daytona/README.md)
|
||||
|
||||
## Local Runtime
|
||||
|
||||
The Local Runtime allows the OpenHands agent to execute actions directly on your local machine without using Docker. This runtime is primarily intended for controlled environments like CI pipelines or testing scenarios where Docker is not available.
|
||||
|
||||
:::caution
|
||||
**Security Warning**: The Local Runtime runs without any sandbox isolation. The agent can directly access and modify files on your machine. Only use this runtime in controlled environments or when you fully understand the security implications.
|
||||
:::
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before using the Local Runtime, ensure you have the following dependencies installed:
|
||||
|
||||
1. You have followed the [Development setup instructions](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md).
|
||||
2. tmux is available on your system.
|
||||
|
||||
### Configuration
|
||||
|
||||
To use the Local Runtime, besides required configurations like the model, API key, you'll need to set the following options via environment variables or the [config.toml file](https://github.com/All-Hands-AI/OpenHands/blob/main/config.template.toml) when starting OpenHands:
|
||||
|
||||
- Via environment variables:
|
||||
|
||||
```bash
|
||||
# Required
|
||||
export RUNTIME=local
|
||||
|
||||
# Optional but recommended
|
||||
export WORKSPACE_BASE=/path/to/your/workspace
|
||||
```
|
||||
|
||||
- Via `config.toml`:
|
||||
|
||||
```toml
|
||||
[core]
|
||||
runtime = "local"
|
||||
workspace_base = "/path/to/your/workspace"
|
||||
```
|
||||
|
||||
If `WORKSPACE_BASE` is not set, the runtime will create a temporary directory for the agent to work in.
|
||||
|
||||
### Example Usage
|
||||
|
||||
Here's an example of how to start OpenHands with the Local Runtime in Headless Mode:
|
||||
|
||||
```bash
|
||||
# Set the runtime type to local
|
||||
export RUNTIME=local
|
||||
|
||||
# Optionally set a workspace directory
|
||||
export WORKSPACE_BASE=/path/to/your/project
|
||||
|
||||
# Start OpenHands
|
||||
poetry run python -m openhands.core.main -t "write a bash script that prints hi"
|
||||
```
|
||||
|
||||
### Use Cases
|
||||
|
||||
The Local Runtime is particularly useful for:
|
||||
|
||||
- CI/CD pipelines where Docker is not available.
|
||||
- Testing and development of OpenHands itself.
|
||||
- Environments where container usage is restricted.
|
||||
- Scenarios where direct file system access is required.
|
||||
|
||||
16
docs/package-lock.json
generated
16
docs/package-lock.json
generated
@@ -17,14 +17,14 @@
|
||||
"prism-react-renderer": "^2.4.1",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-icons": "^5.4.0",
|
||||
"react-use": "^17.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "^3.5.1",
|
||||
"@docusaurus/tsconfig": "^3.7.0",
|
||||
"@docusaurus/types": "^3.5.1",
|
||||
"typescript": "~5.8.2"
|
||||
"typescript": "~5.7.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0"
|
||||
@@ -15680,9 +15680,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-icons": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
|
||||
"integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz",
|
||||
"integrity": "sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
@@ -17638,9 +17638,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
|
||||
"integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
|
||||
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
"prism-react-renderer": "^2.4.1",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-icons": "^5.4.0",
|
||||
"react-use": "^17.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "^3.5.1",
|
||||
"@docusaurus/tsconfig": "^3.7.0",
|
||||
"@docusaurus/types": "^3.5.1",
|
||||
"typescript": "~5.8.2"
|
||||
"typescript": "~5.7.3"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
||||
@@ -8,7 +8,7 @@ function CustomFooter() {
|
||||
<footer className="custom-footer">
|
||||
<div className="footer-content">
|
||||
<div className="footer-icons">
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ngejmfw6-9gW4APWOC9XUp1n~SiQ6iw" target="_blank" rel="noopener noreferrer">
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ypg5jweb-d~6hObZDbXi_HEL8PDrbHg" target="_blank" rel="noopener noreferrer">
|
||||
<FaSlack />
|
||||
</a>
|
||||
<a href="https://discord.gg/ESHStjSjD4" target="_blank" rel="noopener noreferrer">
|
||||
|
||||
@@ -5,6 +5,9 @@ export function Demo() {
|
||||
const videoRef = React.useRef<HTMLVideoElement>(null);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{ paddingBottom: "10px", paddingTop: "10px", textAlign: "center" }}
|
||||
>
|
||||
<video
|
||||
playsInline
|
||||
autoPlay={true}
|
||||
@@ -17,5 +20,6 @@ export function Demo() {
|
||||
>
|
||||
<source src="img/teaser.mp4" type="video/mp4"></source>
|
||||
</video>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
.demo {
|
||||
width: 100%;
|
||||
padding: 30px;
|
||||
max-width: 800px;
|
||||
text-align: center;
|
||||
border-radius: 40px;
|
||||
|
||||
@@ -17,42 +17,22 @@ export function HomepageHeader() {
|
||||
|
||||
<p className="header-subtitle">{siteConfig.tagline}</p>
|
||||
|
||||
<div style={{
|
||||
textAlign: 'center',
|
||||
fontSize: '1.2rem',
|
||||
maxWidth: '800px',
|
||||
margin: '0 auto',
|
||||
padding: '0rem 0rem 1rem'
|
||||
}}>
|
||||
<p style={{ margin: '0' }}>
|
||||
Use AI to tackle the toil in your backlog. Our agents have all the same tools as a human developer: they can modify code, run commands, browse the web,
|
||||
call APIs, and yes-even copy code snippets from StackOverflow.
|
||||
<br/>
|
||||
<Link to="https://docs.all-hands.dev/modules/usage/installation"
|
||||
style={{
|
||||
textDecoration: 'underline',
|
||||
display: 'inline-block',
|
||||
marginTop: '0.5rem'
|
||||
}}
|
||||
>
|
||||
Get started with OpenHands.
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div align="center" className="header-links">
|
||||
<a href="https://github.com/All-Hands-AI/OpenHands/graphs/contributors"><img src="https://img.shields.io/github/contributors/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="Contributors" /></a>
|
||||
<a href="https://github.com/All-Hands-AI/OpenHands/stargazers"><img src="https://img.shields.io/github/stars/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="Stargazers" /></a>
|
||||
<a href="https://codecov.io/github/All-Hands-AI/OpenHands?branch=main"><img alt="CodeCov" src="https://img.shields.io/codecov/c/github/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" /></a>
|
||||
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/LICENSE"><img src="https://img.shields.io/github/license/All-Hands-AI/OpenHands?style=for-the-badge&color=blue" alt="MIT License" /></a>
|
||||
<br/>
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ngejmfw6-9gW4APWOC9XUp1n~SiQ6iw"><img src="https://img.shields.io/badge/Slack-Join%20Us-red?logo=slack&logoColor=white&style=for-the-badge" alt="Join our Slack community" /></a>
|
||||
<a href="https://join.slack.com/t/openhands-ai/shared_invite/zt-2ypg5jweb-d~6hObZDbXi_HEL8PDrbHg"><img src="https://img.shields.io/badge/Slack-Join%20Us-red?logo=slack&logoColor=white&style=for-the-badge" alt="Join our Slack community" /></a>
|
||||
<a href="https://discord.gg/ESHStjSjD4"><img src="https://img.shields.io/badge/Discord-Join%20Us-purple?logo=discord&logoColor=white&style=for-the-badge" alt="Join our Discord community" /></a>
|
||||
<a href="https://github.com/All-Hands-AI/OpenHands/blob/main/CREDITS.md"><img src="https://img.shields.io/badge/Project-Credits-blue?style=for-the-badge&color=FFE165&logo=github&logoColor=white" alt="Credits" /></a>
|
||||
<br/>
|
||||
<a href="https://docs.all-hands.dev/modules/usage/getting-started"><img src="https://img.shields.io/badge/Documentation-000?logo=googledocs&logoColor=FFE165&style=for-the-badge" alt="Check out the documentation" /></a>
|
||||
<a href="https://arxiv.org/abs/2407.16741"><img src="https://img.shields.io/badge/Paper%20on%20Arxiv-000?logoColor=FFE165&logo=arxiv&style=for-the-badge" alt="Paper on Arxiv" /></a>
|
||||
<a href="https://huggingface.co/spaces/OpenHands/evaluation"><img src="https://img.shields.io/badge/Benchmark%20score-000?logoColor=FFE165&logo=huggingface&style=for-the-badge" alt="Evaluation Benchmark Score" /></a>
|
||||
</div>
|
||||
|
||||
<Demo />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/* homepageHeader.css */
|
||||
|
||||
.homepage-header {
|
||||
padding: 1rem 0;
|
||||
height: 800px;
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
padding: 2rem;
|
||||
font-weight: 300;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
.header-subtitle {
|
||||
font-size: 1.5rem;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.header-links {
|
||||
|
||||
@@ -2,7 +2,15 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
import Layout from '@theme/Layout';
|
||||
import { HomepageHeader } from '../components/HomepageHeader/HomepageHeader';
|
||||
import { translate } from '@docusaurus/Translate';
|
||||
import { Demo } from "../components/Demo/Demo";
|
||||
|
||||
export function Header({ title, summary }): JSX.Element {
|
||||
return (
|
||||
<div>
|
||||
<h1>{title}</h1>
|
||||
<h2 style={{ fontSize: '3rem' }}>{summary}</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Home(): JSX.Element {
|
||||
const { siteConfig } = useDocusaurusContext();
|
||||
@@ -15,14 +23,11 @@ export default function Home(): JSX.Element {
|
||||
})}
|
||||
>
|
||||
<HomepageHeader />
|
||||
|
||||
<div style={{ textAlign: 'center', padding: '1rem 0' }}>
|
||||
<Demo />
|
||||
</div>
|
||||
|
||||
<div style={{ textAlign: 'center', padding: '0.5rem 2rem 1.5rem' }}>
|
||||
<div style={{ textAlign: 'center', padding: '2rem' }}>
|
||||
<br />
|
||||
<h2>Most Popular Links</h2>
|
||||
<ul style={{ listStyleType: 'none'}}>
|
||||
<li><a href="/modules/usage/Installation">How to Run OpenHands</a></li>
|
||||
<li><a href="/modules/usage/prompting/microagents-repo">Customizing OpenHands to a repository</a></li>
|
||||
<li><a href="/modules/usage/how-to/github-action">Integrating OpenHands with Github</a></li>
|
||||
<li><a href="/modules/usage/llms#model-recommendations">Recommended models to use</a></li>
|
||||
|
||||
@@ -56,10 +56,9 @@ You can update the arguments in the script
|
||||
./evaluation/benchmarks/aider_bench/scripts/run_infer.sh eval_gpt35_turbo HEAD CodeActAgent 100 1 "1,3,10"
|
||||
```
|
||||
|
||||
### Run Inference on `RemoteRuntime`
|
||||
|
||||
This is in beta. Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply if you want to try this out!
|
||||
### Run Inference on `RemoteRuntime` (experimental)
|
||||
|
||||
This is in limited beta. Contact Xingyao over slack if you want to try this out!
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/aider_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [eval-num-workers] [eval_ids]
|
||||
|
||||
@@ -205,6 +205,7 @@ def process_instance(
|
||||
|
||||
runtime: Runtime = create_runtime(config)
|
||||
call_async_from_sync(runtime.connect)
|
||||
|
||||
initialize_runtime(runtime, instance=instance)
|
||||
|
||||
# Here's how you can run the agent (similar to the `main` function) and get the final task state
|
||||
|
||||
@@ -25,7 +25,6 @@ from openhands.core.config import (
|
||||
from openhands.core.logger import openhands_logger as logger
|
||||
from openhands.core.main import create_runtime, run_controller
|
||||
from openhands.events.action import MessageAction
|
||||
from openhands.utils.async_utils import call_async_from_sync
|
||||
|
||||
# Only CodeActAgent can delegate to BrowsingAgent
|
||||
SUPPORTED_AGENT_CLS = {'CodeActAgent'}
|
||||
@@ -75,7 +74,6 @@ def process_instance(
|
||||
)
|
||||
|
||||
runtime = create_runtime(config)
|
||||
call_async_from_sync(runtime.connect)
|
||||
|
||||
state: State | None = asyncio.run(
|
||||
run_controller(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Commit0 Evaluation with OpenHands
|
||||
|
||||
This folder contains the evaluation harness that we built on top of the original [Commit0](https://commit-0.github.io/) ([paper](https://arxiv.org/abs/2412.01769v1)).
|
||||
This folder contains the evaluation harness that we built on top of the original [Commit0](https://commit-0.github.io/) ([paper](TBD)).
|
||||
|
||||
The evaluation consists of three steps:
|
||||
|
||||
@@ -23,10 +23,10 @@ Make sure your Docker daemon is running, and you have ample disk space (at least
|
||||
When the `run_infer.sh` script is started, it will automatically pull the `lite` split in Commit0. For example, for instance ID `commit-0/minitorch`, it will try to pull our pre-build docker image `wentingzhao/minitorch` from DockerHub. This image will be used create an OpenHands runtime image where the agent will operate on.
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/commit0/scripts/run_infer.sh [repo_split] [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
|
||||
./evaluation/benchmarks/commit0_bench/scripts/run_infer.sh [repo_split] [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
|
||||
|
||||
# Example
|
||||
./evaluation/benchmarks/commit0/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 16 100 8 wentingzhao/commit0_combined test
|
||||
./evaluation/benchmarks/commit0_bench/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 16 100 8 wentingzhao/commit0_combined test
|
||||
```
|
||||
|
||||
where `model_config` is mandatory, and the rest are optional.
|
||||
@@ -48,25 +48,26 @@ default, it is set to 1.
|
||||
- `dataset`, a huggingface dataset name. e.g. `wentingzhao/commit0_combined`, specifies which dataset to evaluate on.
|
||||
- `dataset_split`, split for the huggingface dataset. Notice only `test` is supported for Commit0.
|
||||
|
||||
Note that the `USE_INSTANCE_IMAGE` environment variable is always set to `true` for Commit0.
|
||||
|
||||
Let's say you'd like to run 10 instances using `llm.eval_sonnet` and CodeActAgent,
|
||||
|
||||
then your command would be:
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/commit0/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 10 30 1 wentingzhao/commit0_combined test
|
||||
./evaluation/benchmarks/commit0_bench/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 10 30 1 wentingzhao/commit0_combined test
|
||||
```
|
||||
|
||||
### Run Inference on `RemoteRuntime`
|
||||
|
||||
This is in beta. Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply if you want to try this out!
|
||||
### Run Inference on `RemoteRuntime` (experimental)
|
||||
|
||||
This is in limited beta. Contact Xingyao over slack if you want to try this out!
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/commit0/scripts/run_infer.sh [repo_split] [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
|
||||
./evaluation/benchmarks/commit0_bench/scripts/run_infer.sh [repo_split] [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
|
||||
|
||||
# Example - This runs evaluation on CodeActAgent for 10 instances on "wentingzhao/commit0_combined"'s test set, with max 30 iteration per instances, with 1 number of workers running in parallel
|
||||
ALLHANDS_API_KEY="YOUR-API-KEY" RUNTIME=remote SANDBOX_REMOTE_RUNTIME_API_URL="https://runtime.eval.all-hands.dev" EVAL_DOCKER_IMAGE_PREFIX="docker.io/wentingzhao" \
|
||||
./evaluation/benchmarks/commit0/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 10 30 1 wentingzhao/commit0_combined test
|
||||
./evaluation/benchmarks/commit0_bench/scripts/run_infer.sh lite llm.eval_sonnet HEAD CodeActAgent 10 30 1 wentingzhao/commit0_combined test
|
||||
```
|
||||
|
||||
To clean-up all existing runtime you've already started, run:
|
||||
@@ -39,6 +39,7 @@ from openhands.utils.async_utils import call_async_from_sync
|
||||
from openhands.utils.shutdown_listener import sleep_if_should_continue
|
||||
|
||||
USE_HINT_TEXT = os.environ.get('USE_HINT_TEXT', 'false').lower() == 'true'
|
||||
USE_INSTANCE_IMAGE = os.environ.get('USE_INSTANCE_IMAGE', 'false').lower() == 'true'
|
||||
RUN_WITH_BROWSING = os.environ.get('RUN_WITH_BROWSING', 'false').lower() == 'true'
|
||||
|
||||
AGENT_CLS_TO_FAKE_USER_RESPONSE_FN = {
|
||||
@@ -104,6 +105,7 @@ def get_config(
|
||||
instance: pd.Series,
|
||||
metadata: EvalMetadata,
|
||||
) -> AppConfig:
|
||||
assert USE_INSTANCE_IMAGE
|
||||
repo_name = instance['repo'].split('/')[1]
|
||||
base_container_image = get_instance_docker_image(repo_name)
|
||||
logger.info(
|
||||
@@ -301,16 +303,6 @@ def complete_runtime(
|
||||
pytest_exit_code = obs.content.strip()
|
||||
# logger.info(f'Pytest exit code: {pytest_exit_code}')
|
||||
|
||||
# Get test IDs from instance
|
||||
repo_name = instance['repo'].split('/')[1]
|
||||
repo_name = repo_name.replace('.', '-')
|
||||
action = CmdRunAction(command=f'commit0 get-tests {repo_name}')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
# logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
test_ids = obs.content.strip().split('\n')
|
||||
|
||||
# Read the test report
|
||||
action = CmdRunAction(command='cat report.json')
|
||||
action.set_hard_timeout(600)
|
||||
@@ -321,10 +313,18 @@ def complete_runtime(
|
||||
isinstance(obs, CmdOutputObservation),
|
||||
f'Failed to read test report: {str(obs)}',
|
||||
)
|
||||
json_report = obs.content.strip()
|
||||
# Get test IDs from instance
|
||||
repo_name = instance['repo'].split('/')[1]
|
||||
repo_name = repo_name.replace('.', '-')
|
||||
action = CmdRunAction(command=f'commit0 get-tests {repo_name}')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
# logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
test_ids = obs.content.strip().split('\n')
|
||||
|
||||
try:
|
||||
report = json.loads(json_report)
|
||||
report = json.loads(obs.content)
|
||||
tests = {x['nodeid']: x['call'] for x in report['tests'] if 'call' in x}
|
||||
|
||||
# Calculate test statistics
|
||||
@@ -30,6 +30,11 @@ if [ -z "$MAX_ITER" ]; then
|
||||
MAX_ITER=100
|
||||
fi
|
||||
|
||||
if [ -z "$USE_INSTANCE_IMAGE" ]; then
|
||||
echo "USE_INSTANCE_IMAGE not specified, use default true"
|
||||
USE_INSTANCE_IMAGE=true
|
||||
fi
|
||||
|
||||
if [ -z "$RUN_WITH_BROWSING" ]; then
|
||||
echo "RUN_WITH_BROWSING not specified, use default false"
|
||||
RUN_WITH_BROWSING=false
|
||||
@@ -51,6 +56,8 @@ if [ -z "$SPLIT" ]; then
|
||||
SPLIT="test"
|
||||
fi
|
||||
|
||||
export USE_INSTANCE_IMAGE=$USE_INSTANCE_IMAGE
|
||||
echo "USE_INSTANCE_IMAGE: $USE_INSTANCE_IMAGE"
|
||||
export RUN_WITH_BROWSING=$RUN_WITH_BROWSING
|
||||
echo "RUN_WITH_BROWSING: $RUN_WITH_BROWSING"
|
||||
|
||||
@@ -84,7 +91,7 @@ fi
|
||||
|
||||
function run_eval() {
|
||||
local eval_note=$1
|
||||
COMMAND="poetry run python evaluation/benchmarks/commit0/run_infer.py \
|
||||
COMMAND="poetry run python evaluation/benchmarks/commit0_bench/run_infer.py \
|
||||
--agent-cls $AGENT \
|
||||
--llm-config $MODEL_CONFIG \
|
||||
--max-iterations $MAX_ITER \
|
||||
@@ -13,7 +13,6 @@
|
||||
# limitations under the License.
|
||||
# This file is modified from https://github.com/ShishirPatil/gorilla/blob/main/eval/eval-scripts/ast_eval_hf.py
|
||||
|
||||
import tree_sitter_python as tspython
|
||||
from tree_sitter import Language, Parser
|
||||
|
||||
|
||||
@@ -40,9 +39,10 @@ def get_all_sub_trees(root_node):
|
||||
|
||||
|
||||
# Parse the program into AST trees
|
||||
def ast_parse(candidate):
|
||||
LANGUAGE = Language(tspython.language())
|
||||
parser = Parser(LANGUAGE)
|
||||
def ast_parse(candidate, lang='python'):
|
||||
LANGUAGE = Language('evaluation/gorilla/my-languages.so', lang)
|
||||
parser = Parser()
|
||||
parser.set_language(LANGUAGE)
|
||||
|
||||
candidate_tree = parser.parse(bytes(candidate, 'utf8')).root_node
|
||||
return candidate_tree
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
# limitations under the License.
|
||||
# This file is modified from https://github.com/ShishirPatil/gorilla/blob/main/eval/eval-scripts/ast_eval_tf.py
|
||||
|
||||
import tree_sitter_python as tspython
|
||||
from tree_sitter import Language, Parser
|
||||
|
||||
|
||||
@@ -40,9 +39,10 @@ def get_all_sub_trees(root_node):
|
||||
|
||||
|
||||
# Parse the program into AST trees
|
||||
def ast_parse(candidate):
|
||||
LANGUAGE = Language(tspython.language())
|
||||
parser = Parser(LANGUAGE)
|
||||
def ast_parse(candidate, lang='python'):
|
||||
LANGUAGE = Language('evaluation/gorilla/my-languages.so', lang)
|
||||
parser = Parser()
|
||||
parser.set_language(LANGUAGE)
|
||||
|
||||
candidate_tree = parser.parse(bytes(candidate, 'utf8')).root_node
|
||||
return candidate_tree
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
# limitations under the License.
|
||||
# This file is modified from https://github.com/ShishirPatil/gorilla/blob/main/eval/eval-scripts/ast_eval_th.py
|
||||
|
||||
import tree_sitter_python as tspython
|
||||
from tree_sitter import Language, Parser
|
||||
|
||||
|
||||
@@ -40,9 +39,10 @@ def get_all_sub_trees(root_node):
|
||||
|
||||
|
||||
# Parse the program into AST trees
|
||||
def ast_parse(candidate):
|
||||
LANGUAGE = Language(tspython.language())
|
||||
parser = Parser(LANGUAGE)
|
||||
def ast_parse(candidate, lang='python'):
|
||||
LANGUAGE = Language('evaluation/gorilla/my-languages.so', lang)
|
||||
parser = Parser()
|
||||
parser.set_language(LANGUAGE)
|
||||
|
||||
candidate_tree = parser.parse(bytes(candidate, 'utf8')).root_node
|
||||
return candidate_tree
|
||||
|
||||
@@ -71,19 +71,19 @@ def fetch_data(url, filename):
|
||||
|
||||
def get_data_for_hub(hub: str):
|
||||
if hub == 'hf':
|
||||
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/eval/eval-data/questions/huggingface/questions_huggingface_0_shot.jsonl'
|
||||
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/api/huggingface_api.jsonl'
|
||||
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/apibench/huggingface_eval.json'
|
||||
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/eval/eval-data/questions/huggingface/questions_huggingface_0_shot.jsonl'
|
||||
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/api/huggingface_api.jsonl'
|
||||
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/apibench/huggingface_eval.json'
|
||||
ast_eval = ast_eval_hf
|
||||
elif hub == 'torch':
|
||||
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/eval/eval-data/questions/torchhub/questions_torchhub_0_shot.jsonl'
|
||||
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/api/torchhub_api.jsonl'
|
||||
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/apibench/torchhub_eval.json'
|
||||
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/eval/eval-data/questions/torchhub/questions_torchhub_0_shot.jsonl'
|
||||
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/api/torchhub_api.jsonl'
|
||||
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/apibench/torchhub_eval.json'
|
||||
ast_eval = ast_eval_th
|
||||
elif hub == 'tf':
|
||||
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/eval/eval-data/questions/tensorflowhub/questions_tensorflowhub_0_shot.jsonl'
|
||||
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/api/tensorflowhub_api.jsonl'
|
||||
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/refs/tags/v1.2/data/apibench/tensorflow_eval.json'
|
||||
question_data = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/eval/eval-data/questions/tensorflowhub/questions_tensorflowhub_0_shot.jsonl'
|
||||
api_dataset = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/api/tensorflowhub_api.jsonl'
|
||||
apibench = 'https://raw.githubusercontent.com/ShishirPatil/gorilla/main/data/apibench/tensorflow_eval.json'
|
||||
ast_eval = ast_eval_tf
|
||||
|
||||
question_data = fetch_data(question_data, 'question_data.jsonl')
|
||||
|
||||
@@ -19,10 +19,9 @@ Access with browser the above MiniWoB URLs and see if they load correctly.
|
||||
./evaluation/benchmarks/miniwob/scripts/run_infer.sh llm.claude-35-sonnet-eval
|
||||
```
|
||||
|
||||
### Run Inference on `RemoteRuntime`
|
||||
|
||||
This is in beta. Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply if you want to try this out!
|
||||
### Run Inference on `RemoteRuntime` (experimental)
|
||||
|
||||
This is in limited beta. Contact Xingyao over slack if you want to try this out!
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/miniwob/scripts/run_infer.sh [model_config] [git-version] [agent] [note] [eval_limit] [num_workers]
|
||||
|
||||
@@ -2,13 +2,11 @@
|
||||
|
||||
This folder contains the evaluation harness that we built on top of the original [SWE-Bench benchmark](https://www.swebench.com/) ([paper](https://arxiv.org/abs/2310.06770)).
|
||||
|
||||
**UPDATE (2/18/2025): We now support running SWE-Gym using the same evaluation harness here. For more details, checkout [this README](./SWE-Gym.md).
|
||||
|
||||
**UPDATE (7/1/2024): We now support the official SWE-Bench dockerized evaluation as announced [here](https://github.com/princeton-nlp/SWE-bench/blob/main/docs/20240627_docker/README.md).**
|
||||
|
||||
The evaluation consists of three steps:
|
||||
|
||||
1. Environment setup: [install python environment](../../README.md#development-environment) and [configure LLM config](../../README.md#configure-openhands-and-your-llm).
|
||||
1. Environment setup: [install python environment](../../README.md#development-environment), [configure LLM config](../../README.md#configure-openhands-and-your-llm), and [pull docker](#openhands-swe-bench-instance-level-docker-support).
|
||||
2. [Run inference](#run-inference-on-swe-bench-instances): Generate a edit patch for each Github issue
|
||||
3. [Evaluate patches using SWE-Bench docker](#evaluate-generated-patches)
|
||||
|
||||
@@ -16,21 +14,22 @@ The evaluation consists of three steps:
|
||||
|
||||
Please follow instruction [here](../../README.md#setup) to setup your local development environment and LLM.
|
||||
|
||||
## Run Inference (Rollout) on SWE-Bench Instances: Generate Patch from Problem Statement
|
||||
## OpenHands SWE-Bench Instance-level Docker Support
|
||||
|
||||
### Running Locally with Docker
|
||||
OpenHands now support using the [official evaluation docker](https://github.com/princeton-nlp/SWE-bench/blob/main/docs/20240627_docker/README.md) for both **[inference](#run-inference-on-swe-bench-instances) and [evaluation](#evaluate-generated-patches)**.
|
||||
This is now the default behavior.
|
||||
|
||||
Make sure your Docker daemon is running, and you have ample disk space (at least 200-500GB, depends on the SWE-Bench set you are running on) for the instance-level docker image.
|
||||
## Run Inference on SWE-Bench Instances
|
||||
|
||||
When the `run_infer.sh` script is started, it will automatically pull the relevant SWE-Bench images.
|
||||
For example, for instance ID `django_django-11011`, it will try to pull our pre-build docker image `sweb.eval.x86_64.django_s_django-11011` from DockerHub.
|
||||
This image will be used create an OpenHands runtime image where the agent will operate on.
|
||||
Make sure your Docker daemon is running, and you have ample disk space (at least 200-500GB, depends on the SWE-Bench set you are running on) for the [instance-level docker image](#openhands-swe-bench-instance-level-docker-support).
|
||||
|
||||
When the `run_infer.sh` script is started, it will automatically pull the relevant SWE-Bench images. For example, for instance ID `django_django-11011`, it will try to pull our pre-build docker image `sweb.eval.x86_64.django_s_django-11011` from DockerHub. This image will be used create an OpenHands runtime image where the agent will operate on.
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
|
||||
|
||||
# Example
|
||||
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 500 100 1 princeton-nlp/SWE-bench_Verified test
|
||||
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 300 30 1 princeton-nlp/SWE-bench_Lite test
|
||||
```
|
||||
|
||||
where `model_config` is mandatory, and the rest are optional.
|
||||
@@ -48,16 +47,14 @@ in order to use `eval_limit`, you must also set `agent`.
|
||||
default, it is set to 30.
|
||||
- `num_workers`, e.g. `3`, is the number of parallel workers to run the evaluation. By
|
||||
default, it is set to 1.
|
||||
- `dataset`, a huggingface dataset name. e.g. `princeton-nlp/SWE-bench`, `princeton-nlp/SWE-bench_Lite`, or `princeton-nlp/SWE-bench_Verified`, specifies which dataset to evaluate on.
|
||||
- `dataset`, a huggingface dataset name. e.g. `princeton-nlp/SWE-bench` or `princeton-nlp/SWE-bench_Lite`, specifies which dataset to evaluate on.
|
||||
- `dataset_split`, split for the huggingface dataset. e.g., `test`, `dev`. Default to `test`.
|
||||
|
||||
> [!CAUTION]
|
||||
> Setting `num_workers` larger than 1 is not officially tested, YMMV.
|
||||
|
||||
There is also one optional environment variable you can set.
|
||||
There are also two optional environment variables you can set.
|
||||
|
||||
```bash
|
||||
export USE_HINT_TEXT=true # if you want to use hint text in the evaluation. Default to false. Ignore this if you are not sure.
|
||||
export USE_INSTANCE_IMAGE=true # if you want to use instance-level docker images. Default to true
|
||||
```
|
||||
|
||||
Let's say you'd like to run 10 instances using `llm.eval_gpt4_1106_preview` and CodeActAgent,
|
||||
@@ -68,11 +65,9 @@ then your command would be:
|
||||
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 10
|
||||
```
|
||||
|
||||
### Running in parallel with RemoteRuntime
|
||||
### Run Inference on `RemoteRuntime` (experimental)
|
||||
|
||||
OpenHands Remote Runtime is currently in beta (read [here](https://runtime.all-hands.dev/) for more details), it allows you to run rollout in parallel in the cloud, so you don't need a powerful machine to run evaluation.
|
||||
|
||||
Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply if you want to try this out!
|
||||
This is in limited beta. Contact Xingyao over slack if you want to try this out!
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/swe_bench/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
|
||||
@@ -105,14 +100,41 @@ After running the inference, you will obtain a `output.jsonl` (by default it wil
|
||||
|
||||
## Evaluate Generated Patches
|
||||
|
||||
### Run evaluation with official SWE-Bench harness (Recommend if you have local disk space)
|
||||
### Download Docker Images
|
||||
|
||||
**(Recommended for reproducibility)** If you have extra local space (e.g., 200GB), you can try pull the [instance-level docker images](https://github.com/princeton-nlp/SWE-bench/blob/main/docs/20240627_docker/README.md#choosing-the-right-cache_level) we've prepared by running:
|
||||
|
||||
```bash
|
||||
evaluation/benchmarks/swe_bench/scripts/docker/pull_all_eval_docker.sh instance
|
||||
```
|
||||
|
||||
If you want to save disk space a bit (e.g., with ~50GB free disk space), while speeding up the image pre-build process, you can pull the environment-level docker images:
|
||||
|
||||
```bash
|
||||
evaluation/benchmarks/swe_bench/scripts/docker/pull_all_eval_docker.sh env
|
||||
```
|
||||
|
||||
If you want to evaluate on the full SWE-Bench test set:
|
||||
|
||||
```bash
|
||||
evaluation/benchmarks/swe_bench/scripts/docker/pull_all_eval_docker.sh instance full
|
||||
```
|
||||
|
||||
### Run evaluation
|
||||
|
||||
With `output.jsonl` file, you can run `eval_infer.sh` to evaluate generated patches, and produce a fine-grained report.
|
||||
|
||||
**This evaluation is performed using the official dockerized evaluation announced [here](https://github.com/princeton-nlp/SWE-bench/blob/main/docs/20240627_docker/README.md).**
|
||||
|
||||
> [!NOTE]
|
||||
> This process will automatically download docker images from SWE-Bench official docker hub, please make sure you have enough disk space!
|
||||
> If you want to evaluate existing results, you should first run this to clone existing outputs
|
||||
>
|
||||
>```bash
|
||||
>git clone https://huggingface.co/spaces/OpenHands/evaluation evaluation/evaluation_outputs
|
||||
>```
|
||||
|
||||
NOTE, you should have already pulled the instance-level OR env-level docker images following [this section](#openhands-swe-bench-instance-level-docker-support).
|
||||
|
||||
Then you can run the following:
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/swe_bench/scripts/eval_infer.sh $YOUR_OUTPUT_JSONL [instance_id] [dataset_name] [split]
|
||||
@@ -141,10 +163,9 @@ The final results will be saved to `evaluation/evaluation_outputs/outputs/swe_be
|
||||
- `report.json`: a JSON file that contains keys like `"resolved_ids"` pointing to instance IDs that are resolved by the agent.
|
||||
- `logs/`: a directory of test logs
|
||||
|
||||
### Run evaluation with `RemoteRuntime`
|
||||
### Run evaluation with `RemoteRuntime` (experimental)
|
||||
|
||||
OpenHands Remote Runtime is currently in beta (read [here](https://runtime.all-hands.dev/) for more details), it allows you to run rollout in parallel in the cloud, so you don't need a powerful machine to run evaluation.
|
||||
Fill out [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply if you want to try this out!
|
||||
This is in limited beta. Contact Xingyao over slack if you want to try this out!
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/swe_bench/scripts/eval_infer_remote.sh [output.jsonl filepath] [num_workers]
|
||||
@@ -159,3 +180,35 @@ To clean-up all existing runtimes that you've already started, run:
|
||||
```bash
|
||||
ALLHANDS_API_KEY="YOUR-API-KEY" ./evaluation/utils/scripts/cleanup_remote_runtime.sh
|
||||
```
|
||||
|
||||
## Visualize Results
|
||||
|
||||
First you need to clone `https://huggingface.co/spaces/OpenHands/evaluation` and add your own running results from openhands into the `outputs` of the cloned repo.
|
||||
|
||||
```bash
|
||||
git clone https://huggingface.co/spaces/OpenHands/evaluation
|
||||
```
|
||||
|
||||
**(optional) setup streamlit environment with conda**:
|
||||
|
||||
```bash
|
||||
cd evaluation
|
||||
conda create -n streamlit python=3.10
|
||||
conda activate streamlit
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
**run the visualizer**:
|
||||
Then, in a separate Python environment with `streamlit` library, you can run the following:
|
||||
|
||||
```bash
|
||||
# Make sure you are inside the cloned `evaluation` repo
|
||||
conda activate streamlit # if you follow the optional conda env setup above
|
||||
streamlit run app.py --server.port 8501 --server.address 0.0.0.0
|
||||
```
|
||||
|
||||
Then you can access the SWE-Bench trajectory visualizer at `localhost:8501`.
|
||||
|
||||
## Submit your evaluation results
|
||||
|
||||
You can start your own fork of [our huggingface evaluation outputs](https://huggingface.co/spaces/OpenHands/evaluation) and submit a PR of your evaluation results following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
<h1 align="center"> Training Software Engineering Agents and Verifiers with SWE-Gym </h1>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.jiayipan.com/" style="text-decoration: none;">Jiayi Pan<sup>*,1</sup></a>,
|
||||
<a href="https://xwang.dev/" style="text-decoration: none;">Xingyao Wang<sup>*,2</sup></a>,
|
||||
<a href="https://www.phontron.com/" style="text-decoration: none;">Graham Neubig<sup>3</sup></a>,
|
||||
<a href="https://www.cs.toronto.edu/~ndjaitly/" style="text-decoration: none;">Navdeep Jaitly<sup>4</sup></a>,
|
||||
<a href="https://blender.cs.illinois.edu/hengji.html" style="text-decoration: none;">Heng Ji<sup>2</sup></a>,
|
||||
<a href="https://www.alanesuhr.com/" style="text-decoration: none;">Alane Suhr<sup>^,1</sup></a>,
|
||||
<a href="https://dreasysnail.github.io/" style="text-decoration: none;">Yizhe Zhang<sup>^,4</sup></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<sup>1</sup>UC Berkeley, <sup>2</sup>UIUC, <sup>3</sup>CMU, <sup>4</sup>Apple </br>
|
||||
<sub><sup>*</sup>Equal contribution, <sup>^</sup>Equal supervision</sub>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://arxiv.org/abs/2412.21139">📃 Paper</a>
|
||||
•
|
||||
<a href="https://huggingface.co/SWE-Gym" >🤗 Data & Models</a>
|
||||
</p>
|
||||
|
||||
We present **SWE-Gym**, the first environment for training real-world software engineering agents.
|
||||
We use it to train strong LM agents that achieve state-of-the-art open results on SWE-Bench, with early, promising scaling characteristics as we increase training and inference-time compute.
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/SWE-Gym/SWE-Gym/blob/main/assets/images/teaser.jpg?raw=true" width="100%" alt="teaser">
|
||||
</p>
|
||||
|
||||
---
|
||||
# Run SWE-Gym with OpenHands
|
||||
|
||||
The process of running SWE-Gym is very similar to how you'd run SWE-Bench evaluation.
|
||||
|
||||
|
||||
1. First, clone OpenHands repo `git clone https://github.com/All-Hands-AI/OpenHands.git`
|
||||
2. Then setup the repo following [Development.md](https://github.com/All-Hands-AI/OpenHands/blob/main/Development.md)
|
||||
3. Then you can simply serve your own model as an OpenAI compatible endpoint, put those info in config.toml. You can do this by following instruction [here](../../README.md#setup).
|
||||
4. And then simply do the following to sample for 16x parallelism:
|
||||
|
||||
```bash
|
||||
export ALLHANDS_API_KEY=ah-yourkey # You don't need to set this when running these in local docker container
|
||||
./evaluation/benchmarks/swe_bench/scripts/rollout_swegym.sh llm.mymodel-temp05 'train-t05' 16
|
||||
```
|
||||
|
||||
NOTE: SWE-Gym sampling with parallelism is currently only tested with AllHands RemoteRuntime (limited beta). Fill [this form](https://docs.google.com/forms/d/e/1FAIpQLSckVz_JFwg2_mOxNZjCtr7aoBFI2Mwdan3f75J_TrdMS1JV2g/viewform) to apply for access.
|
||||
|
||||
|
||||
5. When `rollout_swegym.sh` finishes, you will get a file called `output.with_completions.jsonl.gz`. Then you can use [`./scripts/swegym/convert_data.ipynb`](./scripts/swegym/convert_data.ipynb) to convert them into SFT data format.
|
||||
|
||||
---
|
||||
# More info about SWE-Gym
|
||||
|
||||
Progress in agents for software engineering has been limited by the lack of training environments that both include rigorous verification for reinforcement learning and cover the expansive tasks encountered in real-world repository-level engineering.
|
||||
|
||||
We introduce SWE-Gym: An Open Environment for Training Software Engineering Agents & Verifiers.
|
||||
Our baselines achieve new open SOTA - 32%/26% on SWE-Bench Verified/Lite, with promising scaling trends.
|
||||
|
||||

|
||||
*SWE-Gym enables scalable improvements for software engineering agents at both training and inference time. Our current results is primarily bottlenecked by training and inference compute, rather than the size of our environment.*
|
||||
|
||||
## SWE-Gym Environment
|
||||
|
||||
We create SWE-Gym, the first environment for training SWE agents, with **2.4K real tasks from 11 Python repos** & a Lite split of 234 instances. SWE-Gym combines real-world Python tasks, repository context, executable environments, and test verification to train agents for solving software engineering problems.
|
||||
|
||||

|
||||
|
||||
|
||||
## SWE-Gym trains LMs as agents
|
||||
|
||||
When fine-tuned on less than 500 agent-environment interaction trajectories sampled from it from GPT-4o and Claude 3.5 Sonnet, we achieve **+14%** absolute gains on SWE-Bench Verified with an 32B LM-powered OpenHands agent.
|
||||
|
||||

|
||||
|
||||
|
||||
## SWE-Gym enables self-improvement
|
||||
|
||||
SWE-Gym is also effective across agent scaffolds. With rejection sampling fine-tuning and MoatlessTools scaffold, our 32B and 7B models achieve 20% and 10% respectively on SWE-Bench Lite through self-improvement.
|
||||
|
||||
<p align="center">
|
||||
<img src="https://github.com/SWE-Gym/SWE-Gym/blob/main/assets/images/ml-agent.jpg?raw=true" width="80%" alt="Moatless self-improvement">
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
## SWE-Gym enables inference-time scaling
|
||||
|
||||
SWE-Gym enables inference-time scaling through verifiers trained on agent trajectories.
|
||||
These verifiers identify most promising solutions via best-of-n selection, together with our learned agents, they achieve 32%/26% on SWE-Bench Verified/Lite, a new open SoTA.
|
||||
|
||||
|
||||

|
||||
*Inference Time Scaling for Moatless Agent*
|
||||
|
||||

|
||||
*Inference Time Scaling for OpenHands Agent*
|
||||
|
||||
|
||||
## Our baselines on SWE-Gym shows strong scaling trends
|
||||
|
||||
Lastly, our ablations reveal strong scaling trends - performance is now bottlenecked by train and inference compute, rather than the size of our dataset. Pushing and improving these scaling trends further is an exciting direction for future work.
|
||||
|
||||

|
||||
|
||||
## Reproducing Results
|
||||
**The Dataset**
|
||||
|
||||
To access SWE-Gym dataset, checkout our huggingface hub page [SWE-Gym](https://huggingface.co/SWE-Gym)
|
||||
|
||||
The environment constants are currently saved at [SWE-Bench-Fork](https://github.com/SWE-Gym/SWE-Bench-Fork)
|
||||
|
||||
We also have pre-built docker images for each instance under [xingyaoww/sweb.eval.x86_64](https://hub.docker.com/search?q=xingyaoww%2Fsweb.eval.x86_64.) prefix at docker hub.
|
||||
|
||||
|
||||
## 📚 Citation
|
||||
|
||||
```bibtex
|
||||
@misc{pan2024trainingsoftwareengineeringagents,
|
||||
title={Training Software Engineering Agents and Verifiers with SWE-Gym},
|
||||
author={Jiayi Pan and Xingyao Wang and Graham Neubig and Navdeep Jaitly and Heng Ji and Alane Suhr and Yizhe Zhang},
|
||||
year={2024},
|
||||
eprint={2412.21139},
|
||||
archivePrefix={arXiv},
|
||||
primaryClass={cs.SE},
|
||||
url={https://arxiv.org/abs/2412.21139},
|
||||
}
|
||||
```
|
||||
@@ -1,14 +1,18 @@
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from functools import partial
|
||||
from typing import Callable
|
||||
|
||||
import pandas as pd
|
||||
from swebench.harness.grading import get_eval_report
|
||||
from swebench.harness.run_evaluation import (
|
||||
APPLY_PATCH_FAIL,
|
||||
APPLY_PATCH_PASS,
|
||||
)
|
||||
from swebench.harness.test_spec import SWEbenchInstance, TestSpec, make_test_spec
|
||||
from swebench.harness.utils import load_swebench_dataset
|
||||
from tqdm import tqdm
|
||||
|
||||
from evaluation.benchmarks.swe_bench.resource.mapping import (
|
||||
@@ -94,22 +98,12 @@ def get_config(metadata: EvalMetadata, instance: pd.Series) -> AppConfig:
|
||||
return config
|
||||
|
||||
|
||||
@dataclass
|
||||
class ConditionalImports:
|
||||
"""We instantiate the values in this dataclass differently if we're evaluating SWE-bench or SWE-Gym."""
|
||||
|
||||
get_eval_report: Callable
|
||||
APPLY_PATCH_FAIL: str
|
||||
APPLY_PATCH_PASS: str
|
||||
|
||||
|
||||
def process_instance(
|
||||
instance: pd.Series,
|
||||
metadata: EvalMetadata,
|
||||
reset_logger: bool = True,
|
||||
log_dir: str | None = None,
|
||||
runtime_failure_count: int = 0,
|
||||
conditional_imports: ConditionalImports | None = None,
|
||||
) -> EvalOutput:
|
||||
"""
|
||||
Evaluate agent performance on a SWE-bench problem instance.
|
||||
@@ -121,18 +115,9 @@ def process_instance(
|
||||
log_dir (str | None, default=None): Path to directory where log files will be written. Must
|
||||
be provided if `reset_logger` is set.
|
||||
|
||||
conditional_imports: A dataclass containing values that are imported differently based on
|
||||
whether we're evaluating SWE-bench or SWE-Gym.
|
||||
|
||||
Raises:
|
||||
AssertionError: if the `reset_logger` flag is set without a provided log directory.
|
||||
|
||||
AssertionError: if `conditional_imports` is not provided.
|
||||
"""
|
||||
assert (
|
||||
conditional_imports is not None
|
||||
), 'conditional_imports must be provided to run process_instance using multiprocessing'
|
||||
|
||||
# Setup the logger properly, so you can run multi-processing to parallelize the evaluation
|
||||
if reset_logger:
|
||||
assert (
|
||||
@@ -146,7 +131,7 @@ def process_instance(
|
||||
config = get_config(metadata, instance)
|
||||
instance_id = instance.instance_id
|
||||
model_patch = instance['model_patch']
|
||||
test_spec = instance['test_spec']
|
||||
test_spec: TestSpec = instance['test_spec']
|
||||
logger.info(f'Starting evaluation for instance {instance_id}.')
|
||||
|
||||
if 'test_result' not in instance.keys():
|
||||
@@ -176,11 +161,6 @@ def process_instance(
|
||||
logger.warning(
|
||||
f'This is the {runtime_failure_count + 1}th attempt for instance {instance.instance_id}, setting resource factor to {config.sandbox.remote_runtime_resource_factor}'
|
||||
)
|
||||
metadata = copy.deepcopy(metadata)
|
||||
metadata.details['runtime_failure_count'] = runtime_failure_count
|
||||
metadata.details['remote_runtime_resource_factor'] = (
|
||||
config.sandbox.remote_runtime_resource_factor
|
||||
)
|
||||
|
||||
try:
|
||||
runtime = create_runtime(config)
|
||||
@@ -223,9 +203,7 @@ def process_instance(
|
||||
instance['test_result']['apply_patch_output'] = apply_patch_output
|
||||
|
||||
if 'APPLY_PATCH_FAIL' in apply_patch_output:
|
||||
logger.info(
|
||||
f'[{instance_id}] {conditional_imports.APPLY_PATCH_FAIL}:\n{apply_patch_output}'
|
||||
)
|
||||
logger.info(f'[{instance_id}] {APPLY_PATCH_FAIL}:\n{apply_patch_output}')
|
||||
instance['test_result']['report']['failed_apply_patch'] = True
|
||||
|
||||
return EvalOutput(
|
||||
@@ -234,9 +212,7 @@ def process_instance(
|
||||
metadata=metadata,
|
||||
)
|
||||
elif 'APPLY_PATCH_PASS' in apply_patch_output:
|
||||
logger.info(
|
||||
f'[{instance_id}] {conditional_imports.APPLY_PATCH_PASS}:\n{apply_patch_output}'
|
||||
)
|
||||
logger.info(f'[{instance_id}] {APPLY_PATCH_PASS}:\n{apply_patch_output}')
|
||||
|
||||
# Run eval script in background and save output to log file
|
||||
log_file = '/tmp/eval_output.log'
|
||||
@@ -302,20 +278,14 @@ def process_instance(
|
||||
with open(test_output_path, 'w') as f:
|
||||
f.write(test_output)
|
||||
try:
|
||||
extra_kwargs = {}
|
||||
if 'SWE-Gym' in metadata.dataset:
|
||||
# SWE-Gym uses a different version of the package, hence a different eval report argument
|
||||
extra_kwargs['log_path'] = test_output_path
|
||||
else:
|
||||
extra_kwargs['test_log_path'] = test_output_path
|
||||
_report = conditional_imports.get_eval_report(
|
||||
_report = get_eval_report(
|
||||
test_spec=test_spec,
|
||||
prediction={
|
||||
'model_patch': model_patch,
|
||||
'instance_id': instance_id,
|
||||
},
|
||||
log_path=test_output_path,
|
||||
include_tests_status=True,
|
||||
**extra_kwargs,
|
||||
)
|
||||
report = _report[instance_id]
|
||||
logger.info(
|
||||
@@ -374,29 +344,6 @@ if __name__ == '__main__':
|
||||
)
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
if 'SWE-Gym' in args.dataset:
|
||||
from swegym.harness.grading import get_eval_report
|
||||
from swegym.harness.run_evaluation import (
|
||||
APPLY_PATCH_FAIL,
|
||||
APPLY_PATCH_PASS,
|
||||
)
|
||||
from swegym.harness.test_spec import (
|
||||
SWEbenchInstance,
|
||||
make_test_spec,
|
||||
)
|
||||
from swegym.harness.utils import load_swebench_dataset
|
||||
else: # Newer version of SWE-Bench have different import paths
|
||||
from swebench.harness.grading import get_eval_report
|
||||
from swebench.harness.run_evaluation import (
|
||||
APPLY_PATCH_FAIL,
|
||||
APPLY_PATCH_PASS,
|
||||
)
|
||||
from swebench.harness.test_spec.test_spec import (
|
||||
SWEbenchInstance,
|
||||
make_test_spec,
|
||||
)
|
||||
from swebench.harness.utils import load_swebench_dataset
|
||||
|
||||
# Load SWE-Bench dataset
|
||||
full_dataset: list[SWEbenchInstance] = load_swebench_dataset(
|
||||
args.dataset, args.split
|
||||
@@ -475,21 +422,12 @@ if __name__ == '__main__':
|
||||
.decode('utf-8')
|
||||
.strip(), # Current commit
|
||||
dataset=args.dataset, # Dataset name from args
|
||||
details={},
|
||||
)
|
||||
|
||||
# The evaluation harness constrains the signature of `process_instance_func` but we need to
|
||||
# pass extra information. Build a new function object to avoid issues with multiprocessing.
|
||||
process_instance_func = partial(
|
||||
process_instance,
|
||||
log_dir=output_file.replace('.jsonl', '.logs'),
|
||||
# We have to explicitly pass these imports to the process_instance function, otherwise
|
||||
# they won't be available in the multiprocessing context.
|
||||
conditional_imports=ConditionalImports(
|
||||
get_eval_report=get_eval_report,
|
||||
APPLY_PATCH_FAIL=APPLY_PATCH_FAIL,
|
||||
APPLY_PATCH_PASS=APPLY_PATCH_PASS,
|
||||
),
|
||||
process_instance, log_dir=output_file.replace('.jsonl', '.logs')
|
||||
)
|
||||
|
||||
run_evaluation(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@ def get_resource_mapping(dataset_name: str) -> dict[str, float]:
|
||||
if dataset_name not in _global_resource_mapping:
|
||||
file_path = os.path.join(CUR_DIR, f'{dataset_name}.json')
|
||||
if not os.path.exists(file_path):
|
||||
logger.info(f'Resource mapping for {dataset_name} not found.')
|
||||
logger.warning(f'Resource mapping for {dataset_name} not found.')
|
||||
return None
|
||||
|
||||
with open(file_path, 'r') as f:
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import asyncio
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
@@ -45,6 +44,7 @@ from openhands.utils.async_utils import call_async_from_sync
|
||||
from openhands.utils.shutdown_listener import sleep_if_should_continue
|
||||
|
||||
USE_HINT_TEXT = os.environ.get('USE_HINT_TEXT', 'false').lower() == 'true'
|
||||
USE_INSTANCE_IMAGE = os.environ.get('USE_INSTANCE_IMAGE', 'true').lower() == 'true'
|
||||
RUN_WITH_BROWSING = os.environ.get('RUN_WITH_BROWSING', 'false').lower() == 'true'
|
||||
|
||||
|
||||
@@ -59,108 +59,68 @@ def _get_swebench_workspace_dir_name(instance: pd.Series) -> str:
|
||||
|
||||
def get_instruction(instance: pd.Series, metadata: EvalMetadata):
|
||||
workspace_dir_name = _get_swebench_workspace_dir_name(instance)
|
||||
instruction = f"""
|
||||
<uploaded_files>
|
||||
/workspace/{workspace_dir_name}
|
||||
</uploaded_files>
|
||||
# Prepare instruction
|
||||
|
||||
I've uploaded a python code repository in the directory {workspace_dir_name}. Consider the following issue description:
|
||||
|
||||
<issue_description>
|
||||
{instance.problem_statement}
|
||||
</issue_description>
|
||||
|
||||
Can you help me implement the necessary changes to the repository so that the requirements specified in the <issue_description> are met?
|
||||
I've already taken care of all changes to any of the test files described in the <issue_description>. This means you DON'T have to modify the testing logic or any of the tests in any way!
|
||||
Also the development Python environment is already set up for you (i.e., all dependencies already installed), so you don't need to install other packages.
|
||||
Your task is to make the minimal changes to non-test files in the /workspace/{workspace_dir_name} directory to ensure the <issue_description> is satisfied.
|
||||
|
||||
Follow these steps to resolve the issue:
|
||||
|
||||
1. EXPLORATION: First, thoroughly explore the repository structure using tools like `find` and `grep`.
|
||||
- Identify all files mentioned in the problem statement
|
||||
- Locate where the issue occurs in the codebase
|
||||
- Understand the surrounding context and dependencies
|
||||
- Use `grep` to search for relevant functions, classes, or error messages
|
||||
|
||||
2. ANALYSIS: Based on your exploration, think carefully about the problem and propose 2-5 possible approaches to fix the issue.
|
||||
- Analyze the root cause of the problem
|
||||
- Consider trade-offs between different solutions
|
||||
- Select the most promising approach and explain your reasoning
|
||||
|
||||
3. TEST CREATION: Before implementing any fix, create a script to reproduce and verify the issue.
|
||||
- Look at existing test files in the repository to understand the test format/structure
|
||||
- Create a minimal reproduction script that demonstrates the issue
|
||||
- Run your script to confirm the error exists
|
||||
|
||||
4. IMPLEMENTATION: Edit the source code to implement your chosen solution.
|
||||
- Make minimal, focused changes to fix the issue
|
||||
|
||||
5. VERIFICATION: Test your implementation thoroughly.
|
||||
- Run your reproduction script to verify the fix works
|
||||
- Add edge cases to your test script to ensure comprehensive coverage
|
||||
- Run existing tests related to the modified code to ensure you haven't broken anything
|
||||
|
||||
6. FINAL REVIEW: Carefully re-read the problem description and compare your changes with the base commit {instance["base_commit"]}.
|
||||
- Ensure you've fully addressed all requirements
|
||||
- Run any tests in the repository related to:
|
||||
* The issue you are fixing
|
||||
* The files you modified
|
||||
* The functions you changed
|
||||
- If any tests fail, revise your implementation until all tests pass
|
||||
|
||||
Be thorough in your exploration, testing, and reasoning. It's fine if your thinking process is lengthy - quality and completeness are more important than brevity.
|
||||
"""
|
||||
# Instruction based on Anthropic's official trajectory
|
||||
# https://github.com/eschluntz/swe-bench-experiments/tree/main/evaluation/verified/20241022_tools_claude-3-5-sonnet-updated/trajs
|
||||
instruction = (
|
||||
'<uploaded_files>\n'
|
||||
f'/workspace/{workspace_dir_name}\n'
|
||||
'</uploaded_files>\n'
|
||||
f"I've uploaded a python code repository in the directory {workspace_dir_name}. Consider the following issue description:\n\n"
|
||||
f'<issue_description>\n'
|
||||
f'{instance.problem_statement}\n'
|
||||
'</issue_description>\n\n'
|
||||
'Can you help me implement the necessary changes to the repository so that the requirements specified in the <issue_description> are met?\n'
|
||||
"I've already taken care of all changes to any of the test files described in the <pr_description>. This means you DON'T have to modify the testing logic or any of the tests in any way!\n"
|
||||
'Your task is to make the minimal changes to non-tests files in the /workspace directory to ensure the <pr_description> is satisfied.\n'
|
||||
'Follow these steps to resolve the issue:\n'
|
||||
'1. As a first step, it might be a good idea to explore the repo to familiarize yourself with its structure.\n'
|
||||
'2. Create a script to reproduce the error and execute it with `python <filename.py>` using the BashTool, to confirm the error\n'
|
||||
'3. Edit the sourcecode of the repo to resolve the issue\n'
|
||||
'4. Rerun your reproduce script and confirm that the error is fixed!\n'
|
||||
'5. Think about edgecases and make sure your fix handles them as well\n'
|
||||
"Your thinking should be thorough and so it's fine if it's very long.\n"
|
||||
)
|
||||
|
||||
if RUN_WITH_BROWSING:
|
||||
instruction += """
|
||||
<IMPORTANT!>
|
||||
You SHOULD NEVER attempt to browse the web.
|
||||
</IMPORTANT!>
|
||||
"""
|
||||
instruction += (
|
||||
'<IMPORTANT!>\n'
|
||||
'You SHOULD NEVER attempt to browse the web. '
|
||||
'</IMPORTANT!>\n'
|
||||
)
|
||||
return instruction
|
||||
|
||||
|
||||
# TODO: migrate all swe-bench docker to ghcr.io/openhands
|
||||
DEFAULT_DOCKER_IMAGE_PREFIX = os.environ.get('EVAL_DOCKER_IMAGE_PREFIX', 'docker.io/xingyaoww/')
|
||||
logger.info(f'Default docker image prefix: {DEFAULT_DOCKER_IMAGE_PREFIX}')
|
||||
DOCKER_IMAGE_PREFIX = os.environ.get('EVAL_DOCKER_IMAGE_PREFIX', 'docker.io/xingyaoww/')
|
||||
logger.info(f'Using docker image prefix: {DOCKER_IMAGE_PREFIX}')
|
||||
|
||||
|
||||
def get_instance_docker_image(instance_id: str, official_image: bool = False) -> str:
|
||||
if official_image:
|
||||
# Official SWE-Bench image
|
||||
# swebench/sweb.eval.x86_64.django_1776_django-11333:v1
|
||||
docker_image_prefix = 'docker.io/swebench/'
|
||||
repo, name = instance_id.split('__')
|
||||
image_name = f'sweb.eval.x86_64.{repo}_1776_{name}:latest'
|
||||
logger.warning(f'Using official SWE-Bench image: {image_name}')
|
||||
else:
|
||||
# OpenHands version of the image
|
||||
docker_image_prefix = DEFAULT_DOCKER_IMAGE_PREFIX
|
||||
image_name = 'sweb.eval.x86_64.' + instance_id
|
||||
image_name = image_name.replace(
|
||||
'__', '_s_'
|
||||
) # to comply with docker image naming convention
|
||||
return (docker_image_prefix.rstrip('/') + '/' + image_name).lower()
|
||||
def get_instance_docker_image(instance_id: str) -> str:
|
||||
image_name = 'sweb.eval.x86_64.' + instance_id
|
||||
image_name = image_name.replace(
|
||||
'__', '_s_'
|
||||
) # to comply with docker image naming convention
|
||||
return (DOCKER_IMAGE_PREFIX.rstrip('/') + '/' + image_name).lower()
|
||||
|
||||
|
||||
def get_config(
|
||||
instance: pd.Series,
|
||||
metadata: EvalMetadata,
|
||||
) -> AppConfig:
|
||||
# We use a different instance image for the each instance of swe-bench eval
|
||||
use_official_image = bool(
|
||||
('verified' in metadata.dataset.lower() or 'lite' in metadata.dataset.lower())
|
||||
and 'swe-gym' not in metadata.dataset.lower()
|
||||
)
|
||||
base_container_image = get_instance_docker_image(
|
||||
instance['instance_id'], use_official_image
|
||||
)
|
||||
logger.info(
|
||||
f'Using instance container image: {base_container_image}. '
|
||||
f'Please make sure this image exists. '
|
||||
f'Submit an issue on https://github.com/All-Hands-AI/OpenHands if you run into any issues.'
|
||||
)
|
||||
SWE_BENCH_CONTAINER_IMAGE = 'ghcr.io/opendevin/eval-swe-bench:full-v1.2.1'
|
||||
if USE_INSTANCE_IMAGE:
|
||||
# We use a different instance image for the each instance of swe-bench eval
|
||||
base_container_image = get_instance_docker_image(instance['instance_id'])
|
||||
logger.info(
|
||||
f'Using instance container image: {base_container_image}. '
|
||||
f'Please make sure this image exists. '
|
||||
f'Submit an issue on https://github.com/All-Hands-AI/OpenHands if you run into any issues.'
|
||||
)
|
||||
else:
|
||||
base_container_image = SWE_BENCH_CONTAINER_IMAGE
|
||||
logger.info(f'Using swe-bench container image: {base_container_image}')
|
||||
|
||||
sandbox_config = get_default_sandbox_config_for_eval()
|
||||
sandbox_config.base_container_image = base_container_image
|
||||
@@ -232,65 +192,75 @@ def initialize_runtime(
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(obs.exit_code == 0, f'Failed to export USER: {str(obs)}')
|
||||
|
||||
# inject the init script
|
||||
script_dir = os.path.dirname(__file__)
|
||||
if USE_INSTANCE_IMAGE:
|
||||
# inject the init script
|
||||
script_dir = os.path.dirname(__file__)
|
||||
|
||||
# inject the instance info
|
||||
action = CmdRunAction(command='mkdir -p /swe_util/eval_data/instances')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0,
|
||||
f'Failed to create /swe_util/eval_data/instances: {str(obs)}',
|
||||
)
|
||||
# inject the instance info
|
||||
action = CmdRunAction(command='mkdir -p /swe_util/eval_data/instances')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0,
|
||||
f'Failed to create /swe_util/eval_data/instances: {str(obs)}',
|
||||
)
|
||||
|
||||
swe_instance_json_name = 'swe-bench-instance.json'
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
# Construct the full path for the desired file name within the temporary directory
|
||||
temp_file_path = os.path.join(temp_dir, swe_instance_json_name)
|
||||
# Write to the file with the desired name within the temporary directory
|
||||
with open(temp_file_path, 'w') as f:
|
||||
if not isinstance(instance, dict):
|
||||
json.dump([instance.to_dict()], f)
|
||||
else:
|
||||
json.dump([instance], f)
|
||||
swe_instance_json_name = 'swe-bench-instance.json'
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
# Construct the full path for the desired file name within the temporary directory
|
||||
temp_file_path = os.path.join(temp_dir, swe_instance_json_name)
|
||||
# Write to the file with the desired name within the temporary directory
|
||||
with open(temp_file_path, 'w') as f:
|
||||
if not isinstance(instance, dict):
|
||||
json.dump([instance.to_dict()], f)
|
||||
else:
|
||||
json.dump([instance], f)
|
||||
|
||||
# Copy the file to the desired location
|
||||
runtime.copy_to(temp_file_path, '/swe_util/eval_data/instances/')
|
||||
# Copy the file to the desired location
|
||||
runtime.copy_to(temp_file_path, '/swe_util/eval_data/instances/')
|
||||
|
||||
# inject the instance swe entry
|
||||
runtime.copy_to(
|
||||
str(os.path.join(script_dir, 'scripts/setup/instance_swe_entry.sh')),
|
||||
'/swe_util/',
|
||||
)
|
||||
action = CmdRunAction(command='cat ~/.bashrc')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(obs.exit_code == 0, f'Failed to cat ~/.bashrc: {str(obs)}')
|
||||
|
||||
action = CmdRunAction(command='cat ~/.bashrc')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(obs.exit_code == 0, f'Failed to cat ~/.bashrc: {str(obs)}')
|
||||
action = CmdRunAction(command='source ~/.bashrc')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
if isinstance(obs, ErrorObservation):
|
||||
logger.error(f'Failed to source ~/.bashrc: {str(obs)}')
|
||||
assert_and_raise(obs.exit_code == 0, f'Failed to source ~/.bashrc: {str(obs)}')
|
||||
|
||||
action = CmdRunAction(command='source ~/.bashrc')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
if isinstance(obs, ErrorObservation):
|
||||
logger.error(f'Failed to source ~/.bashrc: {str(obs)}')
|
||||
assert_and_raise(obs.exit_code == 0, f'Failed to source ~/.bashrc: {str(obs)}')
|
||||
|
||||
action = CmdRunAction(command='source /swe_util/instance_swe_entry.sh')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0,
|
||||
f'Failed to source /swe_util/instance_swe_entry.sh: {str(obs)}',
|
||||
)
|
||||
action = CmdRunAction(command='source /swe_util/instance_swe_entry.sh')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0,
|
||||
f'Failed to source /swe_util/instance_swe_entry.sh: {str(obs)}',
|
||||
)
|
||||
else:
|
||||
action = CmdRunAction(command='source /swe_util/swe_entry.sh')
|
||||
action.set_hard_timeout(1800)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0,
|
||||
f'Failed to source /swe_util/swe_entry.sh: {str(obs)}',
|
||||
)
|
||||
|
||||
action = CmdRunAction(command=f'cd /workspace/{workspace_dir_name}')
|
||||
action.set_hard_timeout(600)
|
||||
@@ -385,32 +355,6 @@ def complete_runtime(
|
||||
f'Failed to git config --global core.pager "": {str(obs)}',
|
||||
)
|
||||
|
||||
# First check for any git repositories in subdirectories
|
||||
action = CmdRunAction(command='find . -type d -name .git -not -path "./.git"')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
isinstance(obs, CmdOutputObservation) and obs.exit_code == 0,
|
||||
f'Failed to find git repositories: {str(obs)}',
|
||||
)
|
||||
|
||||
git_dirs = [p for p in obs.content.strip().split('\n') if p]
|
||||
if git_dirs:
|
||||
# Remove all .git directories in subdirectories
|
||||
for git_dir in git_dirs:
|
||||
action = CmdRunAction(command=f'rm -rf "{git_dir}"')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
isinstance(obs, CmdOutputObservation) and obs.exit_code == 0,
|
||||
f'Failed to remove git directory {git_dir}: {str(obs)}',
|
||||
)
|
||||
|
||||
# add all files
|
||||
action = CmdRunAction(command='git add -A')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
@@ -477,13 +421,6 @@ def process_instance(
|
||||
logger.warning(
|
||||
f'This is the {runtime_failure_count + 1}th attempt for instance {instance.instance_id}, setting resource factor to {config.sandbox.remote_runtime_resource_factor}'
|
||||
)
|
||||
|
||||
metadata = copy.deepcopy(metadata)
|
||||
metadata.details['runtime_failure_count'] = runtime_failure_count
|
||||
metadata.details['remote_runtime_resource_factor'] = (
|
||||
config.sandbox.remote_runtime_resource_factor
|
||||
)
|
||||
|
||||
runtime = create_runtime(config)
|
||||
call_async_from_sync(runtime.connect)
|
||||
|
||||
@@ -592,22 +529,6 @@ if __name__ == '__main__':
|
||||
logger.info(
|
||||
f'Loaded dataset {args.dataset} with split {args.split}: {len(swe_bench_tests)} tasks'
|
||||
)
|
||||
if 'SWE-Gym' in args.dataset:
|
||||
with open(
|
||||
os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
'split',
|
||||
'swegym_verified_instances.json',
|
||||
),
|
||||
'r',
|
||||
) as f:
|
||||
swegym_verified_instances = json.load(f)
|
||||
swe_bench_tests = swe_bench_tests[
|
||||
swe_bench_tests['instance_id'].isin(swegym_verified_instances)
|
||||
]
|
||||
logger.info(
|
||||
f'{len(swe_bench_tests)} tasks left after filtering for SWE-Gym verified instances'
|
||||
)
|
||||
|
||||
llm_config = None
|
||||
if args.llm_config:
|
||||
@@ -651,6 +572,6 @@ if __name__ == '__main__':
|
||||
output_file,
|
||||
args.eval_num_workers,
|
||||
process_instance,
|
||||
timeout_seconds=8 * 60 * 60, # 8 hour PER instance should be more than enough
|
||||
timeout_seconds=120 * 60, # 2 hour PER instance should be more than enough
|
||||
max_retries=5,
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,300 +1,336 @@
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-12907:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14182:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14365:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14995:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-6938:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-7746:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-10914:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-10924:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11001:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11019:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11039:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11049:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11099:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11133:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11179:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11283:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11422:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11564:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11583:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11620:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11630:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11742:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11797:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11815:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11848:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11905:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11910:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11964:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11999:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12113:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12125:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12184:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12284:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12286:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12308:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12453:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12470:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12497:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12589:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12700:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12708:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12747:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12856:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12908:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12915:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12983:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13028:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13033:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13158:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13220:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13230:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13265:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13315:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13321:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13401:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13447:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13448:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13551:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13590:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13658:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13660:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13710:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13757:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13768:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13925:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13933:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13964:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14016:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14017:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14155:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14238:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14382:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14411:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14534:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14580:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14608:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14667:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14672:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14730:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14752:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14787:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14855:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14915:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14997:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14999:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15061:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15202:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15213:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15252:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15320:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15347:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15388:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15400:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15498:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15695:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15738:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15781:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15789:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15790:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15814:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15819:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15851:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15902:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15996:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16041:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16046:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16139:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16229:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16255:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16379:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16400:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16408:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16527:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16595:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16816:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16820:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16873:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16910:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-17051:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-17087:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-18869:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-22711:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-22835:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23299:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23314:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23476:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23562:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23563:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23913:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23964:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23987:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24149:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24265:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24334:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24970:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25079:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25311:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25332:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25433:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25442:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25498:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26011:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26020:latest
|
||||
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-2848:latest
|
||||
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-3010:latest
|
||||
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-3190:latest
|
||||
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-3407:latest
|
||||
swebench/sweb.eval.x86_64.pallets_1776_flask-4045:latest
|
||||
swebench/sweb.eval.x86_64.pallets_1776_flask-4992:latest
|
||||
swebench/sweb.eval.x86_64.pallets_1776_flask-5063:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-1963:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-2148:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-2317:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-2674:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-3362:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-863:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-3364:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-4094:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-4248:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-4493:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-5131:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-5859:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-6506:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7080:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7114:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7228:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7993:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-11143:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-11148:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5103:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5221:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5227:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5413:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5495:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5692:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-6116:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7168:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7220:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7373:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7432:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7490:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-8365:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-8906:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-9359:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10297:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10508:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10949:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-11040:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-11281:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-12471:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13142:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13241:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13439:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13496:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13497:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13584:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13779:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14087:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14092:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14894:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14983:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-15512:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-15535:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25500:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25570:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25638:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25747:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10325:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10451:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-11445:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7686:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7738:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7975:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8273:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8282:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8435:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8474:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8506:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8595:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8627:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8713:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8721:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8801:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-11400:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-11870:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-11897:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-12171:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-12236:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-12419:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-12454:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-12481:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13031:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13043:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13146:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13177:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13437:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13471:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13480:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13647:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13773:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13895:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13915:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13971:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-14024:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-14308:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-14317:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-14396:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-14774:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-14817:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15011:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15308:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15345:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15346:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15609:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15678:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-16106:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-16281:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-16503:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-16792:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-16988:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-17022:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-17139:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-17630:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-17655:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18057:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18087:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18189:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18199:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18532:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18621:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18698:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18835:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-19007:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-19254:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-19487:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20049:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20154:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20212:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20322:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20442:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20590:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20639:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21055:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21171:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21379:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21612:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21614:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21627:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21847:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-22005:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-22714:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-22840:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-23117:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-23191:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-23262:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-24066:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-24102:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-24152:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-24213:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-24909:latest
|
||||
sweb.base.x86_64:latest
|
||||
sweb.env.x86_64.088a7e628bda9770f9757b:latest
|
||||
sweb.env.x86_64.0d80c7dec81ee2f2f513e2:latest
|
||||
sweb.env.x86_64.0f99bce2750f3109957bec:latest
|
||||
sweb.env.x86_64.1b3b218535da0abf4469cb:latest
|
||||
sweb.env.x86_64.1c1a6945f732f9391228c5:latest
|
||||
sweb.env.x86_64.1f92e6d7cef88badc4f744:latest
|
||||
sweb.env.x86_64.27dd9791e13f5c857a09f9:latest
|
||||
sweb.env.x86_64.297af196949a2a635bce66:latest
|
||||
sweb.env.x86_64.2baaea72acc974f6c02079:latest
|
||||
sweb.env.x86_64.2e50125951bc69cddd7421:latest
|
||||
sweb.env.x86_64.2f217c8b4490bfa0e2ba14:latest
|
||||
sweb.env.x86_64.31244378a92e3bcce809ac:latest
|
||||
sweb.env.x86_64.428468730904ff6b4232aa:latest
|
||||
sweb.env.x86_64.5d1fda9d55d65d8a4e5bdb:latest
|
||||
sweb.env.x86_64.6b007979cf533f0f3016e8:latest
|
||||
sweb.env.x86_64.7037e8c448a4b8ebfe9b13:latest
|
||||
sweb.env.x86_64.71498c7426dbf05599642f:latest
|
||||
sweb.env.x86_64.756beac07713d7e8dc1129:latest
|
||||
sweb.env.x86_64.78278ae2cf880e395f1337:latest
|
||||
sweb.env.x86_64.8f1f7b974f0c57c7aeba39:latest
|
||||
sweb.env.x86_64.934a137824256b612e9dc5:latest
|
||||
sweb.env.x86_64.a0efca7a0fe6719dbf65c2:latest
|
||||
sweb.env.x86_64.a18371b03f944585b4f08c:latest
|
||||
sweb.env.x86_64.a33dddf55cdff5d8e23374:latest
|
||||
sweb.env.x86_64.aa92880033da20ca313928:latest
|
||||
sweb.env.x86_64.b649f0ff62fad147f7f073:latest
|
||||
sweb.env.x86_64.b7ce4be3b3c35f68c61248:latest
|
||||
sweb.env.x86_64.c70909fdac4897d1c685df:latest
|
||||
sweb.env.x86_64.c795f4b88616b8462021ed:latest
|
||||
sweb.env.x86_64.cc47cc71483942d0c3a15e:latest
|
||||
sweb.env.x86_64.dc5ff4c0e3fe8db5afc4da:latest
|
||||
sweb.env.x86_64.e3afd7f04b325a4de4982d:latest
|
||||
sweb.env.x86_64.e5bb89bf78258a7d14c34b:latest
|
||||
sweb.env.x86_64.e83e37f52c09532c62acfb:latest
|
||||
sweb.env.x86_64.efa6065ed5bf204410fd53:latest
|
||||
sweb.eval.x86_64.astropy_s_astropy-12907:latest
|
||||
sweb.eval.x86_64.astropy_s_astropy-14182:latest
|
||||
sweb.eval.x86_64.astropy_s_astropy-14365:latest
|
||||
sweb.eval.x86_64.astropy_s_astropy-14995:latest
|
||||
sweb.eval.x86_64.astropy_s_astropy-6938:latest
|
||||
sweb.eval.x86_64.astropy_s_astropy-7746:latest
|
||||
sweb.eval.x86_64.django_s_django-10914:latest
|
||||
sweb.eval.x86_64.django_s_django-10924:latest
|
||||
sweb.eval.x86_64.django_s_django-11001:latest
|
||||
sweb.eval.x86_64.django_s_django-11019:latest
|
||||
sweb.eval.x86_64.django_s_django-11039:latest
|
||||
sweb.eval.x86_64.django_s_django-11049:latest
|
||||
sweb.eval.x86_64.django_s_django-11099:latest
|
||||
sweb.eval.x86_64.django_s_django-11133:latest
|
||||
sweb.eval.x86_64.django_s_django-11179:latest
|
||||
sweb.eval.x86_64.django_s_django-11283:latest
|
||||
sweb.eval.x86_64.django_s_django-11422:latest
|
||||
sweb.eval.x86_64.django_s_django-11564:latest
|
||||
sweb.eval.x86_64.django_s_django-11583:latest
|
||||
sweb.eval.x86_64.django_s_django-11620:latest
|
||||
sweb.eval.x86_64.django_s_django-11630:latest
|
||||
sweb.eval.x86_64.django_s_django-11742:latest
|
||||
sweb.eval.x86_64.django_s_django-11797:latest
|
||||
sweb.eval.x86_64.django_s_django-11815:latest
|
||||
sweb.eval.x86_64.django_s_django-11848:latest
|
||||
sweb.eval.x86_64.django_s_django-11905:latest
|
||||
sweb.eval.x86_64.django_s_django-11910:latest
|
||||
sweb.eval.x86_64.django_s_django-11964:latest
|
||||
sweb.eval.x86_64.django_s_django-11999:latest
|
||||
sweb.eval.x86_64.django_s_django-12113:latest
|
||||
sweb.eval.x86_64.django_s_django-12125:latest
|
||||
sweb.eval.x86_64.django_s_django-12184:latest
|
||||
sweb.eval.x86_64.django_s_django-12284:latest
|
||||
sweb.eval.x86_64.django_s_django-12286:latest
|
||||
sweb.eval.x86_64.django_s_django-12308:latest
|
||||
sweb.eval.x86_64.django_s_django-12453:latest
|
||||
sweb.eval.x86_64.django_s_django-12470:latest
|
||||
sweb.eval.x86_64.django_s_django-12497:latest
|
||||
sweb.eval.x86_64.django_s_django-12589:latest
|
||||
sweb.eval.x86_64.django_s_django-12700:latest
|
||||
sweb.eval.x86_64.django_s_django-12708:latest
|
||||
sweb.eval.x86_64.django_s_django-12747:latest
|
||||
sweb.eval.x86_64.django_s_django-12856:latest
|
||||
sweb.eval.x86_64.django_s_django-12908:latest
|
||||
sweb.eval.x86_64.django_s_django-12915:latest
|
||||
sweb.eval.x86_64.django_s_django-12983:latest
|
||||
sweb.eval.x86_64.django_s_django-13028:latest
|
||||
sweb.eval.x86_64.django_s_django-13033:latest
|
||||
sweb.eval.x86_64.django_s_django-13158:latest
|
||||
sweb.eval.x86_64.django_s_django-13220:latest
|
||||
sweb.eval.x86_64.django_s_django-13230:latest
|
||||
sweb.eval.x86_64.django_s_django-13265:latest
|
||||
sweb.eval.x86_64.django_s_django-13315:latest
|
||||
sweb.eval.x86_64.django_s_django-13321:latest
|
||||
sweb.eval.x86_64.django_s_django-13401:latest
|
||||
sweb.eval.x86_64.django_s_django-13447:latest
|
||||
sweb.eval.x86_64.django_s_django-13448:latest
|
||||
sweb.eval.x86_64.django_s_django-13551:latest
|
||||
sweb.eval.x86_64.django_s_django-13590:latest
|
||||
sweb.eval.x86_64.django_s_django-13658:latest
|
||||
sweb.eval.x86_64.django_s_django-13660:latest
|
||||
sweb.eval.x86_64.django_s_django-13710:latest
|
||||
sweb.eval.x86_64.django_s_django-13757:latest
|
||||
sweb.eval.x86_64.django_s_django-13768:latest
|
||||
sweb.eval.x86_64.django_s_django-13925:latest
|
||||
sweb.eval.x86_64.django_s_django-13933:latest
|
||||
sweb.eval.x86_64.django_s_django-13964:latest
|
||||
sweb.eval.x86_64.django_s_django-14016:latest
|
||||
sweb.eval.x86_64.django_s_django-14017:latest
|
||||
sweb.eval.x86_64.django_s_django-14155:latest
|
||||
sweb.eval.x86_64.django_s_django-14238:latest
|
||||
sweb.eval.x86_64.django_s_django-14382:latest
|
||||
sweb.eval.x86_64.django_s_django-14411:latest
|
||||
sweb.eval.x86_64.django_s_django-14534:latest
|
||||
sweb.eval.x86_64.django_s_django-14580:latest
|
||||
sweb.eval.x86_64.django_s_django-14608:latest
|
||||
sweb.eval.x86_64.django_s_django-14667:latest
|
||||
sweb.eval.x86_64.django_s_django-14672:latest
|
||||
sweb.eval.x86_64.django_s_django-14730:latest
|
||||
sweb.eval.x86_64.django_s_django-14752:latest
|
||||
sweb.eval.x86_64.django_s_django-14787:latest
|
||||
sweb.eval.x86_64.django_s_django-14855:latest
|
||||
sweb.eval.x86_64.django_s_django-14915:latest
|
||||
sweb.eval.x86_64.django_s_django-14997:latest
|
||||
sweb.eval.x86_64.django_s_django-14999:latest
|
||||
sweb.eval.x86_64.django_s_django-15061:latest
|
||||
sweb.eval.x86_64.django_s_django-15202:latest
|
||||
sweb.eval.x86_64.django_s_django-15213:latest
|
||||
sweb.eval.x86_64.django_s_django-15252:latest
|
||||
sweb.eval.x86_64.django_s_django-15320:latest
|
||||
sweb.eval.x86_64.django_s_django-15347:latest
|
||||
sweb.eval.x86_64.django_s_django-15388:latest
|
||||
sweb.eval.x86_64.django_s_django-15400:latest
|
||||
sweb.eval.x86_64.django_s_django-15498:latest
|
||||
sweb.eval.x86_64.django_s_django-15695:latest
|
||||
sweb.eval.x86_64.django_s_django-15738:latest
|
||||
sweb.eval.x86_64.django_s_django-15781:latest
|
||||
sweb.eval.x86_64.django_s_django-15789:latest
|
||||
sweb.eval.x86_64.django_s_django-15790:latest
|
||||
sweb.eval.x86_64.django_s_django-15814:latest
|
||||
sweb.eval.x86_64.django_s_django-15819:latest
|
||||
sweb.eval.x86_64.django_s_django-15851:latest
|
||||
sweb.eval.x86_64.django_s_django-15902:latest
|
||||
sweb.eval.x86_64.django_s_django-15996:latest
|
||||
sweb.eval.x86_64.django_s_django-16041:latest
|
||||
sweb.eval.x86_64.django_s_django-16046:latest
|
||||
sweb.eval.x86_64.django_s_django-16139:latest
|
||||
sweb.eval.x86_64.django_s_django-16229:latest
|
||||
sweb.eval.x86_64.django_s_django-16255:latest
|
||||
sweb.eval.x86_64.django_s_django-16379:latest
|
||||
sweb.eval.x86_64.django_s_django-16400:latest
|
||||
sweb.eval.x86_64.django_s_django-16408:latest
|
||||
sweb.eval.x86_64.django_s_django-16527:latest
|
||||
sweb.eval.x86_64.django_s_django-16595:latest
|
||||
sweb.eval.x86_64.django_s_django-16816:latest
|
||||
sweb.eval.x86_64.django_s_django-16820:latest
|
||||
sweb.eval.x86_64.django_s_django-16873:latest
|
||||
sweb.eval.x86_64.django_s_django-16910:latest
|
||||
sweb.eval.x86_64.django_s_django-17051:latest
|
||||
sweb.eval.x86_64.django_s_django-17087:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-18869:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-22711:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-22835:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-23299:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-23314:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-23476:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-23562:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-23563:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-23913:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-23964:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-23987:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-24149:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-24265:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-24334:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-24970:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-25079:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-25311:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-25332:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-25433:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-25442:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-25498:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-26011:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-26020:latest
|
||||
sweb.eval.x86_64.mwaskom_s_seaborn-2848:latest
|
||||
sweb.eval.x86_64.mwaskom_s_seaborn-3010:latest
|
||||
sweb.eval.x86_64.mwaskom_s_seaborn-3190:latest
|
||||
sweb.eval.x86_64.mwaskom_s_seaborn-3407:latest
|
||||
sweb.eval.x86_64.pallets_s_flask-4045:latest
|
||||
sweb.eval.x86_64.pallets_s_flask-4992:latest
|
||||
sweb.eval.x86_64.pallets_s_flask-5063:latest
|
||||
sweb.eval.x86_64.psf_s_requests-1963:latest
|
||||
sweb.eval.x86_64.psf_s_requests-2148:latest
|
||||
sweb.eval.x86_64.psf_s_requests-2317:latest
|
||||
sweb.eval.x86_64.psf_s_requests-2674:latest
|
||||
sweb.eval.x86_64.psf_s_requests-3362:latest
|
||||
sweb.eval.x86_64.psf_s_requests-863:latest
|
||||
sweb.eval.x86_64.pydata_s_xarray-3364:latest
|
||||
sweb.eval.x86_64.pydata_s_xarray-4094:latest
|
||||
sweb.eval.x86_64.pydata_s_xarray-4248:latest
|
||||
sweb.eval.x86_64.pydata_s_xarray-4493:latest
|
||||
sweb.eval.x86_64.pydata_s_xarray-5131:latest
|
||||
sweb.eval.x86_64.pylint-dev_s_pylint-5859:latest
|
||||
sweb.eval.x86_64.pylint-dev_s_pylint-6506:latest
|
||||
sweb.eval.x86_64.pylint-dev_s_pylint-7080:latest
|
||||
sweb.eval.x86_64.pylint-dev_s_pylint-7114:latest
|
||||
sweb.eval.x86_64.pylint-dev_s_pylint-7228:latest
|
||||
sweb.eval.x86_64.pylint-dev_s_pylint-7993:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-11143:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-11148:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-5103:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-5221:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-5227:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-5413:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-5495:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-5692:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-6116:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-7168:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-7220:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-7373:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-7432:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-7490:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-8365:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-8906:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-9359:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-10297:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-10508:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-10949:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-11040:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-11281:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-12471:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13142:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13241:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13439:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13496:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13497:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13584:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13779:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14087:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14092:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14894:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14983:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-15512:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-15535:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25500:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25570:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25638:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25747:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-10325:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-10451:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-11445:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-7686:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-7738:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-7975:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-8273:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-8282:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-8435:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-8474:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-8506:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-8595:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-8627:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-8713:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-8721:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-8801:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-11400:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-11870:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-11897:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-12171:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-12236:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-12419:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-12454:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-12481:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13031:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13043:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13146:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13177:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13437:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13471:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13480:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13647:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13773:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13895:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13915:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13971:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-14024:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-14308:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-14317:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-14396:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-14774:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-14817:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-15011:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-15308:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-15345:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-15346:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-15609:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-15678:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-16106:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-16281:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-16503:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-16792:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-16988:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-17022:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-17139:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-17630:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-17655:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-18057:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-18087:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-18189:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-18199:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-18532:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-18621:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-18698:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-18835:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-19007:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-19254:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-19487:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-20049:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-20154:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-20212:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-20322:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-20442:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-20590:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-20639:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21055:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21171:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21379:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21612:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21614:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21627:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21847:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-22005:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-22714:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-22840:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-23117:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-23191:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-23262:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-24066:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-24102:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-24152:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-24213:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-24909:latest
|
||||
|
||||
@@ -1,500 +0,0 @@
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-12907:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-13033:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-13236:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-13398:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-13453:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-13579:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-13977:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14096:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14182:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14309:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14365:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14369:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14508:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14539:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14598:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-14995:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-7166:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-7336:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-7606:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-7671:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-8707:latest
|
||||
swebench/sweb.eval.x86_64.astropy_1776_astropy-8872:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-10097:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-10554:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-10880:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-10914:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-10973:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-10999:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11066:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11087:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11095:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11099:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11119:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11133:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11138:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11141:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11149:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11163:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11179:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11206:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11211:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11239:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11265:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11276:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11292:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11299:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11333:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11400:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11433:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11451:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11477:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11490:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11532:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11551:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11555:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11603:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11728:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11734:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11740:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11749:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11790:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11815:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11820:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11848:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11880:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11885:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11951:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11964:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-11999:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12039:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12050:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12125:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12143:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12155:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12193:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12209:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12262:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12273:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12276:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12304:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12308:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12325:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12406:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12419:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12663:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12708:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12713:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12741:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12754:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12774:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12858:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-12965:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13012:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13023:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13028:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13033:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13089:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13109:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13112:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13121:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13128:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13158:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13195:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13212:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13279:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13297:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13315:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13343:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13344:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13346:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13363:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13401:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13406:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13410:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13417:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13449:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13512:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13513:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13516:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13551:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13568:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13569:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13590:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13658:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13670:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13741:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13786:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13794:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13807:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13809:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13810:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13820:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13821:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13837:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13925:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13933:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-13964:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14007:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14011:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14017:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14034:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14053:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14089:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14122:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14140:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14155:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14170:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14238:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14311:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14315:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14349:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14351:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14373:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14376:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14404:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14434:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14493:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14500:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14534:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14539:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14559:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14580:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14608:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14631:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14672:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14725:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14752:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14765:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14771:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14787:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14792:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14855:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14915:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-14999:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15022:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15037:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15098:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15103:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15104:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15127:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15128:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15161:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15252:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15268:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15277:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15278:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15280:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15315:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15368:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15375:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15380:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15382:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15467:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15499:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15503:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15525:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15554:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15561:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15563:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15569:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15572:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15629:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15695:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15731:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15732:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15741:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15814:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15851:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15863:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15916:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15930:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15957:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15973:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-15987:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16032:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16082:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16100:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16116:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16136:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16139:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16145:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16255:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16256:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16263:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16315:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16333:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16429:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16454:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16485:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16493:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16502:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16527:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16560:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16569:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16595:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16612:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16631:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16642:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16661:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16662:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16667:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16801:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16819:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16877:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16899:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16901:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16938:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-16950:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-17029:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-17084:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-17087:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-7530:latest
|
||||
swebench/sweb.eval.x86_64.django_1776_django-9296:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-13989:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-14623:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-20488:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-20676:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-20826:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-20859:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-21568:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-22719:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-22865:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-22871:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23299:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23314:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23412:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-23476:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24026:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24149:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24177:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24570:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24627:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24637:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24870:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-24970:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25122:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25287:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25311:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25332:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25479:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25775:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-25960:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26113:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26208:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26291:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26342:latest
|
||||
swebench/sweb.eval.x86_64.matplotlib_1776_matplotlib-26466:latest
|
||||
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-3069:latest
|
||||
swebench/sweb.eval.x86_64.mwaskom_1776_seaborn-3187:latest
|
||||
swebench/sweb.eval.x86_64.pallets_1776_flask-5014:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-1142:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-1724:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-1766:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-1921:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-2317:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-2931:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-5414:latest
|
||||
swebench/sweb.eval.x86_64.psf_1776_requests-6028:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-2905:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-3095:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-3151:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-3305:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-3677:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-3993:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-4075:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-4094:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-4356:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-4629:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-4687:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-4695:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-4966:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-6461:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-6599:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-6721:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-6744:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-6938:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-6992:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-7229:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-7233:latest
|
||||
swebench/sweb.eval.x86_64.pydata_1776_xarray-7393:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-4551:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-4604:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-4661:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-4970:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-6386:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-6528:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-6903:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7080:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-7277:latest
|
||||
swebench/sweb.eval.x86_64.pylint-dev_1776_pylint-8898:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-10051:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-10081:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-10356:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5262:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5631:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5787:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5809:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-5840:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-6197:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-6202:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7205:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7236:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7324:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7432:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7490:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7521:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7571:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-7982:latest
|
||||
swebench/sweb.eval.x86_64.pytest-dev_1776_pytest-8399:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10297:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10844:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-10908:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-11310:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-11578:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-12585:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-12682:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-12973:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13124:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13135:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13142:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13328:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13439:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13496:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-13779:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14053:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14087:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14141:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14496:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14629:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14710:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14894:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-14983:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-15100:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25102:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25232:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25747:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25931:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-25973:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-26194:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-26323:latest
|
||||
swebench/sweb.eval.x86_64.scikit-learn_1776_scikit-learn-9288:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10323:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10435:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10449:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10466:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10614:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-10673:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-11445:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-11510:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7440:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7454:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7462:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7590:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7748:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7757:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7889:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7910:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-7985:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8035:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8056:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8120:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8265:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8269:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8459:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8475:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8548:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8551:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8593:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8595:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8621:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8638:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-8721:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9229:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9230:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9258:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9281:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9320:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9367:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9461:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9591:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9602:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9658:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9673:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9698:latest
|
||||
swebench/sweb.eval.x86_64.sphinx-doc_1776_sphinx-9711:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-11618:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-12096:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-12419:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-12481:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-12489:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13031:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13091:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13372:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13480:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13551:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13615:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13647:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13757:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13798:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13852:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13877:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13878:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-13974:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-14248:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-14531:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-14711:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-14976:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15017:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15345:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15349:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15599:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15809:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15875:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-15976:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-16450:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-16597:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-16766:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-16792:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-16886:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-17139:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-17318:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-17630:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-17655:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18189:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18199:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18211:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18698:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-18763:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-19040:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-19346:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-19495:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-19637:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-19783:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-19954:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20154:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20428:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20438:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20590:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20801:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-20916:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21379:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21596:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21612:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21847:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-21930:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-22080:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-22456:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-22714:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-22914:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-23262:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-23413:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-23534:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-23824:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-23950:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-24066:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-24213:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-24443:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-24539:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-24562:latest
|
||||
swebench/sweb.eval.x86_64.sympy_1776_sympy-24661:latest
|
||||
@@ -1,50 +0,0 @@
|
||||
"""Get official docker image names for SWE-bench instances."""
|
||||
|
||||
import argparse
|
||||
|
||||
from datasets import load_dataset
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--dataset', type=str, default='princeton-nlp/SWE-bench')
|
||||
parser.add_argument('--split', type=str, default='test')
|
||||
parser.add_argument('--output', type=str, default='swebench_images.txt')
|
||||
args = parser.parse_args()
|
||||
|
||||
SUPPORTED_DATASET = {
|
||||
'princeton-nlp/SWE-bench_Multimodal',
|
||||
'princeton-nlp/SWE-bench',
|
||||
'princeton-nlp/SWE-bench_Lite',
|
||||
'princeton-nlp/SWE-bench_Verified',
|
||||
}
|
||||
assert args.dataset in SUPPORTED_DATASET, f'Dataset {args.dataset} not supported'
|
||||
|
||||
|
||||
def swebench_instance_id_to_docker_image_name(instance_id: str) -> str:
|
||||
# swebench/sweb.eval.x86_64.django_1776_django-11333:v1
|
||||
repo, name = instance_id.split('__')
|
||||
return f'swebench/sweb.eval.x86_64.{repo}_1776_{name}:latest'
|
||||
|
||||
|
||||
def swebench_multimodal_instance_id_to_docker_image_name(instance_id: str) -> str:
|
||||
# swebench/sweb.mm.eval.x86_64.openlayers_1776_openlayers-12172
|
||||
repo, name = instance_id.split('__')
|
||||
return f'swebench/sweb.mm.eval.x86_64.{repo}_1776_{name}:latest'
|
||||
|
||||
|
||||
dataset = load_dataset(args.dataset, split=args.split)
|
||||
instance_ids = dataset['instance_id']
|
||||
|
||||
print(f'Loading {len(instance_ids)} instances from {args.dataset} split {args.split}')
|
||||
with open(args.output, 'w') as f:
|
||||
for instance_id in instance_ids:
|
||||
if args.dataset in [
|
||||
'princeton-nlp/SWE-bench',
|
||||
'princeton-nlp/SWE-bench_Lite',
|
||||
'princeton-nlp/SWE-bench_Verified',
|
||||
]:
|
||||
f.write(swebench_instance_id_to_docker_image_name(instance_id) + '\n')
|
||||
else:
|
||||
f.write(
|
||||
swebench_multimodal_instance_id_to_docker_image_name(instance_id) + '\n'
|
||||
)
|
||||
print(f'Saved {len(instance_ids)} images to {args.output}')
|
||||
@@ -1,36 +1,66 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
SET=$1
|
||||
# check set is in ["full", "lite", "verified"]
|
||||
if [ "$SET" != "full" ] && [ "$SET" != "lite" ] && [ "$SET" != "verified" ]; then
|
||||
echo "Error: argument 1 must be one of: full, lite, verified"
|
||||
LEVEL=$1
|
||||
# three levels:
|
||||
# - base, keyword "sweb.base"
|
||||
# - env, keyword "sweb.env"
|
||||
# - instance, keyword "sweb.eval"
|
||||
SET=$2
|
||||
|
||||
if [ -z "$LEVEL" ]; then
|
||||
echo "Usage: $0 <cache_level> <set>"
|
||||
echo "cache_level: base, env, or instance"
|
||||
echo "set: lite, full"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
input_file=evaluation/benchmarks/swe_bench/scripts/docker/all-swebench-${SET}-instance-images.txt
|
||||
echo "Downloading images based on ${input_file}"
|
||||
# Check if the file exists
|
||||
if [ ! -f "$input_file" ]; then
|
||||
echo "Error: File '$input_file' not found"
|
||||
exit 1
|
||||
if [ -z "$SET" ]; then
|
||||
echo "Usage: $0 <cache_level> <set>"
|
||||
echo "cache_level: base, env, or instance"
|
||||
echo "set: lite, full, default is lite"
|
||||
SET="lite"
|
||||
fi
|
||||
|
||||
# Get total number of images
|
||||
total_images=$(wc -l < "${input_file}")
|
||||
counter=0
|
||||
# Check if namespace is provided via argument $3, otherwise default to 'xingyaoww'
|
||||
NAMESPACE=${3:-xingyaoww}
|
||||
|
||||
echo "Starting to pull ${total_images} images"
|
||||
echo "Using namespace: $NAMESPACE"
|
||||
|
||||
# Read the file line by line and pull each image
|
||||
while IFS= read -r image; do
|
||||
# Skip empty lines or comments
|
||||
if [ -n "$image" ] && [[ ! "$image" =~ ^[[:space:]]*# ]]; then
|
||||
counter=$((counter + 1))
|
||||
echo "[${counter}/${total_images}] Pulling ${image}"
|
||||
docker pull "${image}"
|
||||
sleep 2
|
||||
fi
|
||||
done < "${input_file}"
|
||||
if [ "$SET" == "lite" ]; then
|
||||
IMAGE_FILE="$(dirname "$0")/all-swebench-lite-instance-images.txt"
|
||||
else
|
||||
IMAGE_FILE="$(dirname "$0")/all-swebench-full-instance-images.txt"
|
||||
fi
|
||||
|
||||
echo "Finished pulling all images"
|
||||
# Define a pattern based on the level
|
||||
case $LEVEL in
|
||||
base)
|
||||
PATTERN="sweb.base"
|
||||
;;
|
||||
env)
|
||||
PATTERN="sweb.base\|sweb.env"
|
||||
;;
|
||||
instance)
|
||||
PATTERN="sweb.base\|sweb.env\|sweb.eval"
|
||||
;;
|
||||
*)
|
||||
echo "Invalid cache level: $LEVEL"
|
||||
echo "Valid levels are: base, env, instance"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Pulling docker images for [$LEVEL] level"
|
||||
|
||||
echo "Pattern: $PATTERN"
|
||||
echo "Image file: $IMAGE_FILE"
|
||||
|
||||
# Read each line from the file, filter by pattern, and pull the docker image
|
||||
grep "$PATTERN" "$IMAGE_FILE" | while IFS= read -r image; do
|
||||
echo "Pulling $NAMESPACE/$image into $image"
|
||||
docker pull $NAMESPACE/$image
|
||||
# replace _s_ to __ in the image name
|
||||
renamed_image=$(echo "$image" | sed 's/_s_/__/g')
|
||||
docker tag $NAMESPACE/$image $renamed_image
|
||||
done
|
||||
|
||||
@@ -24,7 +24,7 @@ def load_completions(output_dir: str, instance_id: str):
|
||||
# create messages
|
||||
messages = result['messages']
|
||||
messages.append(result['response']['choices'][0]['message'])
|
||||
tools = result['kwargs'].get('tools', [])
|
||||
tools = result['kwargs']['tools']
|
||||
return {
|
||||
'messages': messages,
|
||||
'tools': tools,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import pandas as pd
|
||||
from termcolor import colored
|
||||
@@ -36,23 +35,6 @@ if args.only_x_instances:
|
||||
f'After removing instances not in X={args.input_file_1}: Y={df2.shape[0]} instances'
|
||||
)
|
||||
|
||||
|
||||
# Add summarization step for each input file
|
||||
def summarize_file(file_path):
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
summarize_script = os.path.join(script_dir, 'summarize_outputs.py')
|
||||
|
||||
print(f'\nSummary for {file_path}:')
|
||||
print('=' * 80)
|
||||
subprocess.run(['python', summarize_script, file_path], check=True)
|
||||
print('=' * 80)
|
||||
|
||||
|
||||
# Generate summaries
|
||||
summarize_file(args.input_file_1)
|
||||
summarize_file(args.input_file_2)
|
||||
|
||||
|
||||
# Get the intersection of the instance_ids
|
||||
df = pd.merge(df1, df2, on='instance_id', how='inner')
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ def load_completions(instance_id: str):
|
||||
# create messages
|
||||
messages = result['messages']
|
||||
messages.append(result['response']['choices'][0]['message'])
|
||||
tools = result['kwargs'].get('tools', None)
|
||||
tools = result['kwargs']['tools']
|
||||
return {
|
||||
'messages': messages,
|
||||
'tools': tools,
|
||||
@@ -248,22 +248,6 @@ def write_row_to_md_file(row, instance_id_to_test_result):
|
||||
|
||||
completions = load_completions(instance_id)
|
||||
|
||||
# report file
|
||||
global output_dir
|
||||
report_file = os.path.join(output_dir, 'eval_outputs', instance_id, 'report.json')
|
||||
if os.path.exists(report_file):
|
||||
with open(report_file, 'r') as f:
|
||||
report = json.load(f)
|
||||
else:
|
||||
report = None
|
||||
|
||||
test_output_file = os.path.join(
|
||||
output_dir, 'eval_outputs', instance_id, 'test_output.txt'
|
||||
)
|
||||
if test_output is None and os.path.exists(test_output_file):
|
||||
with open(test_output_file, 'r') as f:
|
||||
test_output = f.read()
|
||||
|
||||
with open(filepath, 'w') as f:
|
||||
f.write(f'# {instance_id} (resolved: {resolved})\n')
|
||||
|
||||
@@ -285,14 +269,8 @@ def write_row_to_md_file(row, instance_id_to_test_result):
|
||||
f.write('## Model Patch\n')
|
||||
f.write(f'{process_git_patch(model_patch)}\n')
|
||||
|
||||
if report is not None:
|
||||
f.write('## Report\n')
|
||||
f.write(json.dumps(report, indent=2))
|
||||
f.write('\n')
|
||||
|
||||
f.write('## Test Output\n')
|
||||
f.write(str(test_output))
|
||||
f.write('\n')
|
||||
|
||||
|
||||
instance_id_to_test_result = {}
|
||||
|
||||
@@ -9,7 +9,7 @@ parser.add_argument(
|
||||
'--dataset_name',
|
||||
type=str,
|
||||
help='Name of the dataset to download',
|
||||
default='princeton-nlp/SWE-bench_Verified',
|
||||
default='princeton-nlp/SWE-bench_Lite',
|
||||
)
|
||||
parser.add_argument('--split', type=str, help='Split to download', default='test')
|
||||
args = parser.parse_args()
|
||||
@@ -20,12 +20,7 @@ print(
|
||||
f'Downloading gold patches from {args.dataset_name} (split: {args.split}) to {output_filepath}'
|
||||
)
|
||||
patches = [
|
||||
{
|
||||
'instance_id': row['instance_id'],
|
||||
'model_patch': row['patch'],
|
||||
'model_name_or_path': 'gold',
|
||||
}
|
||||
for row in dataset
|
||||
{'instance_id': row['instance_id'], 'model_patch': row['patch']} for row in dataset
|
||||
]
|
||||
print(f'{len(patches)} gold patches loaded')
|
||||
pd.DataFrame(patches).to_json(output_filepath, lines=True, orient='records')
|
||||
|
||||
@@ -44,6 +44,7 @@ if os.path.exists(swebench_official_report_json):
|
||||
f"- resolved instances: {report['resolved_instances']}\n"
|
||||
f"- unresolved instances: {report['unresolved_instances']}\n"
|
||||
f"- error instances: {report['error_instances']}\n"
|
||||
f"- unstopped instances: {report['unstopped_instances']}\n"
|
||||
)
|
||||
|
||||
output_md += '\n## Resolved Instances\n'
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# NOTE: this script is for rolling out the SWE-Gym dataset for **TRAINING**
|
||||
# For more information, please refer to
|
||||
# 1. the Github Repo: https://github.com/SWE-Gym/SWE-Gym
|
||||
# 2. the paper: https://arxiv.org/abs/2412.21139
|
||||
|
||||
MODEL=$1 # eg your llm config name in config.toml (eg: "llm.claude-3-5-sonnet-20241022-t05")
|
||||
EXP_NAME=$2 # "train-t05"
|
||||
N_WORKERS=${3:-64}
|
||||
N_RUNS=${4:-1}
|
||||
|
||||
export EXP_NAME=$EXP_NAME
|
||||
# use 2x resources for rollout since some codebases are pretty resource-intensive
|
||||
export DEFAULT_RUNTIME_RESOURCE_FACTOR=2
|
||||
echo "MODEL: $MODEL"
|
||||
echo "EXP_NAME: $EXP_NAME"
|
||||
DATASET="SWE-Gym/SWE-Gym" # change this to the "/SWE-Gym-Lite" if you want to rollout the lite subset
|
||||
SPLIT="train"
|
||||
|
||||
if [ -z "$ALLHANDS_API_KEY" ]; then
|
||||
echo "ALLHANDS_API_KEY is not set. Will rollout and evaluate locally using Docker. WARNING: A large value of N_WORKERS will result in a large number of Docker containers being spun up and may crash your machine."
|
||||
export RUNTIME=docker
|
||||
else
|
||||
echo "ALLHANDS_API_KEY is set. Continuing rollout and evaluation with remote runtime..."
|
||||
export RUNTIME=remote
|
||||
export SANDBOX_REMOTE_RUNTIME_API_URL="https://runtime.eval.all-hands.dev"
|
||||
export EVAL_DOCKER_IMAGE_PREFIX="us-central1-docker.pkg.dev/evaluation-092424/swe-bench-images"
|
||||
fi
|
||||
|
||||
EVAL_LIMIT=3000
|
||||
MAX_ITER=100
|
||||
|
||||
|
||||
# ===== Run inference =====
|
||||
source "evaluation/utils/version_control.sh"
|
||||
get_openhands_version
|
||||
|
||||
echo "OPENHANDS_VERSION: $OPENHANDS_VERSION"
|
||||
echo "MODEL_CONFIG: $MODEL_CONFIG"
|
||||
echo "DATASET: $DATASET"
|
||||
echo "SPLIT: $SPLIT"
|
||||
|
||||
# Default to NOT use Hint
|
||||
export USE_INSTANCE_IMAGE=true
|
||||
export USE_HINT_TEXT=false
|
||||
export RUN_WITH_BROWSING=false
|
||||
echo "USE_HINT_TEXT: $USE_HINT_TEXT"
|
||||
EVAL_NOTE="$OPENHANDS_VERSION-no-hint-$EXP_NAME"
|
||||
|
||||
function run_eval() {
|
||||
local eval_note=$1
|
||||
COMMAND="poetry run python evaluation/benchmarks/swe_bench/run_infer.py \
|
||||
--agent-cls CodeActAgent \
|
||||
--llm-config $MODEL \
|
||||
--max-iterations $MAX_ITER \
|
||||
--eval-num-workers $N_WORKERS \
|
||||
--eval-note $eval_note \
|
||||
--dataset $DATASET \
|
||||
--split $SPLIT"
|
||||
|
||||
if [ -n "$EVAL_LIMIT" ]; then
|
||||
echo "EVAL_LIMIT: $EVAL_LIMIT"
|
||||
COMMAND="$COMMAND --eval-n-limit $EVAL_LIMIT"
|
||||
fi
|
||||
|
||||
# Run the command
|
||||
eval $COMMAND
|
||||
}
|
||||
|
||||
for run_idx in $(seq 1 $N_RUNS); do
|
||||
|
||||
while true; do
|
||||
echo "### Running inference... ###"
|
||||
unset SANDBOX_ENV_GITHUB_TOKEN # prevent the agent from using the github token to push
|
||||
current_eval_note="$EVAL_NOTE-run_$run_idx"
|
||||
echo "EVAL_NOTE: $current_eval_note"
|
||||
INFER_OUTPUT=$(run_eval $current_eval_note)
|
||||
INFER_STATUS=$? # Capture the exit status of run_infer.sh
|
||||
echo "INFER_STATUS: $INFER_STATUS"
|
||||
|
||||
echo "### Cleaning up remote runtime... ###"
|
||||
./evaluation/utils/scripts/cleanup_remote_runtime.sh
|
||||
|
||||
if [ $INFER_STATUS -eq 0 ]; then
|
||||
echo "### Inference completed successfully. ###"
|
||||
break
|
||||
else
|
||||
echo "### Inference failed with exit code $INFER_STATUS. Retrying... ###"
|
||||
fi
|
||||
done
|
||||
|
||||
# Extract the output directory using the special delimiters
|
||||
OUTPUT_FILE=$(echo "$INFER_OUTPUT" | grep -o '### OUTPUT FILE:.* ###' | sed 's/### OUTPUT FILE: \(.*\) ###/\1/')
|
||||
echo "Got OUTPUT_FILE: $OUTPUT_FILE"
|
||||
|
||||
while true; do
|
||||
echo "### Evaluating on $OUTPUT_FILE ... ###"
|
||||
COMMAND="poetry run python evaluation/benchmarks/swe_bench/eval_infer.py \
|
||||
--eval-num-workers $((N_WORKERS * 2)) \
|
||||
--input-file $OUTPUT_FILE \
|
||||
--dataset $DATASET \
|
||||
--split $SPLIT"
|
||||
|
||||
if [ -n "$EVAL_LIMIT" ]; then
|
||||
echo "EVAL_LIMIT: $EVAL_LIMIT"
|
||||
COMMAND="$COMMAND --eval-n-limit $EVAL_LIMIT"
|
||||
fi
|
||||
echo "Running command: $COMMAND"
|
||||
# Run the command
|
||||
eval $COMMAND
|
||||
EVAL_STATUS=$?
|
||||
if [ $EVAL_STATUS -eq 0 ]; then
|
||||
echo "### Evaluation completed successfully. ###"
|
||||
break
|
||||
else
|
||||
echo "### Evaluation failed with exit code $EVAL_STATUS. Retrying... ###"
|
||||
fi
|
||||
|
||||
./evaluation/utils/scripts/cleanup_remote_runtime.sh
|
||||
done
|
||||
|
||||
# update the output with evaluation results
|
||||
echo "### Updating the output with evaluation results... ###"
|
||||
poetry run python evaluation/benchmarks/swe_bench/scripts/eval/update_output_with_eval.py $OUTPUT_FILE
|
||||
|
||||
echo "### Combining the final completions... ###"
|
||||
poetry run python evaluation/benchmarks/swe_bench/scripts/eval/combine_final_completions.py $OUTPUT_FILE
|
||||
|
||||
echo "### DONE for run $run_idx! ###"
|
||||
echo "You can find the final output at $(dirname $OUTPUT_FILE)/$FINAL_OUTPUT_FILE"
|
||||
done
|
||||
@@ -29,6 +29,11 @@ if [ -z "$MAX_ITER" ]; then
|
||||
MAX_ITER=100
|
||||
fi
|
||||
|
||||
if [ -z "$USE_INSTANCE_IMAGE" ]; then
|
||||
echo "USE_INSTANCE_IMAGE not specified, use default true"
|
||||
USE_INSTANCE_IMAGE=true
|
||||
fi
|
||||
|
||||
if [ -z "$RUN_WITH_BROWSING" ]; then
|
||||
echo "RUN_WITH_BROWSING not specified, use default false"
|
||||
RUN_WITH_BROWSING=false
|
||||
@@ -45,6 +50,8 @@ if [ -z "$SPLIT" ]; then
|
||||
SPLIT="test"
|
||||
fi
|
||||
|
||||
export USE_INSTANCE_IMAGE=$USE_INSTANCE_IMAGE
|
||||
echo "USE_INSTANCE_IMAGE: $USE_INSTANCE_IMAGE"
|
||||
export RUN_WITH_BROWSING=$RUN_WITH_BROWSING
|
||||
echo "RUN_WITH_BROWSING: $RUN_WITH_BROWSING"
|
||||
|
||||
|
||||
@@ -1,287 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"\n",
|
||||
"import pandas as pd\n",
|
||||
"from tqdm import tqdm\n",
|
||||
"\n",
|
||||
"tqdm.pandas()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# 1. Load raw data and convert to training data"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import gzip\n",
|
||||
"import json\n",
|
||||
"\n",
|
||||
"from tqdm import tqdm\n",
|
||||
"\n",
|
||||
"FILE_PATHS = [\n",
|
||||
" 'YOURPATH-no-hint-train-t05-run_1/output.with_completions.jsonl.gz',\n",
|
||||
" 'YOURPATH-no-hint-train-t05-run_2/output.with_completions.jsonl.gz',\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# More memory efficient for large files\n",
|
||||
"# Initialize lists to store the data\n",
|
||||
"data = []\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Read file line by line\n",
|
||||
"for FILE_PATH in FILE_PATHS:\n",
|
||||
" with gzip.open(FILE_PATH, 'rb') as f: # Use 'rb' for gzipped files\n",
|
||||
" for i, line in tqdm(\n",
|
||||
" enumerate(f), desc=f\"Processing {FILE_PATH.split('/')[-1]}\"\n",
|
||||
" ):\n",
|
||||
" # Parse only the fields we need\n",
|
||||
" raw_data = json.loads(line)\n",
|
||||
" data.append(\n",
|
||||
" {\n",
|
||||
" 'resolved': raw_data['report']['resolved'],\n",
|
||||
" 'messages': raw_data['raw_completions']['messages']\n",
|
||||
" if raw_data['raw_completions'] is not None\n",
|
||||
" else None,\n",
|
||||
" 'git_patch': raw_data['test_result'].get('git_patch', ''),\n",
|
||||
" 'tools': raw_data['raw_completions']['tools']\n",
|
||||
" if raw_data['raw_completions'] is not None\n",
|
||||
" and 'tools' in raw_data['raw_completions']\n",
|
||||
" else None,\n",
|
||||
" }\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"# Convert to DataFrame after collecting all data\n",
|
||||
"df = pd.DataFrame(data)\n",
|
||||
"print(f'#total amount of data={len(df)}')\n",
|
||||
"df = df[~df['messages'].isna()]\n",
|
||||
"print(f'#total amount of data after removing nan={len(df)}')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Filter"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def _contains_multiple_tool_calls(messages: list[dict]) -> bool:\n",
|
||||
" return any(\n",
|
||||
" message.get('tool_calls') and len(message['tool_calls']) > 1\n",
|
||||
" for message in messages\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"df['contains_multiple_tool_calls'] = df['messages'].apply(_contains_multiple_tool_calls)\n",
|
||||
"display(df.groupby(['contains_multiple_tool_calls'])['resolved'].sum())"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import copy\n",
|
||||
"\n",
|
||||
"# Convert function calling messages to non-function calling messages\n",
|
||||
"from openhands.llm.fn_call_converter import (\n",
|
||||
" FunctionCallConversionError,\n",
|
||||
" convert_fncall_messages_to_non_fncall_messages,\n",
|
||||
" convert_from_multiple_tool_calls_to_single_tool_call_messages,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"total_failed = 0\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def _convert_messages(messages: list[dict], tools: list[dict]) -> list[dict]:\n",
|
||||
" global total_failed\n",
|
||||
" message_copy = copy.deepcopy(messages)\n",
|
||||
" for message in message_copy:\n",
|
||||
" if message['content'] is None:\n",
|
||||
" message['content'] = ''\n",
|
||||
" try:\n",
|
||||
" return convert_fncall_messages_to_non_fncall_messages(\n",
|
||||
" message_copy, tools, add_in_context_learning_example=False\n",
|
||||
" )\n",
|
||||
" except FunctionCallConversionError:\n",
|
||||
" total_failed += 1\n",
|
||||
" # print(f'Failed to convert messages: {messages}\\nTools: {tools}')\n",
|
||||
" # traceback.print_exc()\n",
|
||||
" return None\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"df['converted_messages'] = df.apply(\n",
|
||||
" lambda row: convert_from_multiple_tool_calls_to_single_tool_call_messages(\n",
|
||||
" row['messages'], ignore_final_tool_result=True\n",
|
||||
" ),\n",
|
||||
" axis=1,\n",
|
||||
")\n",
|
||||
"df['nonfncall_messages'] = df.apply(\n",
|
||||
" lambda row: _convert_messages(row['converted_messages'], row['tools']), axis=1\n",
|
||||
")\n",
|
||||
"print('total nan', df['nonfncall_messages'].isna().sum())\n",
|
||||
"df = df[~df['nonfncall_messages'].isna()]\n",
|
||||
"print(f'Total failed: {total_failed}')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Tokenization"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from pandarallel import pandarallel\n",
|
||||
"from transformers import AutoTokenizer\n",
|
||||
"\n",
|
||||
"os.environ['TOKENIZERS_PARALLELISM'] = 'false'\n",
|
||||
"pandarallel.initialize(progress_bar=True, verbose=1, nb_workers=16)\n",
|
||||
"tokenizer = AutoTokenizer.from_pretrained('Qwen/Qwen2.5-7B-Instruct')\n",
|
||||
"df['n_tokens'] = df['rm_conv'].parallel_apply(\n",
|
||||
" lambda x: len(tokenizer.apply_chat_template(x))\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"print(f'BEFORE: #total={len(df)}')\n",
|
||||
"df_selected = df[df['n_tokens'] < 131072]\n",
|
||||
"print(f'AFTER(truncated to 128k): #total={len(df_selected)}')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_selected['n_tokens'].describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# ecdf of n_tokens\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"import seaborn as sns\n",
|
||||
"\n",
|
||||
"display(df.groupby(['resolved'])['n_tokens'].describe())\n",
|
||||
"sns.ecdfplot(x='n_tokens', data=df, hue='resolved')\n",
|
||||
"plt.show()\n",
|
||||
"\n",
|
||||
"print(f'#total={len(df)}')\n",
|
||||
"df_selected = df[df['n_tokens'] < 131072]\n",
|
||||
"print(f'#selected={len(df_selected)}')\n",
|
||||
"display(df_selected.groupby(['resolved'])['n_tokens'].describe())\n",
|
||||
"sns.ecdfplot(x='n_tokens', data=df_selected, hue='resolved')\n",
|
||||
"plt.show()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_selected[~df_selected['resolved']]['n_tokens'].describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_selected['resolved'].value_counts()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_selected.groupby(['resolved'])['n_tokens'].describe()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Save Resolved Messages for SFT"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"df_selected[df_selected['resolved']][['nonfncall_messages']].rename(\n",
|
||||
" columns={'nonfncall_messages': 'messages'}\n",
|
||||
").to_json(\n",
|
||||
" os.path.join(\n",
|
||||
" 'YOUR_OUTPUT_FOLDER',\n",
|
||||
" f'policy_traj_128k_swegym_{df_selected[\"resolved\"].value_counts()[True]}i.jsonl',\n",
|
||||
" ),\n",
|
||||
" lines=True,\n",
|
||||
" orient='records',\n",
|
||||
")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "openhands-ai-CPy6G0pU-py3.12",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.8"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +0,0 @@
|
||||
codamosa_ids = ['pydata__xarray-4750-16496', 'pydata__xarray-3239-16458', 'pydata__xarray-4966-16515', 'pydata__xarray-3302-16459', 'pydata__xarray-5126-16518', 'pydata__xarray-4994-16516', 'pydata__xarray-3905-16478', 'pydata__xarray-4182-16484', 'pydata__xarray-5131-16520', 'pydata__xarray-5662-16532', 'pydata__xarray-3364-16461', 'pydata__xarray-5731-16534', 'pydata__xarray-3239-16457', 'pydata__xarray-7203-16577', 'pydata__xarray-3156-16454', 'pydata__xarray-5126-16519', 'pydata__xarray-5365-16529', 'pydata__xarray-4629-16492', 'pydata__xarray-4248-16486', 'pydata__xarray-4339-16487', 'pydata__xarray-3151-16453', 'pydata__xarray-3114-16452', 'pydata__xarray-5033-16517', 'pydata__xarray-4802-16505', 'pydata__xarray-5455-16530', 'pydata__xarray-6400-16539', 'pydata__xarray-3239-16456', 'pydata__xarray-4419-16488']
|
||||
|
||||
pynguin_ids = ['pydata__xarray-6548-16541', 'pydata__xarray-7003-16557', 'pydata__xarray-3114-16452', 'pydata__xarray-4339-16487', 'pydata__xarray-6889-16549', 'pydata__xarray-3239-16458', 'pydata__xarray-3364-16461', 'pydata__xarray-3239-16457', 'pydata__xarray-5365-16529', 'pydata__xarray-5131-16520', 'pydata__xarray-7229-16578', 'pydata__xarray-6461-16540', 'pydata__xarray-4419-16488', 'pydata__xarray-7147-16571', 'pydata__xarray-3151-16453', 'pydata__xarray-4966-16515', 'pydata__xarray-4629-16492', 'pydata__xarray-3239-16456', 'pydata__xarray-7400-16582', 'pydata__xarray-4994-16516', 'pydata__xarray-3302-16459', 'pydata__xarray-6601-16544', 'pydata__xarray-6882-16548', 'pydata__xarray-6135-16535', 'pydata__xarray-7393-16581', 'pydata__xarray-5731-16534', 'pydata__xarray-7203-16577']
|
||||
|
||||
ids = ['pydata__xarray-3114-16452', 'pydata__xarray-3151-16453', 'pydata__xarray-3156-16454', 'pydata__xarray-3239-16456', 'pydata__xarray-3239-16457', 'pydata__xarray-3239-16458', 'pydata__xarray-3302-16459', 'pydata__xarray-3364-16461', 'pydata__xarray-3677-16471', 'pydata__xarray-3905-16478', 'pydata__xarray-4182-16484', 'pydata__xarray-4248-16486', 'pydata__xarray-4339-16487', 'pydata__xarray-4419-16488', 'pydata__xarray-4629-16492', 'pydata__xarray-4750-16496', 'pydata__xarray-4802-16505', 'pydata__xarray-4966-16515', 'pydata__xarray-4994-16516', 'pydata__xarray-5033-16517', 'pydata__xarray-5126-16518', 'pydata__xarray-5126-16519', 'pydata__xarray-5131-16520', 'pydata__xarray-5365-16529', 'pydata__xarray-5455-16530', 'pydata__xarray-5662-16532', 'pydata__xarray-5731-16534', 'pydata__xarray-6135-16535', 'pydata__xarray-6135-16536', 'pydata__xarray-6386-16537', 'pydata__xarray-6394-16538', 'pydata__xarray-6400-16539', 'pydata__xarray-6461-16540', 'pydata__xarray-6548-16541', 'pydata__xarray-6599-16543', 'pydata__xarray-6601-16544', 'pydata__xarray-6882-16548', 'pydata__xarray-6889-16549', 'pydata__xarray-7003-16557', 'pydata__xarray-7147-16571', 'pydata__xarray-7150-16572', 'pydata__xarray-7203-16577', 'pydata__xarray-7229-16578', 'pydata__xarray-7393-16581', 'pydata__xarray-7400-16582']
|
||||
|
||||
|
||||
Command eval (our approach):
|
||||
poetry run ./evaluation/benchmarks/testgeneval/scripts/eval_infer_remote.sh evaluation/evaluation_outputs/outputs/kjain14__testgeneval-test/CodeActAgent/gpt-4o_maxiter_25_N_v0.20.0-no-hint-run_1/output.jsonl 10 kjain14/testgeneval test true
|
||||
|
||||
Command run (our approach):
|
||||
./evaluation/benchmarks/testgeneval/scripts/run_infer.sh llm.eval_gpt HEAD CodeActAgent -1 25 10 kjain14/testgeneval test 1 ../TestGenEval/results/testgeneval/preds/gpt-4o-2024-08-06__testgeneval__0.2__test.jsonl
|
||||
@@ -1,80 +0,0 @@
|
||||
# TestGenEval Benchmark Evaluation
|
||||
|
||||
This folder contains the evaluation harness for the TestGenEval benchmark, which is based on the original TestGenEval benchmark ([paper](https://arxiv.org/abs/2410.00752)). TestGenEval is designed to evaluate the ability of language models to generate unit tests for given Python functions.
|
||||
|
||||
## Setup Environment and LLM Configuration
|
||||
|
||||
1. Follow the instructions [here](../../README.md#setup) to set up your local development environment and configure your LLM.
|
||||
|
||||
2. Install the TestGenEval dependencies:
|
||||
```bash
|
||||
poetry install --with testgeneval
|
||||
```
|
||||
|
||||
## Run Inference
|
||||
|
||||
To generate tests using your model, run the following command:
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/testgeneval/scripts/run_infer.sh [model_config] [git-version] [agent] [eval_limit] [max_iter] [num_workers] [dataset] [dataset_split]
|
||||
|
||||
# Example
|
||||
./evaluation/benchmarks/testgeneval/scripts/run_infer.sh llm.eval_gpt4_1106_preview HEAD CodeActAgent 100 30 1 kjain14/testgenevallite test
|
||||
```
|
||||
|
||||
Parameters:
|
||||
- `model_config`: The config group name for your LLM settings (e.g., `eval_gpt4_1106_preview`)
|
||||
- `git-version`: The git commit hash or release tag of OpenHands to evaluate (e.g., `HEAD` or `0.6.2`)
|
||||
- `agent`: The name of the agent for benchmarks (default: `CodeActAgent`)
|
||||
- `eval_limit`: Limit the evaluation to the first N instances (optional)
|
||||
- `max_iter`: Maximum number of iterations for the agent to run (default: 30)
|
||||
- `num_workers`: Number of parallel workers for evaluation (default: 1)
|
||||
- `dataset`: HuggingFace dataset name (default: `kjain14/testgenevallite`)
|
||||
- `dataset_split`: Dataset split to use (default: `test`)
|
||||
|
||||
After running the inference, you will obtain an `output.jsonl` file (by default saved to `evaluation/evaluation_outputs`).
|
||||
|
||||
## Evaluate Generated Tests
|
||||
|
||||
To evaluate the generated tests, use the `eval_infer.sh` script:
|
||||
|
||||
```bash
|
||||
./evaluation/benchmarks/testgeneval/scripts/eval_infer.sh $YOUR_OUTPUT_JSONL [instance_id] [dataset_name] [split] [num_workers] [skip_mutation]
|
||||
|
||||
# Example
|
||||
./evaluation/benchmarks/testgeneval/scripts/eval_infer.sh evaluation/evaluation_outputs/outputs/kjain14__testgenevallite-test/CodeActAgent/gpt-4-1106-preview_maxiter_50_N_v1.0/output.jsonl
|
||||
```
|
||||
|
||||
Optional arguments:
|
||||
- `instance_id`: Evaluate a single instance (optional)
|
||||
- `dataset_name`: Name of the dataset to use (default: `kjain14/testgenevallite`)
|
||||
- `split`: Dataset split to use (default: `test`)
|
||||
- `num_workers`: Number of workers for running docker (default: 1)
|
||||
- `skip_mutation`: Skip mutation testing (enter `true` if desired)
|
||||
|
||||
The evaluation results will be saved to `evaluation/evaluation_outputs/outputs/kjain14__testgenevallite-test/CodeActAgent/gpt-4-1106-preview_maxiter_50_N_v1.0/` with `output.testgeneval.jsonl` containing the metrics.
|
||||
|
||||
## Metrics
|
||||
|
||||
The TestGenEval benchmark evaluates generated tests based on the following metrics:
|
||||
|
||||
1. Correctness: Measures if the generated tests are syntactically correct and run without errors.
|
||||
2. Coverage: Assesses the code coverage achieved by the generated tests.
|
||||
3. Mutation Score: Evaluates the effectiveness of the tests in detecting intentionally introduced bugs (mutations).
|
||||
4. Readability: Analyzes the readability of the generated tests using various metrics.
|
||||
|
||||
## Submit Your Evaluation Results
|
||||
|
||||
To contribute your evaluation results:
|
||||
|
||||
1. Fork [our HuggingFace evaluation outputs](https://huggingface.co/spaces/OpenHands/evaluation).
|
||||
2. Add your results to the forked repository.
|
||||
3. Submit a Pull Request with your evaluation results following the guide [here](https://huggingface.co/docs/hub/en/repositories-pull-requests-discussions#pull-requests-and-discussions).
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [TestGenEval Paper](https://arxiv.org/abs/2410.00752)
|
||||
- [OpenHands Documentation](https://github.com/All-Hands-AI/OpenHands)
|
||||
- [HuggingFace Datasets](https://huggingface.co/datasets)
|
||||
|
||||
For any questions or issues, please open an issue in the [OpenHands repository](https://github.com/All-Hands-AI/OpenHands/issues).
|
||||
@@ -1,351 +0,0 @@
|
||||
import math
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from tree_sitter import Language, Parser
|
||||
|
||||
|
||||
def total_byte_entropy_stats(python_code):
|
||||
# Count the occurrence of each byte (character for simplicity)
|
||||
byte_counts = {}
|
||||
for byte in python_code.encode('utf-8'):
|
||||
byte_counts[byte] = byte_counts.get(byte, 0) + 1
|
||||
|
||||
total_bytes = sum(byte_counts.values())
|
||||
entropy = -sum(
|
||||
(count / total_bytes) * math.log2(count / total_bytes)
|
||||
for count in byte_counts.values()
|
||||
)
|
||||
|
||||
return {'total_byte_entropy': entropy}
|
||||
|
||||
|
||||
def average_nulls_stats(tree, num_lines):
|
||||
total_nulls = 0
|
||||
nulls_per_line = {} # Dictionary to count nulls per line
|
||||
|
||||
def traverse(node):
|
||||
nonlocal total_nulls
|
||||
if node.type == 'null_literal':
|
||||
total_nulls += 1
|
||||
line_number = node.start_point[0] # Get line number
|
||||
if line_number in nulls_per_line:
|
||||
nulls_per_line[line_number] += 1
|
||||
else:
|
||||
nulls_per_line[line_number] = 1
|
||||
for child in node.children:
|
||||
traverse(child)
|
||||
|
||||
traverse(tree.root_node)
|
||||
|
||||
# Calculate average nulls per line
|
||||
avg_nulls = total_nulls / num_lines if num_lines > 0 else 0
|
||||
|
||||
# Calculate max nulls on any line
|
||||
max_nulls_on_any_line = max(nulls_per_line.values()) if nulls_per_line else 0
|
||||
|
||||
return {
|
||||
'avg_nulls': avg_nulls,
|
||||
'total_nulls': total_nulls,
|
||||
'max_nulls': max_nulls_on_any_line,
|
||||
'has_nulls': 1 if total_nulls > 0 else 0,
|
||||
}
|
||||
|
||||
|
||||
def arithmetic_operations_stats(tree, num_lines):
|
||||
# Dictionary to hold counts of each arithmetic operation
|
||||
op_counts = {'+': 0, '-': 0, '*': 0, '/': 0, '%': 0}
|
||||
total_ops = 0
|
||||
|
||||
# Function to traverse the AST and update operation counts
|
||||
def traverse(node):
|
||||
nonlocal total_ops
|
||||
if node.type == 'binary_expression' or node.type == 'update_expression':
|
||||
for child in node.children:
|
||||
if child.type == 'operator':
|
||||
op = child.text.decode('utf8')
|
||||
if op in op_counts:
|
||||
op_counts[op] += 1
|
||||
total_ops += 1
|
||||
else:
|
||||
for child in node.children:
|
||||
traverse(child)
|
||||
|
||||
traverse(tree.root_node)
|
||||
|
||||
return {
|
||||
'total_arithmetic_operations': total_ops,
|
||||
'avg_arithmetic_operations': total_ops / num_lines,
|
||||
}
|
||||
|
||||
|
||||
def numbers_floats_stats(tree, num_lines):
|
||||
total_numbers = 0
|
||||
total_floats = 0
|
||||
|
||||
def traverse(node):
|
||||
nonlocal total_numbers, total_floats
|
||||
if node.type in ['integer_literal', 'decimal_literal']:
|
||||
total_numbers += 1
|
||||
if (
|
||||
'.' in node.text.decode('utf8')
|
||||
or 'e' in node.text.decode('utf8').lower()
|
||||
):
|
||||
total_floats += 1
|
||||
for child in node.children:
|
||||
traverse(child)
|
||||
|
||||
traverse(tree.root_node)
|
||||
return {'total_numbers': total_numbers, 'total_floats': total_floats}
|
||||
|
||||
|
||||
def code_stats(python_code):
|
||||
lines = python_code.strip().split('\n')
|
||||
total_line_length = sum(len(line) for line in lines)
|
||||
max_line_length = max(len(line) for line in lines)
|
||||
return {
|
||||
'total_line_length': total_line_length,
|
||||
'max_line_length': max_line_length,
|
||||
'avg_characters': total_line_length / len(lines),
|
||||
}
|
||||
|
||||
|
||||
def assertions_stats(tree, num_lines):
|
||||
total_assertions = 0
|
||||
|
||||
def traverse(node):
|
||||
nonlocal total_assertions
|
||||
if node.type == 'assert_statement':
|
||||
total_assertions += 1
|
||||
for child in node.children:
|
||||
traverse(child)
|
||||
|
||||
traverse(tree.root_node)
|
||||
return {
|
||||
'total_assertions': total_assertions,
|
||||
'total_has_assertions': 1 if total_assertions > 0 else 0,
|
||||
}
|
||||
|
||||
|
||||
def class_instances_stats(tree, num_lines):
|
||||
total_class_instances = 0
|
||||
|
||||
def traverse(node):
|
||||
nonlocal total_class_instances
|
||||
if node.type == 'object_creation_expression':
|
||||
total_class_instances += 1
|
||||
for child in node.children:
|
||||
traverse(child)
|
||||
|
||||
traverse(tree.root_node)
|
||||
return {'total_class_instances': total_class_instances}
|
||||
|
||||
|
||||
def has_execeptions(tree, num_lines):
|
||||
total_has_exceptions = 0
|
||||
|
||||
def traverse(node):
|
||||
nonlocal total_has_exceptions
|
||||
if node.type == 'try_statement':
|
||||
total_has_exceptions += 1
|
||||
for child in node.children:
|
||||
traverse(child)
|
||||
|
||||
traverse(tree.root_node)
|
||||
return {'total_has_exceptions': 1 if total_has_exceptions > 0 else 0}
|
||||
|
||||
|
||||
def distinct_methods_stats(tree, num_lines):
|
||||
method_names = set()
|
||||
total_nodes = 0
|
||||
|
||||
def traverse(node):
|
||||
nonlocal total_nodes
|
||||
if node.type == 'method_declaration':
|
||||
for child in node.children:
|
||||
if child.type == 'identifier':
|
||||
method_names.add(child.text.decode('utf8'))
|
||||
break
|
||||
total_nodes += 1
|
||||
for child in node.children:
|
||||
traverse(child)
|
||||
|
||||
traverse(tree.root_node)
|
||||
total_distinct_methods = len(method_names)
|
||||
total_method_ratio = (
|
||||
total_distinct_methods / (total_nodes - total_distinct_methods)
|
||||
if total_nodes > total_distinct_methods
|
||||
else 0
|
||||
)
|
||||
|
||||
return {
|
||||
'total_distinct_methods': total_distinct_methods,
|
||||
'total_method_ratio': total_method_ratio,
|
||||
}
|
||||
|
||||
|
||||
def loops_stats(tree, num_lines):
|
||||
"""
|
||||
Calculate the average number of loops.
|
||||
"""
|
||||
total_loops = 0
|
||||
|
||||
def traverse(node):
|
||||
nonlocal total_loops
|
||||
if node.type in ['for_statement', 'while_statement', 'do_statement']:
|
||||
total_loops += 1
|
||||
for child in node.children:
|
||||
traverse(child)
|
||||
|
||||
traverse(tree.root_node)
|
||||
avg_loops = total_loops / num_lines
|
||||
return {'avg_loops': avg_loops}
|
||||
|
||||
|
||||
def branches_stats(tree, num_lines):
|
||||
"""
|
||||
Calculate the average number of branches (conditional statements).
|
||||
"""
|
||||
total_branches = 0
|
||||
|
||||
def traverse(node):
|
||||
nonlocal total_branches
|
||||
if node.type in ['if_statement', 'switch_statement']:
|
||||
total_branches += 1
|
||||
for child in node.children:
|
||||
traverse(child)
|
||||
|
||||
traverse(tree.root_node)
|
||||
# Assuming each branch is its own, this might need refinement based on definition
|
||||
avg_branches = total_branches / num_lines
|
||||
return {'avg_branches': avg_branches}
|
||||
|
||||
|
||||
def string_stats(tree, num_lines):
|
||||
string_literals = []
|
||||
|
||||
# Function to traverse the AST and collect string literals
|
||||
def traverse(node):
|
||||
if node.type == 'string_literal':
|
||||
# Extracting the string literal, excluding the quotation marks
|
||||
literal_text = node.text.decode('utf8')[1:-1]
|
||||
string_literals.append(literal_text)
|
||||
for child in node.children:
|
||||
traverse(child)
|
||||
|
||||
traverse(tree.root_node)
|
||||
|
||||
# Calculate the average string length
|
||||
total_length = sum(len(s) for s in string_literals)
|
||||
avg_length = total_length / num_lines
|
||||
return {'avg_str_length': avg_length}
|
||||
|
||||
|
||||
def identifier_stats(tree, num_lines):
|
||||
root_node = tree.root_node
|
||||
identifier_counts = {} # Dictionary to count occurrences of each identifier
|
||||
total_nodes = 0 # Counter for all nodes
|
||||
|
||||
# Function to recursively count identifiers and all nodes, gathering their stats
|
||||
def count(node):
|
||||
nonlocal identifier_counts, total_nodes
|
||||
iden_count = 0
|
||||
max_length = 0
|
||||
total_nodes += 1 # Increment total nodes for every node visited
|
||||
if node.type == 'identifier':
|
||||
identifier = node.text.decode('utf8') # Assuming UTF-8 encoding
|
||||
iden_count += 1
|
||||
identifier_counts[identifier] = identifier_counts.get(identifier, 0) + 1
|
||||
iden_length = len(identifier)
|
||||
if iden_length > max_length:
|
||||
max_length = iden_length
|
||||
for child in node.children:
|
||||
child_count, child_max_length = count(child)
|
||||
iden_count += child_count
|
||||
if child_max_length > max_length:
|
||||
max_length = child_max_length
|
||||
return iden_count, max_length
|
||||
|
||||
total_identifiers, max_identifier_length = count(root_node)
|
||||
total_unique_identifiers = len(identifier_counts)
|
||||
total_identifier_length = sum(len(k) * v for k, v in identifier_counts.items())
|
||||
avg_identifier_length = total_identifier_length / num_lines
|
||||
|
||||
# Calculate the identifier ratio as total identifiers over total nodes
|
||||
identifier_ratio = total_identifiers / total_nodes if total_nodes > 0 else 0
|
||||
|
||||
return {
|
||||
'total_identifiers': total_identifiers,
|
||||
'total_identifier_length': total_identifier_length,
|
||||
'max_identifier_length': max_identifier_length,
|
||||
'avg_identifier_length': avg_identifier_length,
|
||||
'total_unique_identifiers': total_unique_identifiers,
|
||||
'total_identifier_ratio': identifier_ratio, # Include the new ratio in the returned dictionary
|
||||
'total_nodes': total_nodes, # Include total node count for reference or further calculations
|
||||
}
|
||||
|
||||
|
||||
def compute_regression(results):
|
||||
components = {
|
||||
'total_line_length': -0.0001,
|
||||
'max_line_length': -0.0021,
|
||||
'total_identifiers': 0.0076,
|
||||
'total_identifier_length': -0.0004,
|
||||
'max_identifier_length': -0.0067,
|
||||
'avg_identifier_length': -0.005,
|
||||
'avg_arithmetic_operations': 0.0225,
|
||||
'avg_branches': 0.9886,
|
||||
'avg_loops': 0.1572,
|
||||
'total_assertions': 0.0119,
|
||||
'total_has_assertions': -0.0147,
|
||||
'avg_characters': 0.1242,
|
||||
'total_class_instances': -0.043,
|
||||
'total_distinct_methods': -0.0127,
|
||||
'avg_str_length': 0.0026,
|
||||
'total_has_exceptions': 0.1206,
|
||||
'total_unique_identifiers': -0.019,
|
||||
'max_nulls': -0.0712,
|
||||
'total_numbers': -0.0078,
|
||||
'avg_nulls': 0.1444,
|
||||
'total_identifier_ratio': 0.334,
|
||||
'total_method_ratio': 0.0406,
|
||||
'total_floats': -0.0174,
|
||||
'total_byte_entropy': -0.3917,
|
||||
}
|
||||
test_score = 0
|
||||
|
||||
for component in components:
|
||||
test_score += components[component] * results[component]
|
||||
|
||||
test_score += 5.7501
|
||||
return test_score
|
||||
|
||||
|
||||
def compute_readability(python_code):
|
||||
# Create parser and set up language
|
||||
import tree_sitter_python
|
||||
from tree_sitter import Parser, Language
|
||||
|
||||
parser = Parser(Language(tree_sitter_python.language()))
|
||||
|
||||
results = code_stats(python_code)
|
||||
|
||||
num_lines = len(python_code.strip().split('\n'))
|
||||
results.update(total_byte_entropy_stats(python_code))
|
||||
|
||||
tree = parser.parse(bytes(python_code, 'utf8'))
|
||||
|
||||
results.update(identifier_stats(tree, num_lines))
|
||||
results.update(loops_stats(tree, num_lines))
|
||||
results.update(branches_stats(tree, num_lines))
|
||||
results.update(distinct_methods_stats(tree, num_lines))
|
||||
results.update(has_execeptions(tree, num_lines))
|
||||
results.update(class_instances_stats(tree, num_lines))
|
||||
results.update(assertions_stats(tree, num_lines))
|
||||
results.update(numbers_floats_stats(tree, num_lines))
|
||||
results.update(average_nulls_stats(tree, num_lines))
|
||||
results.update(arithmetic_operations_stats(tree, num_lines))
|
||||
results.update(string_stats(tree, num_lines))
|
||||
|
||||
score = compute_regression(results)
|
||||
return score
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,629 +0,0 @@
|
||||
import os
|
||||
import tempfile
|
||||
import time
|
||||
from functools import partial
|
||||
|
||||
import pandas as pd
|
||||
from report_utils import (
|
||||
check_coverage,
|
||||
check_mutation,
|
||||
count_methods,
|
||||
get_lines_of_code,
|
||||
)
|
||||
|
||||
from evaluation.benchmarks.testgeneval.compute_readability import compute_readability
|
||||
from evaluation.benchmarks.testgeneval.constants import (
|
||||
COVERAGE_PREFIX,
|
||||
MUTATION_BUFFER,
|
||||
MUTATION_TEMPLATE,
|
||||
MUTATION_TIMEOUT,
|
||||
TESTS_SUFFIX,
|
||||
)
|
||||
from evaluation.benchmarks.testgeneval.metrics import (
|
||||
bleu,
|
||||
edit_sim,
|
||||
exact_match,
|
||||
rouge_l,
|
||||
)
|
||||
from evaluation.benchmarks.testgeneval.pygments_utils import tokenize_code
|
||||
from evaluation.benchmarks.testgeneval.run_infer import get_instance_docker_image
|
||||
from evaluation.benchmarks.testgeneval.test_filter import filter_tests
|
||||
from evaluation.benchmarks.testgeneval.test_spec import (
|
||||
TestGenEvalInstance,
|
||||
TestSpec,
|
||||
make_test_spec,
|
||||
)
|
||||
from evaluation.benchmarks.testgeneval.utils import load_testgeneval_dataset
|
||||
from evaluation.utils.shared import (
|
||||
EvalMetadata,
|
||||
EvalOutput,
|
||||
prepare_dataset,
|
||||
reset_logger_for_multiprocessing,
|
||||
run_evaluation,
|
||||
)
|
||||
from openhands.core.config import AppConfig, SandboxConfig, get_parser
|
||||
from openhands.core.logger import openhands_logger as logger
|
||||
from openhands.core.main import create_runtime
|
||||
from openhands.events.action import CmdRunAction
|
||||
from openhands.events.observation import CmdOutputObservation
|
||||
from openhands.utils.async_utils import call_async_from_sync
|
||||
|
||||
DOCKER_IMAGE_PREFIX = os.environ.get('EVAL_DOCKER_IMAGE_PREFIX', 'docker.io/kdjain/')
|
||||
logger.info(f'Using docker image prefix: {DOCKER_IMAGE_PREFIX}')
|
||||
|
||||
|
||||
def get_config(instance: pd.Series) -> AppConfig:
|
||||
base_container_image = get_instance_docker_image(instance['instance_id_swebench'])
|
||||
assert (
|
||||
base_container_image
|
||||
), f"Invalid container image for instance {instance['instance_id_swebench']}."
|
||||
logger.info(f'Using instance container image: {base_container_image}.')
|
||||
return AppConfig(
|
||||
run_as_openhands=False,
|
||||
runtime=os.environ.get('RUNTIME', 'eventstream'),
|
||||
sandbox=SandboxConfig(
|
||||
base_container_image=base_container_image,
|
||||
use_host_network=False,
|
||||
timeout=1800,
|
||||
api_key=os.environ.get('ALLHANDS_API_KEY'),
|
||||
remote_runtime_api_url=os.environ.get(
|
||||
'SANDBOX_REMOTE_RUNTIME_API_URL', 'http://localhost:8000'
|
||||
),
|
||||
),
|
||||
workspace_base=None,
|
||||
workspace_mount_path=None,
|
||||
)
|
||||
|
||||
|
||||
def compute_lexical_metrics(pred_suite, gold_suite):
|
||||
pred_loc = get_lines_of_code(pred_suite)
|
||||
gold_loc = get_lines_of_code(gold_suite)
|
||||
pred_methods = count_methods(pred_suite)
|
||||
gold_methods = count_methods(gold_suite)
|
||||
readability_pred = compute_readability(pred_suite)
|
||||
readability_gold = compute_readability(gold_suite)
|
||||
|
||||
preds = tokenize_code(pred_suite)
|
||||
golds = tokenize_code(gold_suite)
|
||||
|
||||
return {
|
||||
'pred_loc': pred_loc,
|
||||
'gold_loc': gold_loc,
|
||||
'pred_readability': readability_pred,
|
||||
'gold_readability': readability_gold,
|
||||
'pred_methods': pred_methods,
|
||||
'gold_methods': gold_methods,
|
||||
'bleu': bleu(preds, golds),
|
||||
'xmatch': exact_match(preds, golds),
|
||||
'edit_sim': edit_sim(preds, golds),
|
||||
'rouge_f': rouge_l(golds, preds)['f'],
|
||||
'rouge_p': rouge_l(golds, preds)['p'],
|
||||
'rouge_r': rouge_l(golds, preds)['r'],
|
||||
}
|
||||
|
||||
|
||||
def run_command(runtime, command, timeout=600):
|
||||
action = CmdRunAction(command=command)
|
||||
action.set_hard_timeout(timeout)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert obs.exit_code == 0
|
||||
return obs
|
||||
|
||||
|
||||
def run_tests(runtime, instance, test_script, log_file='/tmp/test_output.log'):
|
||||
action = CmdRunAction(command=f'bash {test_script} > {log_file} 2>&1 & echo $!')
|
||||
action.set_hard_timeout(60)
|
||||
obs = runtime.run_action(action)
|
||||
|
||||
assert isinstance(obs, CmdOutputObservation), 'Failed to start test script.'
|
||||
pid = obs.content.split()[-1].strip()
|
||||
logger.info(f'[{instance.instance_id}] Test process started with PID: {pid}')
|
||||
|
||||
start_time = time.time()
|
||||
timeout = 1800
|
||||
while True:
|
||||
elapsed_time = time.time() - start_time
|
||||
if elapsed_time > timeout:
|
||||
logger.info(f'[{instance.instance_id}] Test process timed out.')
|
||||
instance['test_result']['report']['test_timeout'] = True
|
||||
break
|
||||
|
||||
check_action = CmdRunAction(command=f'ps -p {pid} > /dev/null; echo $?')
|
||||
check_obs = runtime.run_action(check_action)
|
||||
if (
|
||||
isinstance(check_obs, CmdOutputObservation)
|
||||
and len(check_obs.content.split()) > 0
|
||||
and check_obs.content.split()[-1].strip() == '1'
|
||||
):
|
||||
logger.info(f'[{instance.instance_id}] Test process completed.')
|
||||
break
|
||||
time.sleep(30)
|
||||
|
||||
test_action = CmdRunAction(command=f'cat {log_file}')
|
||||
test_action.set_hard_timeout(300)
|
||||
test_obs = runtime.run_action(test_action)
|
||||
assert isinstance(test_obs, CmdOutputObservation), 'Failed to retrieve test output.'
|
||||
return test_obs.exit_code, test_obs.content, elapsed_time
|
||||
|
||||
|
||||
def run_mutation_testing(
|
||||
runtime, instance, mutation_script, log_file='/tmp/mutation_output.log'
|
||||
):
|
||||
action = CmdRunAction(command=f'bash {mutation_script} > {log_file} 2>&1 & echo $!')
|
||||
action.set_hard_timeout(60)
|
||||
obs = runtime.run_action(action)
|
||||
|
||||
assert isinstance(obs, CmdOutputObservation), 'Failed to start test script.'
|
||||
pid = obs.content.split()[-1].strip()
|
||||
logger.info(f'[{instance.instance_id}] Mutation process started with PID: {pid}')
|
||||
|
||||
start_time = time.time()
|
||||
timeout = 4000
|
||||
while True:
|
||||
elapsed_time = time.time() - start_time
|
||||
if elapsed_time > timeout:
|
||||
logger.info(f'[{instance.instance_id}] Mutation process timed out.')
|
||||
instance['test_result']['report']['mutation_timeout'] = True
|
||||
break
|
||||
|
||||
check_action = CmdRunAction(command=f'ps -p {pid} > /dev/null; echo $?')
|
||||
check_obs = runtime.run_action(check_action)
|
||||
if (
|
||||
isinstance(check_obs, CmdOutputObservation)
|
||||
and len(check_obs.content.split()) > 0
|
||||
and check_obs.content.split()[-1].strip() == '1'
|
||||
):
|
||||
logger.info(f'[{instance.instance_id}] Mutation process completed.')
|
||||
break
|
||||
time.sleep(30)
|
||||
|
||||
assert isinstance(obs, CmdOutputObservation), 'Failed to run mutation script.'
|
||||
mutation_action = CmdRunAction(command=f'cat {log_file}')
|
||||
mutation_action.set_hard_timeout(300)
|
||||
mutation_obs = runtime.run_action(mutation_action)
|
||||
assert isinstance(
|
||||
mutation_obs, CmdOutputObservation
|
||||
), 'Failed to retrieve mutation output.'
|
||||
return mutation_obs.exit_code, mutation_obs.content
|
||||
|
||||
|
||||
def grade_test_output(
|
||||
test_suite: str, instance: pd.Series, test_output: str, test_spec: TestSpec, runtime
|
||||
):
|
||||
"""
|
||||
Two-pass test grading with short-circuiting:
|
||||
1. Run all tests to identify passing/failing tests
|
||||
2. If no failing tests, evaluate coverage immediately
|
||||
3. Otherwise, run only passing tests for coverage analysis
|
||||
"""
|
||||
unit_test_output, coverage_output = '', ''
|
||||
if TESTS_SUFFIX in test_output:
|
||||
unit_test_output = test_output.split(TESTS_SUFFIX)[0]
|
||||
|
||||
if not unit_test_output:
|
||||
return (
|
||||
False,
|
||||
0,
|
||||
'',
|
||||
'',
|
||||
{
|
||||
'total_tests': 0,
|
||||
'passing_tests': 0,
|
||||
'failing_tests': 0,
|
||||
'any_pass': False,
|
||||
'all_pass': False,
|
||||
'passing_test_names': [],
|
||||
'failing_test_names': [],
|
||||
},
|
||||
)
|
||||
|
||||
logger.info('Calling filter unit tests')
|
||||
filtered_content, passing_tests, failing_tests = filter_tests(
|
||||
test_suite, unit_test_output, test_spec.repo
|
||||
)
|
||||
|
||||
total_tests = len(passing_tests) + len(failing_tests)
|
||||
test_stats = {
|
||||
'total_tests': total_tests,
|
||||
'passing_tests': len(passing_tests),
|
||||
'failing_tests': len(failing_tests),
|
||||
'any_pass': len(passing_tests) > 0,
|
||||
'all_pass': len(failing_tests) == 0 and total_tests > 0,
|
||||
'passing_test_names': passing_tests,
|
||||
'failing_test_names': failing_tests,
|
||||
}
|
||||
|
||||
if not passing_tests:
|
||||
return False, 0, unit_test_output, coverage_output, test_stats
|
||||
|
||||
# If all tests pass, evaluate coverage immediately
|
||||
if not failing_tests:
|
||||
coverage = 0
|
||||
cov_success = False
|
||||
if COVERAGE_PREFIX in test_output:
|
||||
coverage_output = test_output.split(COVERAGE_PREFIX)[1]
|
||||
_, coverage = check_coverage(coverage_output, test_spec.code_file)
|
||||
cov_success = True
|
||||
# test_stats['filtered_suite'] = test_suite
|
||||
return cov_success, coverage, unit_test_output, coverage_output, test_stats
|
||||
|
||||
cov_success = False
|
||||
coverage = 0
|
||||
# Second pass - run coverage on passing tests
|
||||
if filtered_content:
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
test_suite_path = os.path.join(temp_dir, 'test_suite.py')
|
||||
with open(test_suite_path, 'w') as f:
|
||||
f.write(filtered_content)
|
||||
runtime.copy_to(test_suite_path, '/tmp')
|
||||
|
||||
run_command(runtime, f'cp /tmp/test_suite.py /testbed/{test_spec.test_file}')
|
||||
_, test_output_second_pass, _ = run_tests(runtime, instance, '/tmp/test.sh')
|
||||
|
||||
coverage, coverage_output, unit_test_output = 0, '', test_output_second_pass
|
||||
|
||||
if COVERAGE_PREFIX in test_output_second_pass:
|
||||
coverage_output = test_output_second_pass.split(COVERAGE_PREFIX)[1]
|
||||
unit_test_output = test_output_second_pass.split(TESTS_SUFFIX)[0]
|
||||
_, coverage = check_coverage(coverage_output, test_spec.code_file)
|
||||
cov_success = True
|
||||
|
||||
# test_stats['filtered_suite'] = filtered_content
|
||||
return cov_success, coverage, unit_test_output, coverage_output, test_stats
|
||||
|
||||
|
||||
def process_instance(
|
||||
instance: pd.Series,
|
||||
metadata: EvalMetadata,
|
||||
reset_logger: bool = True,
|
||||
log_dir: str | None = None,
|
||||
) -> EvalOutput:
|
||||
"""
|
||||
Evaluate agent performance on a TestGenEval problem instance.
|
||||
|
||||
Note that this signature differs from the expected input to `run_evaluation`. Use
|
||||
`functools.partial` to provide optional arguments before passing to the evaluation harness.
|
||||
|
||||
Args:
|
||||
log_dir (str | None, default=None): Path to directory where log files will be written. Must
|
||||
be provided if `reset_logger` is set.
|
||||
|
||||
Raises:
|
||||
AssertionError: if the `reset_logger` flag is set without a provided log directory.
|
||||
"""
|
||||
if reset_logger:
|
||||
assert (
|
||||
log_dir is not None
|
||||
), "Can't reset logger without a provided log directory."
|
||||
os.makedirs(log_dir, exist_ok=True)
|
||||
reset_logger_for_multiprocessing(logger, instance.instance_id, log_dir)
|
||||
else:
|
||||
logger.info(f'Starting evaluation for instance {instance.instance_id}.')
|
||||
|
||||
config = get_config(instance)
|
||||
id = instance.instance_id
|
||||
logger.info(f'Starting evaluation for instance {id}.')
|
||||
|
||||
instance['test_result']['id'] = id
|
||||
instance['test_result']['report'] = {
|
||||
'test_output': '',
|
||||
# 'coverage_output': '',
|
||||
# 'mutation_output': '',
|
||||
'empty_generation': False,
|
||||
'error_eval': False,
|
||||
'all_tests_pass': False,
|
||||
'tests_pass': False,
|
||||
'test_timeout': False,
|
||||
'mutation_timeout': False,
|
||||
'coverage_success': False,
|
||||
'mutation_success': False,
|
||||
'coverage': 0,
|
||||
'mutation_score': 0,
|
||||
'mutation_error_interval': -1,
|
||||
'num_mutants': -1,
|
||||
}
|
||||
|
||||
instance['test_result']['lexical'] = {
|
||||
'pred_loc': -1,
|
||||
'gold_loc': -1,
|
||||
'pred_readability': -1,
|
||||
'gold_readability': -1,
|
||||
'pred_methods': -1,
|
||||
'gold_methods': -1,
|
||||
'bleu': -1,
|
||||
'xmatch': -1,
|
||||
'edit_sim': -1,
|
||||
'rouge_f': -1,
|
||||
'rouge_p': -1,
|
||||
'rouge_r': -1,
|
||||
}
|
||||
|
||||
if instance['test_suite'] == '' or instance['test_suite'] is None:
|
||||
instance['test_result']['report']['empty_generation'] = True
|
||||
return EvalOutput(
|
||||
instance_id=instance.instance_id, test_result=instance['test_result']
|
||||
)
|
||||
|
||||
if not args.skip_lexical:
|
||||
lexical_metrics = compute_lexical_metrics(
|
||||
instance['test_suite'], instance['instance']['test_src']
|
||||
)
|
||||
instance['test_result']['lexical'] = lexical_metrics
|
||||
|
||||
test_suite = instance['test_suite']
|
||||
test_spec: TestSpec = instance['test_spec']
|
||||
runtime = create_runtime(config)
|
||||
call_async_from_sync(runtime.connect)
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
test_suite_path = os.path.join(temp_dir, 'test_suite.py')
|
||||
with open(test_suite_path, 'w') as f:
|
||||
f.write(test_suite)
|
||||
runtime.copy_to(test_suite_path, '/tmp')
|
||||
|
||||
test_script_path = os.path.join(temp_dir, 'test.sh')
|
||||
with open(test_script_path, 'w') as f:
|
||||
f.write(test_spec.test_script)
|
||||
runtime.copy_to(test_script_path, '/tmp')
|
||||
|
||||
mutation_script_path = os.path.join(temp_dir, 'mutation.sh')
|
||||
with open(mutation_script_path, 'w') as f:
|
||||
f.write(test_spec.mutation_script)
|
||||
runtime.copy_to(mutation_script_path, '/tmp')
|
||||
|
||||
try:
|
||||
run_command(runtime, 'chmod +x /tmp/test.sh /tmp/mutation.sh')
|
||||
run_command(runtime, f'cp /tmp/test_suite.py /testbed/{test_spec.test_file}')
|
||||
|
||||
# First pass - run all tests
|
||||
_, test_output, test_time = run_tests(runtime, instance, '/tmp/test.sh')
|
||||
|
||||
# Grade tests with two-pass approach
|
||||
coverage_success, coverage, unit_test_output, coverage_output, test_stats = (
|
||||
grade_test_output(test_suite, instance, test_output, test_spec, runtime)
|
||||
)
|
||||
|
||||
# Update report with test statistics
|
||||
instance['test_result']['report'].update(
|
||||
{
|
||||
'test_output': unit_test_output,
|
||||
# 'coverage_output': coverage_output,
|
||||
'tests_pass': test_stats['any_pass'], # Changed to use any_pass
|
||||
'all_tests_pass': test_stats['all_pass'], # Added all_pass metric
|
||||
'coverage_success': coverage_success,
|
||||
'coverage': coverage if coverage_success else 0,
|
||||
'test_stats': test_stats,
|
||||
}
|
||||
)
|
||||
|
||||
# Only run mutation testing if we have passing tests and coverage
|
||||
if (
|
||||
not args.skip_mutation
|
||||
and coverage_success
|
||||
and test_stats['any_pass']
|
||||
and coverage > 0
|
||||
):
|
||||
mutation_timeout = max(10, 1.5 * test_time)
|
||||
mutation_toml = MUTATION_TEMPLATE.format(
|
||||
test_cmd=test_spec.test_cmd,
|
||||
source_fp=test_spec.code_file,
|
||||
timeout=mutation_timeout,
|
||||
)
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
mutation_toml_path = os.path.join(temp_dir, 'mutation.toml')
|
||||
with open(mutation_toml_path, 'w') as f:
|
||||
f.write(mutation_toml)
|
||||
runtime.copy_to(mutation_toml_path, '/tmp')
|
||||
|
||||
run_command(runtime, 'cp /tmp/mutation.toml /testbed/mutation.toml')
|
||||
|
||||
mutation_code, mutation_output = run_mutation_testing(
|
||||
runtime, instance, '/tmp/mutation.sh'
|
||||
)
|
||||
# instance['test_result']['report']['mutation_output'] = mutation_output
|
||||
if mutation_output and mutation_code == 0:
|
||||
(
|
||||
mutation_success,
|
||||
num_mutants,
|
||||
mutation_score,
|
||||
mutation_confidence_interval,
|
||||
) = check_mutation(mutation_output)
|
||||
instance['test_result']['report']['num_mutants'] = num_mutants
|
||||
instance['test_result']['report']['mutation_success'] = mutation_success
|
||||
instance['test_result']['report']['mutation_score'] = mutation_score
|
||||
instance['test_result']['report']['mutation_error_interval'] = (
|
||||
mutation_confidence_interval
|
||||
)
|
||||
|
||||
return EvalOutput(
|
||||
instance_id=instance.instance_id, test_result=instance['test_result']
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f'Error processing instance {instance.instance_id}: {e}')
|
||||
raise RuntimeError(
|
||||
instance.instance_id,
|
||||
'Unexpected output...',
|
||||
logger,
|
||||
)
|
||||
|
||||
finally:
|
||||
runtime.close()
|
||||
|
||||
|
||||
def count_and_log_fields(evaluated_predictions, fields, key):
|
||||
"""
|
||||
Count and log the sum of specified fields in the evaluated predictions,
|
||||
ignoring fields with a value of -1. If all values for a field are -1,
|
||||
return -1.
|
||||
|
||||
:param evaluated_predictions: DataFrame containing evaluation results
|
||||
:param fields: List of field names to count
|
||||
:param key: Key to access the field values ('report' or 'lexical')
|
||||
"""
|
||||
|
||||
def count_field(row, field):
|
||||
value = row['test_result'][key][field]
|
||||
return (
|
||||
value if value != -1 else None
|
||||
) # Ignore -1 fields by treating them as None
|
||||
|
||||
for field in fields:
|
||||
# Extract the valid values for the field, ignoring -1
|
||||
valid_values = evaluated_predictions.apply(
|
||||
count_field, args=(field,), axis=1
|
||||
).dropna()
|
||||
|
||||
if valid_values.empty: # If all values are -1
|
||||
logger.info(f'# {field}: -1 (All values are -1)')
|
||||
else:
|
||||
count = valid_values.sum() # Sum of valid values
|
||||
length = len(valid_values) # Count of valid entries
|
||||
logger.info(f'# {field}: {length}. ({count / length:.2f})')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = get_parser()
|
||||
parser.add_argument(
|
||||
'--input-file', type=str, required=True, help='Path to input predictions file'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--dataset',
|
||||
type=str,
|
||||
default='kjain14/testgeneval',
|
||||
help='Dataset to evaluate on',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--split', type=str, default='test', help='Split to evaluate on'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--skip_mutation', action='store_true', help='Skip mutation testing'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--skip_lexical', action='store_true', help='Skip lexical metrics'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--mutation_timeout',
|
||||
type=int,
|
||||
default=MUTATION_TIMEOUT,
|
||||
help='Mutation timeout',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--mutation_buffer',
|
||||
type=int,
|
||||
default=MUTATION_BUFFER,
|
||||
help='Mutation buffer',
|
||||
)
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
dataset: list[TestGenEvalInstance] = load_testgeneval_dataset(
|
||||
args.dataset, args.split
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f'Loaded dataset {args.dataset} with split {args.split} to run inference on.'
|
||||
)
|
||||
|
||||
# Load predictions
|
||||
assert args.input_file.endswith('.jsonl'), 'Input file must be a jsonl file.'
|
||||
predictions = pd.read_json(args.input_file, lines=True)
|
||||
assert (
|
||||
'instance_id' in predictions.columns
|
||||
), 'Input file must contain instance_id column.'
|
||||
|
||||
if 'test_suite' not in predictions.columns and (
|
||||
'test_result' in predictions.columns
|
||||
and 'test_suite' in predictions['test_result'].iloc(0)
|
||||
):
|
||||
raise ValueError(
|
||||
'Input file must contain test_suite column OR test_result column with test_suite field.'
|
||||
)
|
||||
|
||||
if 'instance_id_swebench' not in predictions.columns:
|
||||
predictions['instance_id_swebench'] = predictions['instance'].apply(
|
||||
lambda x: x['instance_id_swebench']
|
||||
)
|
||||
|
||||
if 'instance_id' not in predictions.columns and (
|
||||
'instance_id' in predictions['instance'].iloc(0)
|
||||
):
|
||||
raise ValueError(
|
||||
'Input file must contain id column OR instance column with id field.'
|
||||
)
|
||||
|
||||
if 'instance_id' not in predictions.columns:
|
||||
predictions['instance_id'] = predictions['instance'].apply(
|
||||
lambda x: x['instance_id']
|
||||
)
|
||||
|
||||
if 'test_suite' not in predictions.columns:
|
||||
predictions['test_suite'] = predictions['test_result'].apply(
|
||||
lambda x: x['test_suite']
|
||||
)
|
||||
|
||||
assert len(predictions['instance_id'].unique()) == len(
|
||||
predictions
|
||||
), 'instance_id column must be unique.'
|
||||
|
||||
assert {'instance_id_swebench', 'test_suite', 'instance_id'}.issubset(
|
||||
set(predictions.columns)
|
||||
), 'Input file must contain id, instance_id and test_suite columns.'
|
||||
|
||||
predictions['test_spec'] = predictions['instance'].apply(
|
||||
lambda x: make_test_spec(x, args.mutation_timeout, args.mutation_buffer)
|
||||
)
|
||||
|
||||
output_file = args.input_file.replace('.jsonl', '.testgeneval.jsonl')
|
||||
instances = prepare_dataset(predictions, output_file, args.eval_n_limit)
|
||||
|
||||
# If possible, load the relevant metadata to avoid issues with `run_evaluation`.
|
||||
metadata: EvalMetadata | None = None
|
||||
metadata_filepath = os.path.join(os.path.dirname(args.input_file), 'metadata.json')
|
||||
if os.path.exists(metadata_filepath):
|
||||
with open(metadata_filepath, 'r') as metadata_file:
|
||||
data = metadata_file.read()
|
||||
metadata = EvalMetadata.model_validate_json(data)
|
||||
|
||||
# The evaluation harness constrains the signature of `process_instance_func` but we need to
|
||||
# pass extra information. Build a new function object to avoid issues with multiprocessing.
|
||||
process_instance_func = partial(
|
||||
process_instance, log_dir=output_file.replace('.jsonl', '.logs')
|
||||
)
|
||||
|
||||
run_evaluation(
|
||||
instances,
|
||||
metadata=None,
|
||||
output_file=output_file,
|
||||
num_workers=args.eval_num_workers,
|
||||
process_instance_func=process_instance_func,
|
||||
)
|
||||
|
||||
# Load evaluated predictions & print number of resolved predictions
|
||||
evaluated_predictions = pd.read_json(output_file, lines=True)
|
||||
report_fields = [
|
||||
'coverage',
|
||||
'mutation_score',
|
||||
'tests_pass',
|
||||
'all_tests_pass',
|
||||
'empty_generation',
|
||||
'coverage_success',
|
||||
'test_timeout',
|
||||
'error_eval',
|
||||
]
|
||||
lexical_fields = [
|
||||
'pred_loc',
|
||||
'gold_loc',
|
||||
'pred_methods',
|
||||
'gold_methods',
|
||||
'bleu',
|
||||
'xmatch',
|
||||
'edit_sim',
|
||||
'rouge_f',
|
||||
'rouge_p',
|
||||
'rouge_r',
|
||||
]
|
||||
|
||||
# Log report and lexical fields
|
||||
count_and_log_fields(evaluated_predictions, report_fields, key='report')
|
||||
count_and_log_fields(evaluated_predictions, lexical_fields, key='lexical')
|
||||
@@ -1,291 +0,0 @@
|
||||
import re
|
||||
|
||||
from evaluation.benchmarks.testgeneval.constants import TestStatus
|
||||
|
||||
|
||||
def parse_log_pytest(log: str) -> dict[str, str]:
|
||||
"""
|
||||
Parser for test logs generated with PyTest framework
|
||||
|
||||
Args:
|
||||
log (str): log content
|
||||
Returns:
|
||||
dict: test case to test status mapping
|
||||
"""
|
||||
test_status_map = {}
|
||||
for line in log.split('\n'):
|
||||
if any([line.startswith(x.value) for x in TestStatus]):
|
||||
# Additional parsing for FAILED status
|
||||
if line.startswith(TestStatus.FAILED.value):
|
||||
line = line.replace(' - ', ' ')
|
||||
test_case = line.split()
|
||||
if len(test_case) <= 1:
|
||||
continue
|
||||
test_status_map[test_case[1]] = test_case[0]
|
||||
return test_status_map
|
||||
|
||||
|
||||
def parse_log_pytest_options(log: str) -> dict[str, str]:
|
||||
"""
|
||||
Parser for test logs generated with PyTest framework with options
|
||||
|
||||
Args:
|
||||
log (str): log content
|
||||
Returns:
|
||||
dict: test case to test status mapping
|
||||
"""
|
||||
option_pattern = re.compile(r'(.*?)\[(.*)\]')
|
||||
test_status_map = {}
|
||||
for line in log.split('\n'):
|
||||
if any([line.startswith(x.value) for x in TestStatus]):
|
||||
# Additional parsing for FAILED status
|
||||
if line.startswith(TestStatus.FAILED.value):
|
||||
line = line.replace(' - ', ' ')
|
||||
test_case = line.split()
|
||||
if len(test_case) <= 1:
|
||||
continue
|
||||
has_option = option_pattern.search(test_case[1])
|
||||
if has_option:
|
||||
main, option = has_option.groups()
|
||||
if (
|
||||
option.startswith('/')
|
||||
and not option.startswith('//')
|
||||
and '*' not in option
|
||||
):
|
||||
option = '/' + option.split('/')[-1]
|
||||
test_name = f'{main}[{option}]'
|
||||
else:
|
||||
test_name = test_case[1]
|
||||
test_status_map[test_name] = test_case[0]
|
||||
return test_status_map
|
||||
|
||||
|
||||
def parse_log_django(log: str) -> dict[str, str]:
|
||||
"""
|
||||
Parser for test logs generated with Django tester framework
|
||||
|
||||
Args:
|
||||
log (str): log content
|
||||
Returns:
|
||||
dict: test case to test status mapping
|
||||
"""
|
||||
test_status_map = {}
|
||||
lines = log.split('\n')
|
||||
|
||||
prev_test = None
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
|
||||
# This isn't ideal but the test output spans multiple lines
|
||||
if '--version is equivalent to version' in line:
|
||||
test_status_map['--version is equivalent to version'] = (
|
||||
TestStatus.PASSED.value
|
||||
)
|
||||
|
||||
# Log it in case of error
|
||||
if ' ... ' in line:
|
||||
prev_test = line.split(' ... ')[0]
|
||||
|
||||
pass_suffixes = (' ... ok', ' ... OK', ' ... OK')
|
||||
for suffix in pass_suffixes:
|
||||
if line.endswith(suffix):
|
||||
# TODO: Temporary, exclusive fix for django__django-7188
|
||||
# The proper fix should involve somehow getting the test results to
|
||||
# print on a separate line, rather than the same line
|
||||
if line.strip().startswith(
|
||||
'Applying sites.0002_alter_domain_unique...test_no_migrations'
|
||||
):
|
||||
line = line.split('...', 1)[-1].strip()
|
||||
test = line.rsplit(suffix, 1)[0]
|
||||
test_status_map[test] = TestStatus.PASSED.value
|
||||
break
|
||||
if ' ... skipped' in line:
|
||||
test = line.split(' ... skipped')[0]
|
||||
test_status_map[test] = TestStatus.SKIPPED.value
|
||||
if line.endswith(' ... FAIL'):
|
||||
test = line.split(' ... FAIL')[0]
|
||||
test_status_map[test] = TestStatus.FAILED.value
|
||||
if line.startswith('FAIL:'):
|
||||
test = line.split()[1].strip()
|
||||
test_status_map[test] = TestStatus.FAILED.value
|
||||
if line.endswith(' ... ERROR'):
|
||||
test = line.split(' ... ERROR')[0]
|
||||
test_status_map[test] = TestStatus.ERROR.value
|
||||
if line.startswith('ERROR:'):
|
||||
test = line.split()[1].strip()
|
||||
test_status_map[test] = TestStatus.ERROR.value
|
||||
|
||||
if line.lstrip().startswith('ok') and prev_test is not None:
|
||||
# It means the test passed, but there's some additional output (including new lines)
|
||||
# between "..." and "ok" message
|
||||
test = prev_test
|
||||
test_status_map[test] = TestStatus.PASSED.value
|
||||
|
||||
# TODO: This is very brittle, we should do better
|
||||
# There's a bug in the django logger, such that sometimes a test output near the end gets
|
||||
# interrupted by a particular long multiline print statement.
|
||||
# We have observed this in one of 3 forms:
|
||||
# - "{test_name} ... Testing against Django installed in {*} silenced.\nok"
|
||||
# - "{test_name} ... Internal Server Error: \/(.*)\/\nok"
|
||||
# - "{test_name} ... System check identified no issues (0 silenced).\nok"
|
||||
patterns = [
|
||||
r'^(.*?)\s\.\.\.\sTesting\ against\ Django\ installed\ in\ ((?s:.*?))\ silenced\)\.\nok$',
|
||||
r'^(.*?)\s\.\.\.\sInternal\ Server\ Error:\ \/(.*)\/\nok$',
|
||||
r'^(.*?)\s\.\.\.\sSystem check identified no issues \(0 silenced\)\nok$',
|
||||
]
|
||||
for pattern in patterns:
|
||||
for match in re.finditer(pattern, log, re.MULTILINE):
|
||||
test_name = match.group(1)
|
||||
test_status_map[test_name] = TestStatus.PASSED.value
|
||||
return test_status_map
|
||||
|
||||
|
||||
def parse_log_pytest_v2(log: str) -> dict[str, str]:
|
||||
"""
|
||||
Parser for test logs generated with PyTest framework (Later Version)
|
||||
|
||||
Args:
|
||||
log (str): log content
|
||||
Returns:
|
||||
dict: test case to test status mapping
|
||||
"""
|
||||
test_status_map = {}
|
||||
escapes = ''.join([chr(char) for char in range(1, 32)])
|
||||
for line in log.split('\n'):
|
||||
line = re.sub(r'\[(\d+)m', '', line)
|
||||
translator = str.maketrans('', '', escapes)
|
||||
line = line.translate(translator)
|
||||
if any([line.startswith(x.value) for x in TestStatus]):
|
||||
if line.startswith(TestStatus.FAILED.value):
|
||||
line = line.replace(' - ', ' ')
|
||||
test_case = line.split()
|
||||
if len(test_case) >= 2:
|
||||
test_status_map[test_case[1]] = test_case[0]
|
||||
# Support older pytest versions by checking if the line ends with the test status
|
||||
elif any([line.endswith(x.value) for x in TestStatus]):
|
||||
test_case = line.split()
|
||||
if len(test_case) >= 2:
|
||||
test_status_map[test_case[0]] = test_case[1]
|
||||
return test_status_map
|
||||
|
||||
|
||||
def parse_log_seaborn(log: str) -> dict[str, str]:
|
||||
"""
|
||||
Parser for test logs generated with seaborn testing framework
|
||||
|
||||
Args:
|
||||
log (str): log content
|
||||
Returns:
|
||||
dict: test case to test status mapping
|
||||
"""
|
||||
test_status_map = {}
|
||||
for line in log.split('\n'):
|
||||
if line.startswith(TestStatus.FAILED.value):
|
||||
test_case = line.split()[1]
|
||||
test_status_map[test_case] = TestStatus.FAILED.value
|
||||
elif f' {TestStatus.PASSED.value} ' in line:
|
||||
parts = line.split()
|
||||
if parts[1] == TestStatus.PASSED.value:
|
||||
test_case = parts[0]
|
||||
test_status_map[test_case] = TestStatus.PASSED.value
|
||||
elif line.startswith(TestStatus.PASSED.value):
|
||||
parts = line.split()
|
||||
test_case = parts[1]
|
||||
test_status_map[test_case] = TestStatus.PASSED.value
|
||||
return test_status_map
|
||||
|
||||
|
||||
def parse_log_sympy(log: str) -> dict[str, str]:
|
||||
"""
|
||||
Parser for test logs generated with Sympy framework
|
||||
|
||||
Args:
|
||||
log (str): log content
|
||||
Returns:
|
||||
dict: test case to test status mapping
|
||||
"""
|
||||
test_status_map = {}
|
||||
pattern = r'(_*) (.*)\.py:(.*) (_*)'
|
||||
matches = re.findall(pattern, log)
|
||||
for match in matches:
|
||||
test_case = f'{match[1]}.py:{match[2]}'
|
||||
test_status_map[test_case] = TestStatus.FAILED.value
|
||||
for line in log.split('\n'):
|
||||
line = line.strip()
|
||||
if line.startswith('test_'):
|
||||
if line.endswith('[FAIL]') or line.endswith('[OK]'):
|
||||
line = line[: line.rfind('[')]
|
||||
line = line.strip()
|
||||
if line.endswith(' E'):
|
||||
test = line.split()[0]
|
||||
test_status_map[test] = TestStatus.ERROR.value
|
||||
if line.endswith(' F'):
|
||||
test = line.split()[0]
|
||||
test_status_map[test] = TestStatus.FAILED.value
|
||||
if line.endswith(' ok'):
|
||||
test = line.split()[0]
|
||||
test_status_map[test] = TestStatus.PASSED.value
|
||||
return test_status_map
|
||||
|
||||
|
||||
def parse_log_matplotlib(log: str) -> dict[str, str]:
|
||||
"""
|
||||
Parser for test logs generated with PyTest framework
|
||||
|
||||
Args:
|
||||
log (str): log content
|
||||
Returns:
|
||||
dict: test case to test status mapping
|
||||
"""
|
||||
test_status_map = {}
|
||||
for line in log.split('\n'):
|
||||
line = line.replace('MouseButton.LEFT', '1')
|
||||
line = line.replace('MouseButton.RIGHT', '3')
|
||||
if any([line.startswith(x.value) for x in TestStatus]):
|
||||
# Additional parsing for FAILED status
|
||||
if line.startswith(TestStatus.FAILED.value):
|
||||
line = line.replace(' - ', ' ')
|
||||
test_case = line.split()
|
||||
if len(test_case) <= 1:
|
||||
continue
|
||||
test_status_map[test_case[1]] = test_case[0]
|
||||
return test_status_map
|
||||
|
||||
|
||||
parse_log_astroid = parse_log_pytest
|
||||
parse_log_flask = parse_log_pytest
|
||||
parse_log_marshmallow = parse_log_pytest
|
||||
parse_log_pvlib = parse_log_pytest
|
||||
parse_log_pyvista = parse_log_pytest
|
||||
parse_log_sqlfluff = parse_log_pytest
|
||||
parse_log_xarray = parse_log_pytest
|
||||
|
||||
parse_log_pydicom = parse_log_pytest_options
|
||||
parse_log_requests = parse_log_pytest_options
|
||||
parse_log_pylint = parse_log_pytest_options
|
||||
|
||||
parse_log_astropy = parse_log_pytest_v2
|
||||
parse_log_scikit = parse_log_pytest_v2
|
||||
parse_log_sphinx = parse_log_pytest_v2
|
||||
|
||||
|
||||
MAP_REPO_TO_PARSER = {
|
||||
'astropy/astropy': parse_log_astropy,
|
||||
'django/django': parse_log_django,
|
||||
'marshmallow-code/marshmallow': parse_log_marshmallow,
|
||||
'matplotlib/matplotlib': parse_log_matplotlib,
|
||||
'mwaskom/seaborn': parse_log_seaborn,
|
||||
'pallets/flask': parse_log_flask,
|
||||
'psf/requests': parse_log_requests,
|
||||
'pvlib/pvlib-python': parse_log_pvlib,
|
||||
'pydata/xarray': parse_log_xarray,
|
||||
'pydicom/pydicom': parse_log_pydicom,
|
||||
'pylint-dev/astroid': parse_log_astroid,
|
||||
'pylint-dev/pylint': parse_log_pylint,
|
||||
'pytest-dev/pytest': parse_log_pytest,
|
||||
'pyvista/pyvista': parse_log_pyvista,
|
||||
'scikit-learn/scikit-learn': parse_log_scikit,
|
||||
'sqlfluff/sqlfluff': parse_log_sqlfluff,
|
||||
'sphinx-doc/sphinx': parse_log_sphinx,
|
||||
'sympy/sympy': parse_log_sympy,
|
||||
}
|
||||
@@ -1,311 +0,0 @@
|
||||
import sys
|
||||
from typing import Callable, Dict, List, Optional, Sequence, TypeVar, Union
|
||||
|
||||
import nltk
|
||||
import numpy as np
|
||||
from fuzzywuzzy import fuzz
|
||||
from rouge import Rouge
|
||||
|
||||
|
||||
|
||||
# increase recursion depth to ensure ROUGE can be calculated for long sentences
|
||||
if sys.getrecursionlimit() < 10_000:
|
||||
sys.setrecursionlimit(10_000)
|
||||
|
||||
def bleu(gold: List[str], pred: List[str]) -> float:
|
||||
"""
|
||||
Calculate BLEU score, using smoothing method 2 with auto reweighting, in the range of 0~100.
|
||||
|
||||
:param gold: list of gold tokens
|
||||
:param pred: list of predicted tokens
|
||||
:return: BLEU score
|
||||
"""
|
||||
if len(pred) == 0 or len(gold) == 0:
|
||||
return 0.0
|
||||
return 100.0 * nltk.translate.bleu_score.sentence_bleu(
|
||||
[gold],
|
||||
pred,
|
||||
smoothing_function=nltk.translate.bleu_score.SmoothingFunction().method2,
|
||||
auto_reweigh=True,
|
||||
)
|
||||
|
||||
|
||||
def batch_bleu(golds: List[List[str]], preds: List[List[str]]) -> List[float]:
|
||||
"""
|
||||
Calculate BLEU score for a batch of sentences.
|
||||
|
||||
:param golds: list of gold sentences
|
||||
:param preds: list of predicted sentences
|
||||
:return: list of BLEU scores
|
||||
"""
|
||||
if len(golds) != len(preds):
|
||||
raise ValueError("golds and preds must have the same length")
|
||||
return [bleu(gold, pred) for gold, pred in zip(golds, preds)]
|
||||
|
||||
|
||||
def corpus_bleu(golds: List[List[str]], preds: List[List[str]]) -> float:
|
||||
"""
|
||||
Calculate corpus-level BLEU score for a batch of sentences.
|
||||
|
||||
:param golds: list of gold sentences
|
||||
:param preds: list of predicted sentences
|
||||
:return: corpus-level BLEU score
|
||||
"""
|
||||
if len(golds) != len(preds):
|
||||
raise ValueError("golds and preds must have the same length")
|
||||
return 100.0 * nltk.translate.bleu_score.corpus_bleu(
|
||||
[[gold] for gold in golds],
|
||||
preds,
|
||||
smoothing_function=nltk.translate.bleu_score.SmoothingFunction().method2,
|
||||
auto_reweigh=True,
|
||||
)
|
||||
|
||||
|
||||
def edit_sim(
|
||||
gold: Union[str, List[str]], pred: Union[str, List[str]], sep: str = " "
|
||||
) -> float:
|
||||
"""
|
||||
Calculate char-level edit similarity, in the range of 0~100.
|
||||
|
||||
:param gold: gold sentence or list of gold tokens
|
||||
:param pred: predicted sentence or list of predicted tokens
|
||||
:param sep: separator between tokens
|
||||
:return: char-level edit similarity
|
||||
"""
|
||||
if len(pred) == 0 or len(gold) == 0:
|
||||
return 0.0
|
||||
if isinstance(gold, list):
|
||||
gold = sep.join(gold)
|
||||
if isinstance(pred, list):
|
||||
pred = sep.join(pred)
|
||||
return fuzz.ratio(gold, pred)
|
||||
|
||||
|
||||
def batch_edit_sim(
|
||||
golds: List[Union[str, List[str]]],
|
||||
preds: List[Union[str, List[str]]],
|
||||
sep: str = " ",
|
||||
) -> List[float]:
|
||||
"""
|
||||
Calculate char-level edit similarity for a batch of sentences.
|
||||
|
||||
:param golds: list of gold sentences
|
||||
:param preds: list of predicted sentences
|
||||
:param sep: separator between tokens
|
||||
:return: list of char-level edit similarity
|
||||
"""
|
||||
if len(golds) != len(preds):
|
||||
raise ValueError("golds and preds must have the same length")
|
||||
return [edit_sim(gold, pred, sep) for gold, pred in zip(golds, preds)]
|
||||
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def exact_match(gold: T, pred: T) -> float:
|
||||
"""
|
||||
Calculate exact match accuracy, in the range of {0, 100}.
|
||||
|
||||
:param gold: gold sentence or list of gold tokens
|
||||
:param pred: predicted sentence or list of predicted tokens
|
||||
:return: exact match accuracy
|
||||
"""
|
||||
if len(pred) == 0 or len(gold) == 0:
|
||||
return 0.0
|
||||
return 100.0 if gold == pred else 0.0
|
||||
|
||||
|
||||
def batch_exact_match(golds: List[T], preds: List[T]) -> List[float]:
|
||||
"""
|
||||
Calculate exact match accuracy for a batch of sentences.
|
||||
|
||||
:param golds: list of gold sentences
|
||||
:param preds: list of predicted sentences
|
||||
:return: list of exact match accuracy
|
||||
"""
|
||||
if len(golds) != len(preds):
|
||||
raise ValueError("golds and preds must have the same length")
|
||||
return [exact_match(gold, pred) for gold, pred in zip(golds, preds)]
|
||||
|
||||
|
||||
def rouge_l(
|
||||
gold: Union[str, List[str]], pred: Union[str, List[str]], sep: str = " "
|
||||
) -> Dict[str, float]:
|
||||
"""
|
||||
Calculate ROUGE-L F1, precision, and recall scores, in the range of 0~100.
|
||||
|
||||
:param gold: gold sentence or list of gold tokens
|
||||
:param pred: predicted sentence or list of predicted tokens
|
||||
:return: {"p": precision, "r": recall, "f": F1}
|
||||
"""
|
||||
if len(pred) == 0 or len(gold) == 0:
|
||||
return {"p": 0.0, "r": 0.0, "f": 0.0}
|
||||
if isinstance(gold, list):
|
||||
gold = sep.join(gold)
|
||||
if isinstance(pred, list):
|
||||
pred = sep.join(pred)
|
||||
try:
|
||||
rouge = Rouge()
|
||||
scores = rouge.get_scores(hyps=pred, refs=gold, avg=True)
|
||||
return {x: scores["rouge-l"][x] * 100.0 for x in ["p", "r", "f"]}
|
||||
except ValueError:
|
||||
return {"p": 0.0, "r": 0.0, "f": 0.0}
|
||||
|
||||
|
||||
def batch_rouge_l(
|
||||
golds: List[Union[str, List[str]]],
|
||||
preds: List[Union[str, List[str]]],
|
||||
sep: str = " ",
|
||||
) -> Dict[str, List[float]]:
|
||||
"""
|
||||
Calculate ROUGE-L F1, precision, and recall scores for a batch of sentences.
|
||||
|
||||
:param golds: list of gold sentences
|
||||
:param preds: list of predicted sentences
|
||||
:param sep: separator between tokens
|
||||
:return: list of {"p": precision, "r": recall, "f": F1}
|
||||
"""
|
||||
if len(golds) != len(preds):
|
||||
raise ValueError("golds and preds must have the same length")
|
||||
scores = [rouge_l(gold, pred, sep) for gold, pred in zip(golds, preds)]
|
||||
return {x: [score[x] for score in scores] for x in ["p", "r", "f"]}
|
||||
|
||||
|
||||
def accuracy(
|
||||
gold: List[str],
|
||||
pred: List[str],
|
||||
ignore: Optional[Sequence[str]] = None,
|
||||
) -> float:
|
||||
"""
|
||||
Calculate token-level accuracy, in the range of 0~100.
|
||||
If gold and pred are not the same length, the longer one would be truncated.
|
||||
|
||||
:param gold: list of gold tokens
|
||||
:param pred: list of predicted tokens
|
||||
:param ignore: list of (gold) tokens to ignore
|
||||
:return: accuracy
|
||||
"""
|
||||
if len(pred) == 0 or len(gold) == 0:
|
||||
return 0.0
|
||||
if ignore is None:
|
||||
ignore = []
|
||||
i = 0
|
||||
total = 0
|
||||
match = 0
|
||||
while i < len(gold) and i < len(pred):
|
||||
if gold[i] in ignore:
|
||||
i += 1
|
||||
continue
|
||||
total += 1
|
||||
if gold[i] == pred[i]:
|
||||
match += 1
|
||||
i += 1
|
||||
|
||||
if total == 0:
|
||||
return 0.0
|
||||
return 100.0 * match / total
|
||||
|
||||
|
||||
def batch_accuracy(
|
||||
golds: List[List[str]],
|
||||
preds: List[List[str]],
|
||||
ignore: Optional[Sequence[str]] = None,
|
||||
) -> List[float]:
|
||||
"""
|
||||
Calculate token-level accuracy for a batch of sentences.
|
||||
|
||||
:param golds: list of gold sentences
|
||||
:param preds: list of predicted sentences
|
||||
:param ignore: list of (gold) tokens to ignore
|
||||
:return: list of accuracy
|
||||
"""
|
||||
if len(golds) != len(preds):
|
||||
raise ValueError("golds and preds must have the same length")
|
||||
return [accuracy(gold, pred, ignore) for gold, pred in zip(golds, preds)]
|
||||
|
||||
|
||||
def first_match_to_topk(
|
||||
first_match_list: List[int], k_values: List[int]
|
||||
) -> Dict[int, List[float]]:
|
||||
"""
|
||||
Calculate top-k accuracy with the first match ranks (1-indexed).
|
||||
|
||||
:param first_match: first match ranks (1-indexed)
|
||||
:param k_values: k values to consider
|
||||
:return: a mapping from k to top-k accuracies (ranging from 0~100)
|
||||
"""
|
||||
return {k: [100.0 if x <= k else 0.0 for x in first_match_list] for k in k_values}
|
||||
|
||||
|
||||
def pass_at_k(n: int, c: int, k: int) -> float:
|
||||
"""
|
||||
Sample pass@k metric according to the Codex paper, but in the scale of 0~100.
|
||||
:param n: total number of samples
|
||||
:param c: number of correct samples
|
||||
:param k: k in pass@$k$
|
||||
"""
|
||||
if n < k or (n - c) < k:
|
||||
# fallback to the (1 - (1-p)^k) formula
|
||||
return (1 - (1 - (c / n)) ** k) * 100
|
||||
else:
|
||||
return (1.0 - np.prod(1.0 - k / np.arange(n - c + 1, n + 1)).item()) * 100
|
||||
|
||||
|
||||
def self_bleu(samples: List[List[str]]) -> float:
|
||||
"""
|
||||
Calculate self-BLEU among the samples.
|
||||
:param samples: the chosen m samples
|
||||
:return: self-BLEU
|
||||
"""
|
||||
if len(samples) == 0:
|
||||
return 100.0
|
||||
|
||||
scores = []
|
||||
for i in range(len(samples)):
|
||||
scores.append(
|
||||
100.0
|
||||
* nltk.translate.bleu_score.sentence_bleu(
|
||||
[samples[j] for j in range(len(samples)) if j != i],
|
||||
samples[i],
|
||||
smoothing_function=nltk.translate.bleu_score.SmoothingFunction().method2,
|
||||
auto_reweigh=True,
|
||||
)
|
||||
)
|
||||
return np.mean(scores).item()
|
||||
|
||||
|
||||
def self_edit_distance(samples: List[Union[str, List[str]]], sep=" ") -> float:
|
||||
"""
|
||||
Calculate self-edit-distance among the samples.
|
||||
:param samples: the chosen m samples
|
||||
:param sep: the separator between tokens
|
||||
:return: self-edit-distance
|
||||
"""
|
||||
if len(samples) == 0:
|
||||
return 0.0
|
||||
|
||||
scores = []
|
||||
for i in range(len(samples)):
|
||||
sample_i = samples[i]
|
||||
if not isinstance(sample_i, str):
|
||||
sample_i = sep.join(sample_i)
|
||||
for j in range(len(samples)):
|
||||
if i == j:
|
||||
continue
|
||||
sample_j = samples[j]
|
||||
if not isinstance(sample_j, str):
|
||||
sample_j = sep.join(sample_j)
|
||||
|
||||
scores.append(100 - fuzz.ratio(sample_i, sample_j))
|
||||
return np.mean(scores).item()
|
||||
|
||||
|
||||
|
||||
QUALITY_METRICS: Dict[str, Callable[[List[str], List[str]], float]] = {
|
||||
"bleu": bleu,
|
||||
"xmatch": exact_match,
|
||||
"edit-sim": edit_sim,
|
||||
"rouge-f": lambda g, p: rouge_l(g, p)["f"],
|
||||
"rouge-p": lambda g, p: rouge_l(g, p)["p"],
|
||||
"rouge-r": lambda g, p: rouge_l(g, p)["r"],
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
CODEACT_TESTGEN_PROMPT_OLD = """Your goal is to generate a high-quality test suite (at least 20+ passing tests) for the code file: {code_file}. Output the test suite at {test_file}\n'
|
||||
|
||||
[current directory: /workspace/{workspace_dir_name}]
|
||||
|
||||
IMPORTANT: You should ONLY interact with the environment provided to you AND NEVER ASK FOR HUMAN HELP
|
||||
|
||||
IMPORTANT: Follow instructions, if you have < 80 tests you should generate more tests rather than trying to fix the ones you have.
|
||||
|
||||
IMPORTANT: Code file to test:
|
||||
```python
|
||||
{code_src}
|
||||
```
|
||||
|
||||
Here are additional imports that you may need:
|
||||
{imports}
|
||||
|
||||
Look at code dependencies (NOT {code_file} since you already have contents) and test files you need context for to write a complete test suite.
|
||||
|
||||
Aim for 20+ test functions with asserts. Do not hestitate to use the Python interpreter to understand the input output behavior of the code you are testing.
|
||||
|
||||
Output your test suite at {test_file}. Each unit test must be a function starting with test_. Include all your test imports and setup before your first test. Do not include a main method to run the tests. Make sure to make it as comprehensive as possible, try to execute all the methods you saw.
|
||||
|
||||
When you think you've successfully generated a test suite, run it on for the current project using {coverage_command}.
|
||||
|
||||
If you have few tests GENERATE MORE TESTS rather than trying to fix the ones you have (it is possible to filter out failing tests later).
|
||||
|
||||
Then run coverage report -m --include {code_file} to see how well your test suite covers the code under test.
|
||||
|
||||
When you are trying to improve coverage pick a part of the code that is not covered (indicated by lines on coverage report), examine the code and then
|
||||
try to generate a test for it. Feel free to use a code interpreter to understand the input output behavior. ONLY add tests
|
||||
not remove them.
|
||||
|
||||
If you are unable to see passing and failing tests, FIX YOUR IMPORTS to use the same style as other test files.
|
||||
|
||||
You should NOT modify any existing test case files. You SHOULD add new test in a NEW file to reproduce the issue.
|
||||
|
||||
You should NEVER use web browsing or any other web-based tools.
|
||||
|
||||
You should NEVER install new packages, use existing packages only.
|
||||
|
||||
You should ALWAYS use the default Python interpreter available in the <execute_bash> environment to run code related to the provided issue and/or repository.
|
||||
|
||||
You should ALWAYS use local imports DO NOT import the general library.
|
||||
|
||||
When you think you have a fully adequate test suite, please run the following command: <execute_bash> exit </execute_bash>.
|
||||
"""
|
||||
|
||||
CODEACT_TESTGEN_PROMPT = """
|
||||
Your goal is to generate a comprehensive, **broad-coverage** test suite for the code below, ensuring you test as many lines and branches as possible on the first attempt.
|
||||
|
||||
Place your test suite in a new file named {test_file}.
|
||||
|
||||
IMPORTANT REQUIREMENTS:
|
||||
1. **No external help or resources**—use only the snippet below.
|
||||
2. **Focus on breadth over depth**: cover all major functions, classes, and code paths early to minimize coverage iterations.
|
||||
3. Each test function must start with `test_` and use `assert` to verify behavior.
|
||||
4. Include only necessary imports (standard library or local).
|
||||
5. Do **not** modify existing test files—create a brand new one. No `main()` or other non-test code.
|
||||
6. Produce **at least 20 test functions**; if coverage is lacking, add more tests rather than removing or changing existing ones.
|
||||
7. Use the following commands to check coverage:
|
||||
<execute_bash> {coverage_command} </execute_bash>
|
||||
<execute_bash> coverage report -m --include {code_file} </execute_bash>
|
||||
If lines remain uncovered, add new tests targeting them specifically.
|
||||
8. When you're satisfied with coverage, finalize by running:
|
||||
<execute_bash> exit </execute_bash>
|
||||
|
||||
Below is the **complete code snippet** to test:
|
||||
|
||||
<START_OF_CODE>
|
||||
{code_src}
|
||||
<END_OF_CODE>
|
||||
|
||||
NOTE: if you are testing django, you must use from django.test import SimpleTestCase and class based tests (i.e. class TestSomething(SimpleTestCase)).
|
||||
NOTE: if there is an error executing tests you MUST fix it before exiting. DO NOT install new packages.
|
||||
NOTE: if outputting a revised test suite REPLACE {test_file} with the revised suite
|
||||
|
||||
**Output the final test suite** (20+ tests) for {test_file} in a single code block, no extra commentary. MAKE SURE you run the tests and ensure you can see which tests passed and failed BEFORE exiting.
|
||||
"""
|
||||
|
||||
CODEACT_TESTGEN_PROMPT_ITERATE = """
|
||||
Your goal is to improve the test suite at {test_file} to achieve **broad-coverage** of the code below.
|
||||
|
||||
First run the test suite.
|
||||
|
||||
If no tests run, then remove {test_file} and create {test_file} with a new suite.
|
||||
|
||||
Otherwise, improve it aiming to improve code coverage.
|
||||
|
||||
IMPORTANT REQUIREMENTS:
|
||||
1. Use the following commands to check coverage (RUN THIS FIRST):
|
||||
<execute_bash> {coverage_command} </execute_bash>
|
||||
<execute_bash> coverage report -m --include {code_file} </execute_bash>
|
||||
If lines remain uncovered, add new tests targeting them specifically.
|
||||
2. **No external help or resources**—use only the snippet below.
|
||||
3. **Focus on breadth over depth**: cover all major functions, classes, and code paths early to minimize coverage iterations.
|
||||
4. Each test function must use `assert` to verify behavior.
|
||||
5. Include only necessary imports (standard library or local).
|
||||
6. Do **not** modify other test files in the repository. No `main()` or other non-test code.
|
||||
7. Produce **at least 20 test functions**; if coverage is lacking, add more tests rather than removing or changing existing ones.
|
||||
8. When you're satisfied with coverage, finalize by running:
|
||||
<execute_bash> exit </execute_bash>
|
||||
|
||||
Below is the **complete code snippet** to test:
|
||||
|
||||
<START_OF_CODE>
|
||||
{code_src}
|
||||
<END_OF_CODE>
|
||||
|
||||
NOTE: if you are testing django, you must use from django.test import SimpleTestCase and class based tests (i.e. class TestSomething(SimpleTestCase)).
|
||||
NOTE: if there is an error executing tests you MUST fix it before exiting. DO NOT install new packages.
|
||||
NOTE: if outputting a revised test suite REPLACE {test_file} with the revised suite
|
||||
|
||||
**Output the final test suite** (20+ tests) for {test_file} in a single code block, no extra commentary. MAKE SURE you run the tests and ensure you can see which tests passed and failed BEFORE exiting.
|
||||
"""
|
||||
@@ -1,31 +0,0 @@
|
||||
import re
|
||||
from pygments.lexers.python import PythonLexer
|
||||
|
||||
def tokenize_code(code):
|
||||
lexer = PythonLexer()
|
||||
tokens = process_pygments_tokens(lexer.get_tokens(code))
|
||||
return tokens
|
||||
|
||||
def process_pygments_tokens(tokens):
|
||||
new_tokens = []
|
||||
|
||||
for token in tokens:
|
||||
if str(token[0]) == "Token.Text" and re.match(r'\s+', token[1]) or str(token[0]) == "Token.Text.Whitespace":
|
||||
continue
|
||||
new_tokens.append(token[1])
|
||||
|
||||
new_tokens_final = []
|
||||
i = 0
|
||||
while i < len(new_tokens)-2:
|
||||
if new_tokens[i] == '"' and new_tokens[i+1]=='STR' and new_tokens[i+2] == '"':
|
||||
new_tokens_final.append("\"STR\"")
|
||||
i = i + 3
|
||||
else:
|
||||
new_tokens_final.append(new_tokens[i])
|
||||
i = i + 1
|
||||
|
||||
for i in range(len(new_tokens)-2, len(new_tokens)):
|
||||
if i >= 0:
|
||||
new_tokens_final.append(new_tokens[i])
|
||||
|
||||
return new_tokens_final
|
||||
@@ -1,58 +0,0 @@
|
||||
import json
|
||||
import re
|
||||
|
||||
|
||||
def check_coverage(coverage_output, code_file):
|
||||
json_cov = json.loads(coverage_output)
|
||||
if code_file in json_cov['files'].keys():
|
||||
file_data = json_cov['files'][code_file]
|
||||
return True, file_data['summary']['percent_covered']
|
||||
|
||||
return False, 0
|
||||
|
||||
|
||||
def check_mutation(mutation_output):
|
||||
if 'total jobs: ' in mutation_output:
|
||||
num_mutants = int(mutation_output.split('total jobs: ')[1].split('\n')[0])
|
||||
final_conf = mutation_output.split('\n')[-1]
|
||||
if len(final_conf.strip().split(' ')) == 3:
|
||||
low, val, high = final_conf.split(' ')
|
||||
low = float(low)
|
||||
val = float(val)
|
||||
high = float(high)
|
||||
|
||||
confidence_range = high - val
|
||||
mutation_score = 100 - val
|
||||
|
||||
return True, num_mutants, mutation_score, confidence_range
|
||||
|
||||
return False, -1, 0, -1
|
||||
|
||||
|
||||
def count_methods(code_str):
|
||||
"""
|
||||
Counts the number of methods/functions in a given string of code.
|
||||
|
||||
Args:
|
||||
code_str (str): A string containing code.
|
||||
|
||||
Returns:
|
||||
int: The number of methods/functions found.
|
||||
"""
|
||||
# Regular expression to find Python function definitions
|
||||
pattern = r'\bdef\b\s+\w+\s*\('
|
||||
matches = re.findall(pattern, code_str)
|
||||
return len(matches)
|
||||
|
||||
|
||||
def get_lines_of_code(code_str):
|
||||
"""
|
||||
Extracts lines of code from a given string.
|
||||
|
||||
Args:
|
||||
code_str (str): A string containing code.
|
||||
|
||||
Returns:
|
||||
list: A list of lines of code.
|
||||
"""
|
||||
return len(code_str.strip().split('\n'))
|
||||
@@ -1,578 +0,0 @@
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
import time
|
||||
import traceback
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import toml
|
||||
from datasets import load_dataset
|
||||
|
||||
import openhands.agenthub
|
||||
from evaluation.benchmarks.testgeneval.constants import MAP_REPO_VERSION_TO_SPECS
|
||||
from evaluation.benchmarks.testgeneval.prompt import (
|
||||
CODEACT_TESTGEN_PROMPT,
|
||||
CODEACT_TESTGEN_PROMPT_ITERATE,
|
||||
)
|
||||
from evaluation.benchmarks.testgeneval.utils import get_test_directives
|
||||
from evaluation.utils.shared import (
|
||||
EvalException,
|
||||
EvalMetadata,
|
||||
EvalOutput,
|
||||
assert_and_raise,
|
||||
codeact_user_response,
|
||||
get_metrics,
|
||||
is_fatal_evaluation_error,
|
||||
make_metadata,
|
||||
prepare_dataset,
|
||||
reset_logger_for_multiprocessing,
|
||||
run_evaluation,
|
||||
update_llm_config_for_completions_logging,
|
||||
)
|
||||
from openhands.controller.state.state import State
|
||||
from openhands.core.config import (
|
||||
AgentConfig,
|
||||
AppConfig,
|
||||
SandboxConfig,
|
||||
get_llm_config_arg,
|
||||
get_parser,
|
||||
)
|
||||
from openhands.core.logger import openhands_logger as logger
|
||||
from openhands.core.main import create_runtime, run_controller
|
||||
from openhands.events.action import CmdRunAction, MessageAction
|
||||
from openhands.events.observation import CmdOutputObservation, ErrorObservation
|
||||
from openhands.events.serialization.event import event_to_dict
|
||||
from openhands.runtime.base import Runtime
|
||||
from openhands.utils.async_utils import call_async_from_sync
|
||||
|
||||
RUN_WITH_BROWSING = os.environ.get('RUN_WITH_BROWSING', 'false').lower() == 'true'
|
||||
|
||||
AGENT_CLS_TO_FAKE_USER_RESPONSE_FN = {
|
||||
'CodeActAgent': codeact_user_response,
|
||||
}
|
||||
|
||||
|
||||
def _preprocess_instance(d):
|
||||
for key, value in d.items():
|
||||
if isinstance(value, np.ndarray):
|
||||
d[key] = value.tolist()
|
||||
return d
|
||||
|
||||
|
||||
def _get_swebench_workspace_dir_name(instance: pd.Series) -> str:
|
||||
return f'{instance.repo}__{instance.version}'.replace('/', '__')
|
||||
|
||||
|
||||
def get_instruction(instance: pd.Series, metadata: EvalMetadata):
|
||||
# workspace_dir_name = _get_swebench_workspace_dir_name(instance)
|
||||
# Prepare instruction
|
||||
coverage_command = ' '.join(
|
||||
[
|
||||
MAP_REPO_VERSION_TO_SPECS[instance['repo']][instance['version']][
|
||||
'test_cmd'
|
||||
],
|
||||
*get_test_directives(instance),
|
||||
]
|
||||
)
|
||||
|
||||
# Testing general agents
|
||||
prompt_to_use = (
|
||||
CODEACT_TESTGEN_PROMPT_ITERATE
|
||||
if instance['full_pred'] is not None
|
||||
else CODEACT_TESTGEN_PROMPT
|
||||
)
|
||||
instruction = prompt_to_use.format(
|
||||
code_file=os.path.join('/testbed', instance.code_file),
|
||||
test_file=os.path.join('/testbed', instance.test_file),
|
||||
coverage_command=coverage_command,
|
||||
code_src=instance['code_src'],
|
||||
imports='\n'.join(instance.local_imports),
|
||||
workspace_dir_name=_get_swebench_workspace_dir_name(instance),
|
||||
)
|
||||
|
||||
if RUN_WITH_BROWSING:
|
||||
instruction += (
|
||||
'<IMPORTANT!>\n'
|
||||
'You SHOULD NEVER attempt to browse the web. '
|
||||
'</IMPORTANT!>\n'
|
||||
)
|
||||
|
||||
return instruction
|
||||
|
||||
|
||||
# TODO: migrate all swe-bench docker to ghcr.io/openhands
|
||||
DOCKER_IMAGE_PREFIX = os.environ.get('EVAL_DOCKER_IMAGE_PREFIX', 'docker.io/kdjain/')
|
||||
logger.info(f'Using docker image prefix: {DOCKER_IMAGE_PREFIX}')
|
||||
|
||||
|
||||
def get_instance_docker_image(instance_id: str) -> str:
|
||||
image_name = 'sweb.eval.x86_64.' + instance_id
|
||||
image_name = image_name.replace(
|
||||
'__', '_s_'
|
||||
) # to comply with docker image naming convention
|
||||
return DOCKER_IMAGE_PREFIX.rstrip('/') + '/' + image_name
|
||||
|
||||
|
||||
def get_config(
|
||||
instance: pd.Series,
|
||||
metadata: EvalMetadata,
|
||||
) -> AppConfig:
|
||||
# We use a different instance image for the each instance of TestGenEval
|
||||
base_container_image = get_instance_docker_image(instance['instance_id_swebench'])
|
||||
logger.info(
|
||||
f'Using instance container image: {base_container_image}. '
|
||||
f'Please make sure this image exists. '
|
||||
f'Submit an issue on https://github.com/All-Hands-AI/OpenHands if you run into any issues.'
|
||||
)
|
||||
|
||||
config = AppConfig(
|
||||
default_agent=metadata.agent_class,
|
||||
run_as_openhands=False,
|
||||
max_iterations=metadata.max_iterations,
|
||||
runtime=os.environ.get('RUNTIME', 'eventstream'),
|
||||
sandbox=SandboxConfig(
|
||||
base_container_image=base_container_image,
|
||||
enable_auto_lint=True,
|
||||
use_host_network=False,
|
||||
# large enough timeout, since some testcases take very long to run
|
||||
timeout=300,
|
||||
# Add platform to the sandbox config to solve issue 4401
|
||||
platform='linux/amd64',
|
||||
api_key=os.environ.get('ALLHANDS_API_KEY', None),
|
||||
remote_runtime_api_url=os.environ.get(
|
||||
'SANDBOX_REMOTE_RUNTIME_API_URL', 'http://localhost:8000'
|
||||
),
|
||||
keep_runtime_alive=False,
|
||||
remote_runtime_init_timeout=3600,
|
||||
),
|
||||
# do not mount workspace
|
||||
workspace_base=None,
|
||||
workspace_mount_path=None,
|
||||
)
|
||||
config.set_llm_config(
|
||||
update_llm_config_for_completions_logging(
|
||||
metadata.llm_config, metadata.eval_output_dir, instance['id']
|
||||
)
|
||||
)
|
||||
agent_config = AgentConfig(
|
||||
codeact_enable_jupyter=False,
|
||||
codeact_enable_browsing=RUN_WITH_BROWSING,
|
||||
codeact_enable_llm_editor=False,
|
||||
condenser=metadata.condenser_config,
|
||||
enable_prompt_extensions=False,
|
||||
)
|
||||
config.set_agent_config(agent_config)
|
||||
return config
|
||||
|
||||
|
||||
def initialize_runtime(
|
||||
runtime: Runtime,
|
||||
instance: pd.Series, # this argument is not required
|
||||
):
|
||||
"""Initialize the runtime for the agent.
|
||||
|
||||
This function is called before the runtime is used to run the agent.
|
||||
"""
|
||||
logger.info('-' * 30)
|
||||
logger.info('BEGIN Runtime Initialization Fn')
|
||||
logger.info('-' * 30)
|
||||
workspace_dir_name = _get_swebench_workspace_dir_name(instance)
|
||||
obs: CmdOutputObservation
|
||||
|
||||
instance['instance_id'] = instance['instance_id_swebench']
|
||||
|
||||
# Set instance id
|
||||
action = CmdRunAction(
|
||||
command=f"""echo 'export SWE_INSTANCE_ID={instance['instance_id_swebench']}' >> ~/.bashrc && echo 'export PIP_CACHE_DIR=~/.cache/pip' >> ~/.bashrc && echo "alias git='git --no-pager'" >> ~/.bashrc"""
|
||||
)
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0, f'Failed to export SWE_INSTANCE_ID: {str(obs)}'
|
||||
)
|
||||
|
||||
action = CmdRunAction(command="""export USER=$(whoami); echo USER=${USER} """)
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(obs.exit_code == 0, f'Failed to export USER: {str(obs)}')
|
||||
|
||||
# inject the init script
|
||||
script_dir = os.path.dirname(__file__)
|
||||
|
||||
# inject the instance info
|
||||
action = CmdRunAction(command='mkdir -p /swe_util/eval_data/instances')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0,
|
||||
f'Failed to create /swe_util/eval_data/instances: {str(obs)}',
|
||||
)
|
||||
|
||||
swe_instance_json_name = 'swe-bench-instance.json'
|
||||
swe_prediction = 'test_suite.py'
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
# Construct the full path for the desired file name within the temporary directory
|
||||
temp_file_path = os.path.join(temp_dir, swe_instance_json_name)
|
||||
# Write to the file with the desired name within the temporary directory
|
||||
with open(temp_file_path, 'w') as f:
|
||||
if not isinstance(instance, dict):
|
||||
preprocessed_instance = _preprocess_instance(instance.to_dict())
|
||||
json.dump([preprocessed_instance], f)
|
||||
else:
|
||||
preprocessed_instance = _preprocess_instance(instance)
|
||||
json.dump([preprocessed_instance], f)
|
||||
|
||||
# Copy the file to the desired location
|
||||
runtime.copy_to(temp_file_path, '/swe_util/eval_data/instances/')
|
||||
|
||||
if instance['full_pred'] is not None:
|
||||
temp_file_path_pred = os.path.join(temp_dir, swe_prediction)
|
||||
with open(temp_file_path_pred, 'w') as f:
|
||||
f.write(instance['full_pred'])
|
||||
|
||||
runtime.copy_to(temp_file_path_pred, '/tmp')
|
||||
|
||||
# Copy the file to the desired location
|
||||
action = CmdRunAction(
|
||||
command=f"cp /tmp/test_suite.py /testbed/{instance['test_file']}"
|
||||
)
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0, f'Failed to copy test file: {str(obs)}'
|
||||
)
|
||||
|
||||
action = CmdRunAction(
|
||||
command='git -C /testbed add . && git -C /testbed commit -m "Add test file"'
|
||||
)
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(obs.exit_code == 0, f'Failed to cat ~/.bashrc: {str(obs)}')
|
||||
|
||||
# inject the instance swe entry
|
||||
runtime.copy_to(
|
||||
str(os.path.join(script_dir, 'scripts/setup/instance_swe_entry.sh')),
|
||||
'/swe_util/',
|
||||
)
|
||||
action = CmdRunAction(command='cat ~/.bashrc')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(obs.exit_code == 0, f'Failed to cat ~/.bashrc: {str(obs)}')
|
||||
|
||||
action = CmdRunAction(command='source ~/.bashrc')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
if isinstance(obs, ErrorObservation):
|
||||
logger.error(f'Failed to source ~/.bashrc: {str(obs)}')
|
||||
assert_and_raise(obs.exit_code == 0, f'Failed to source ~/.bashrc: {str(obs)}')
|
||||
|
||||
action = CmdRunAction(command='source /swe_util/instance_swe_entry.sh')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0,
|
||||
f'Failed to source /swe_util/instance_swe_entry.sh: {str(obs)}',
|
||||
)
|
||||
|
||||
action = CmdRunAction(command=f'cd /workspace/{workspace_dir_name}')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0,
|
||||
f'Failed to cd to /workspace/{workspace_dir_name}: {str(obs)}',
|
||||
)
|
||||
|
||||
action = CmdRunAction(command='git reset --hard')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(obs.exit_code == 0, f'Failed to git reset --hard: {str(obs)}')
|
||||
|
||||
action = CmdRunAction(
|
||||
command='for remote_name in $(git remote); do git remote remove "${remote_name}"; done'
|
||||
)
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(obs.exit_code == 0, f'Failed to remove git remotes: {str(obs)}')
|
||||
|
||||
logger.info('-' * 30)
|
||||
logger.info('END Runtime Initialization Fn')
|
||||
logger.info('-' * 30)
|
||||
|
||||
|
||||
def complete_runtime(
|
||||
runtime: Runtime,
|
||||
instance: pd.Series, # this argument is not required, but it is used to get the workspace_dir_name
|
||||
) -> dict[str, Any]:
|
||||
"""Complete the runtime for the agent.
|
||||
|
||||
This function is called before the runtime is used to run the agent.
|
||||
If you need to do something in the sandbox to get the correctness metric after
|
||||
the agent has run, modify this function.
|
||||
"""
|
||||
try:
|
||||
logger.info('-' * 30)
|
||||
logger.info('BEGIN Runtime Completion Fn')
|
||||
logger.info('-' * 30)
|
||||
obs: CmdOutputObservation
|
||||
workspace_dir_name = _get_swebench_workspace_dir_name(instance)
|
||||
|
||||
action = CmdRunAction(command=f'cd /workspace/{workspace_dir_name}')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0,
|
||||
f'Failed to cd to /workspace/{workspace_dir_name}: {str(obs)}',
|
||||
)
|
||||
|
||||
action = CmdRunAction(command=f'cat {instance.test_file}')
|
||||
action.set_hard_timeout(600)
|
||||
logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
obs = runtime.run_action(action)
|
||||
logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
assert_and_raise(
|
||||
obs.exit_code == 0,
|
||||
f'Failed to find file: {instance.test_file} in /workspace/{workspace_dir_name}',
|
||||
)
|
||||
|
||||
test_suite = obs.content.strip()
|
||||
except Exception:
|
||||
# Print stack trace
|
||||
print('Skipping, exception in complete_runtime')
|
||||
print(traceback.format_exc())
|
||||
test_suite = instance['full_pred'] if instance['full_pred'] is not None else ''
|
||||
|
||||
# action = CmdRunAction(command='git add -A')
|
||||
# action.set_hard_timeout(600)
|
||||
# logger.info(action, extra={'msg_type': 'ACTION'})
|
||||
# obs = runtime.run_action(action)
|
||||
# logger.info(obs, extra={'msg_type': 'OBSERVATION'})
|
||||
# assert_and_raise(obs.exit_code == 0, f'Failed to git add -A: {str(obs)}')
|
||||
|
||||
logger.info('-' * 30)
|
||||
logger.info('END Runtime Completion Fn')
|
||||
logger.info('-' * 30)
|
||||
return {
|
||||
'test_suite': test_suite,
|
||||
}
|
||||
|
||||
|
||||
def process_instance(
|
||||
instance: pd.Series,
|
||||
metadata: EvalMetadata,
|
||||
reset_logger: bool = True,
|
||||
) -> EvalOutput:
|
||||
config = get_config(instance, metadata)
|
||||
start_time = time.time() # Track start time
|
||||
|
||||
# Setup the logger properly, so you can run multi-processing to parallelize the evaluation
|
||||
if reset_logger:
|
||||
log_dir = os.path.join(metadata.eval_output_dir, 'infer_logs')
|
||||
reset_logger_for_multiprocessing(logger, instance.id, log_dir)
|
||||
else:
|
||||
logger.info(f'Starting evaluation for instance {instance.id}.')
|
||||
|
||||
runtime = create_runtime(config)
|
||||
call_async_from_sync(runtime.connect)
|
||||
|
||||
try:
|
||||
initialize_runtime(runtime, instance)
|
||||
|
||||
instruction = get_instruction(instance, metadata)
|
||||
|
||||
# Here's how you can run the agent (similar to the `main` function) and get the final task state
|
||||
state: State | None = asyncio.run(
|
||||
run_controller(
|
||||
config=config,
|
||||
initial_user_action=MessageAction(content=instruction),
|
||||
runtime=runtime,
|
||||
fake_user_response_fn=AGENT_CLS_TO_FAKE_USER_RESPONSE_FN[
|
||||
metadata.agent_class
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
# if fatal error, throw EvalError to trigger re-run
|
||||
if is_fatal_evaluation_error(state.last_error):
|
||||
raise EvalException('Fatal error detected: ' + state.last_error)
|
||||
|
||||
# ======= THIS IS SWE-Bench specific =======
|
||||
return_val = complete_runtime(runtime, instance)
|
||||
test_suite = return_val['test_suite']
|
||||
logger.info(
|
||||
f'Got test suite for instance {instance.instance_id}:\n--------\n{test_suite}\n--------'
|
||||
)
|
||||
finally:
|
||||
runtime.close()
|
||||
|
||||
end_time = time.time()
|
||||
elapsed_time = end_time - start_time
|
||||
logger.info(
|
||||
f'Evaluation for instance {instance.instance_id} took {elapsed_time:.2f} seconds.'
|
||||
)
|
||||
|
||||
# ==========================================
|
||||
|
||||
# ======= Attempt to evaluate the agent's edits =======
|
||||
# we use eval_infer.sh to evaluate the agent's edits, not here
|
||||
# because the agent may alter the environment / testcases
|
||||
test_result = {
|
||||
'test_suite': test_suite,
|
||||
'elapsed_time': elapsed_time,
|
||||
}
|
||||
|
||||
# If you are working on some simpler benchmark that only evaluates the final model output (e.g., in a MessageAction)
|
||||
# You can simply get the LAST `MessageAction` from the returned `state.history` and parse it for evaluation.
|
||||
if state is None:
|
||||
raise ValueError('State should not be None.')
|
||||
|
||||
histories = [event_to_dict(event) for event in state.history]
|
||||
metrics = get_metrics(state)
|
||||
|
||||
# Save the output
|
||||
output = EvalOutput(
|
||||
instance_id=instance.id,
|
||||
instruction=instruction,
|
||||
instance=_preprocess_instance(instance.to_dict()), # SWE Bench specific
|
||||
test_result=test_result,
|
||||
metadata=metadata,
|
||||
history=histories,
|
||||
metrics=metrics,
|
||||
error=state.last_error if state and state.last_error else None,
|
||||
)
|
||||
# print(output)
|
||||
return output
|
||||
|
||||
|
||||
def prepare_dataset_pre(dataset: pd.DataFrame, filter_column: str) -> pd.DataFrame:
|
||||
file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'config.toml')
|
||||
if os.path.exists(file_path):
|
||||
with open(file_path, 'r') as file:
|
||||
data = toml.load(file)
|
||||
if 'selected_ids' in data:
|
||||
selected_ids = data['selected_ids']
|
||||
logger.info(
|
||||
f'Filtering {len(selected_ids)} tasks from "selected_ids"...'
|
||||
)
|
||||
subset = dataset[dataset[filter_column].isin(selected_ids)]
|
||||
logger.info(f'Retained {subset.shape[0]} tasks after filtering')
|
||||
|
||||
subset['instance_id_swebench'] = subset['instance_id']
|
||||
subset['instance_id'] = subset['id']
|
||||
return subset
|
||||
|
||||
dataset['instance_id_swebench'] = dataset['instance_id']
|
||||
dataset['instance_id'] = dataset['id']
|
||||
return dataset
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = get_parser()
|
||||
parser.add_argument(
|
||||
'--dataset',
|
||||
type=str,
|
||||
default='kjain/testgenevallite',
|
||||
help='data set to evaluate on, either full-test or lite-test',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--split',
|
||||
type=str,
|
||||
default='test',
|
||||
help='split to evaluate on',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--testfile_start',
|
||||
action='store_true',
|
||||
help='Whether to start from the 0 shot test file',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'--zero_shot_path',
|
||||
type=str,
|
||||
help='Path to the zero shot test file predictions',
|
||||
)
|
||||
args, _ = parser.parse_known_args()
|
||||
|
||||
if args.testfile_start and not args.zero_shot_path:
|
||||
raise ValueError(
|
||||
'If you want to start from the 0 shot test file, you must provide the path to the zero shot test file predictions'
|
||||
)
|
||||
|
||||
preds_map = {}
|
||||
if args.testfile_start:
|
||||
with open(args.zero_shot_path, 'r') as f:
|
||||
for line in f:
|
||||
pred = json.loads(line)
|
||||
preds_map[pred['id']] = pred['preds']['full'][0]
|
||||
|
||||
# NOTE: It is preferable to load datasets from huggingface datasets and perform post-processing
|
||||
# so we don't need to manage file uploading to OpenHands's repo
|
||||
dataset = load_dataset(args.dataset, split=args.split)
|
||||
logger.info(f'Loaded dataset {args.dataset} with split {args.split}')
|
||||
testgeneval_filepairs = prepare_dataset_pre(dataset.to_pandas(), 'id')
|
||||
|
||||
llm_config = None
|
||||
if args.llm_config:
|
||||
llm_config = get_llm_config_arg(args.llm_config)
|
||||
llm_config.log_completions = True
|
||||
# modify_params must be False for evaluation purpose, for reproducibility and accurancy of results
|
||||
llm_config.modify_params = False
|
||||
|
||||
if llm_config is None:
|
||||
raise ValueError(f'Could not find LLM config: --llm_config {args.llm_config}')
|
||||
|
||||
details = {}
|
||||
_agent_cls = openhands.agenthub.Agent.get_cls(args.agent_cls)
|
||||
|
||||
dataset_descrption = (
|
||||
args.dataset.replace('/', '__') + '-' + args.split.replace('/', '__')
|
||||
)
|
||||
metadata = make_metadata(
|
||||
llm_config,
|
||||
dataset_descrption,
|
||||
args.agent_cls,
|
||||
args.max_iterations,
|
||||
args.eval_note,
|
||||
args.eval_output_dir,
|
||||
details=details,
|
||||
)
|
||||
|
||||
output_file = os.path.join(metadata.eval_output_dir, 'output.jsonl')
|
||||
instances = prepare_dataset(testgeneval_filepairs, output_file, args.eval_n_limit)
|
||||
|
||||
if not instances.empty:
|
||||
instances['full_pred'] = (
|
||||
instances['instance_id']
|
||||
.map(preds_map)
|
||||
.apply(lambda x: x if pd.notna(x) else None)
|
||||
)
|
||||
|
||||
run_evaluation(
|
||||
instances, metadata, output_file, args.eval_num_workers, process_instance
|
||||
)
|
||||
@@ -1,128 +0,0 @@
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from datasets import load_dataset
|
||||
|
||||
|
||||
# Function to run shell commands
|
||||
def run_command(command):
|
||||
try:
|
||||
subprocess.run(command, check=True, shell=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f'An error occurred: {e}')
|
||||
|
||||
|
||||
# Function to log in to Docker Hub
|
||||
def docker_login():
|
||||
print('Logging into Docker Hub...')
|
||||
run_command('docker login')
|
||||
|
||||
|
||||
# Function to generate Dockerfile content based on image type
|
||||
def generate_dockerfile_content(
|
||||
base_image, dependencies, datum, patch_path, test_patch_path
|
||||
):
|
||||
dockerfile_content = f"""
|
||||
FROM {base_image}
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
RUN source /opt/miniconda3/bin/activate && conda activate testbed && pip install {' '.join(dependencies)}
|
||||
COPY {patch_path} /app/patch.diff
|
||||
RUN git apply /app/patch.diff
|
||||
RUN rm /app/patch.diff
|
||||
COPY {test_patch_path} /app/patch.diff
|
||||
RUN git apply /app/patch.diff
|
||||
RUN git config --global user.email ""
|
||||
RUN git config --global user.name "TestGenEval"
|
||||
RUN rm /app/patch.diff
|
||||
RUN rm {datum['test_file']}
|
||||
"""
|
||||
|
||||
# Add specific content based on image type
|
||||
dockerfile_content += 'RUN git add .\nRUN git commit -m "Testing fixes"'
|
||||
|
||||
return dockerfile_content
|
||||
|
||||
|
||||
# Function to build, push, and clean up Docker images
|
||||
def build_and_push_image(dockerfile_content, image_name):
|
||||
with open('Dockerfile.temp', 'w') as dockerfile:
|
||||
dockerfile.write(dockerfile_content)
|
||||
run_command(f'docker build -f Dockerfile.temp -t {image_name} .')
|
||||
run_command(f'docker push {image_name}')
|
||||
run_command(f'docker rmi {image_name}')
|
||||
os.remove('Dockerfile.temp')
|
||||
|
||||
|
||||
# Function to process images with .eval in the name
|
||||
def process_images(dataset, original_namespace, new_namespace, start_instance_id):
|
||||
dependencies = ['coverage', 'cosmic-ray']
|
||||
|
||||
found_start = len(start_instance_id) == 0
|
||||
for datum in dataset:
|
||||
if not found_start and datum['instance_id'] == start_instance_id:
|
||||
found_start = True
|
||||
elif found_start:
|
||||
full_image_name = f'{original_namespace}/sweb.eval.x86_64.{datum["instance_id"].replace("__", "_s_")}:latest'
|
||||
print(f'Processing image: {full_image_name}')
|
||||
run_command(f'docker pull {full_image_name}')
|
||||
|
||||
# Save patches and preds_context to regular files
|
||||
patch_file_path = 'patch.diff'
|
||||
test_patch_file_path = 'test_patch.diff'
|
||||
|
||||
with open(patch_file_path, 'w') as patch_file, open(
|
||||
test_patch_file_path, 'w'
|
||||
) as test_patch_file:
|
||||
patch_file.write(datum['patch'])
|
||||
test_patch_file.write(datum['test_patch'])
|
||||
|
||||
# Define image types and corresponding tags
|
||||
new_image_name = f'{new_namespace}/sweb.eval.x86_64.{datum["instance_id"].replace("__", "_s_")}:latest'
|
||||
dockerfile_content = generate_dockerfile_content(
|
||||
full_image_name,
|
||||
dependencies,
|
||||
datum,
|
||||
patch_file_path,
|
||||
test_patch_file_path,
|
||||
)
|
||||
build_and_push_image(dockerfile_content, new_image_name)
|
||||
|
||||
# Cleanup regular files and images
|
||||
os.remove(patch_file_path)
|
||||
os.remove(test_patch_file_path)
|
||||
run_command(f'docker rmi {full_image_name}')
|
||||
run_command('docker system prune -f') # Clean up dangling resources
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Process Docker images with .eval in the name.'
|
||||
)
|
||||
parser.add_argument('--dataset', type=str, default='kjain14/testgeneval')
|
||||
parser.add_argument('--split', type=str, default='test')
|
||||
parser.add_argument(
|
||||
'--new_namespace',
|
||||
type=str,
|
||||
default='kdjain',
|
||||
help='The new Docker Hub namespace to push the images',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--original_namespace',
|
||||
type=str,
|
||||
default='xingyaoww',
|
||||
help='The original Docker Hub namespace',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--start_instance_id',
|
||||
type=str,
|
||||
default='',
|
||||
help='The instance_id to start processing from',
|
||||
)
|
||||
args = parser.parse_args()
|
||||
dataset = load_dataset(args.dataset)[args.split]
|
||||
|
||||
docker_login()
|
||||
process_images(
|
||||
dataset, args.original_namespace, args.new_namespace, args.start_instance_id
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,196 +0,0 @@
|
||||
sweb.base.x86_64:latest
|
||||
sweb.env.x86_64.088a7e628bda9770f9757b:latest
|
||||
sweb.env.x86_64.0d80c7dec81ee2f2f513e2:latest
|
||||
sweb.env.x86_64.0f99bce2750f3109957bec:latest
|
||||
sweb.env.x86_64.1b3b218535da0abf4469cb:latest
|
||||
sweb.env.x86_64.1c1a6945f732f9391228c5:latest
|
||||
sweb.env.x86_64.1f92e6d7cef88badc4f744:latest
|
||||
sweb.env.x86_64.27dd9791e13f5c857a09f9:latest
|
||||
sweb.env.x86_64.297af196949a2a635bce66:latest
|
||||
sweb.env.x86_64.2baaea72acc974f6c02079:latest
|
||||
sweb.env.x86_64.2e50125951bc69cddd7421:latest
|
||||
sweb.env.x86_64.2f217c8b4490bfa0e2ba14:latest
|
||||
sweb.env.x86_64.31244378a92e3bcce809ac:latest
|
||||
sweb.env.x86_64.428468730904ff6b4232aa:latest
|
||||
sweb.env.x86_64.5d1fda9d55d65d8a4e5bdb:latest
|
||||
sweb.env.x86_64.6b007979cf533f0f3016e8:latest
|
||||
sweb.env.x86_64.7037e8c448a4b8ebfe9b13:latest
|
||||
sweb.env.x86_64.71498c7426dbf05599642f:latest
|
||||
sweb.env.x86_64.756beac07713d7e8dc1129:latest
|
||||
sweb.env.x86_64.78278ae2cf880e395f1337:latest
|
||||
sweb.env.x86_64.8f1f7b974f0c57c7aeba39:latest
|
||||
sweb.env.x86_64.934a137824256b612e9dc5:latest
|
||||
sweb.env.x86_64.a0efca7a0fe6719dbf65c2:latest
|
||||
sweb.env.x86_64.a18371b03f944585b4f08c:latest
|
||||
sweb.env.x86_64.a33dddf55cdff5d8e23374:latest
|
||||
sweb.env.x86_64.aa92880033da20ca313928:latest
|
||||
sweb.env.x86_64.b649f0ff62fad147f7f073:latest
|
||||
sweb.env.x86_64.b7ce4be3b3c35f68c61248:latest
|
||||
sweb.env.x86_64.c70909fdac4897d1c685df:latest
|
||||
sweb.env.x86_64.c795f4b88616b8462021ed:latest
|
||||
sweb.env.x86_64.cc47cc71483942d0c3a15e:latest
|
||||
sweb.env.x86_64.dc5ff4c0e3fe8db5afc4da:latest
|
||||
sweb.env.x86_64.e3afd7f04b325a4de4982d:latest
|
||||
sweb.env.x86_64.e5bb89bf78258a7d14c34b:latest
|
||||
sweb.env.x86_64.e83e37f52c09532c62acfb:latest
|
||||
sweb.env.x86_64.efa6065ed5bf204410fd53:latest
|
||||
sweb.eval.x86_64.django_s_django-17087:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-10508:latest
|
||||
sweb.eval.x86_64.django_s_django-14017:latest
|
||||
sweb.eval.x86_64.django_s_django-11422:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-14774:latest
|
||||
sweb.eval.x86_64.django_s_django-14915:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-22005:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-5221:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-17022:latest
|
||||
sweb.eval.x86_64.django_s_django-15996:latest
|
||||
sweb.eval.x86_64.django_s_django-15252:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21171:latest
|
||||
sweb.eval.x86_64.django_s_django-11797:latest
|
||||
sweb.eval.x86_64.django_s_django-16046:latest
|
||||
sweb.eval.x86_64.django_s_django-11583:latest
|
||||
sweb.eval.x86_64.django_s_django-15738:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21612:latest
|
||||
sweb.eval.x86_64.astropy_s_astropy-12907:latest
|
||||
sweb.eval.x86_64.django_s_django-11620:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-16792:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13779:latest
|
||||
sweb.eval.x86_64.django_s_django-16041:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13471:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-20442:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-20049:latest
|
||||
sweb.eval.x86_64.django_s_django-14411:latest
|
||||
sweb.eval.x86_64.django_s_django-13447:latest
|
||||
sweb.eval.x86_64.django_s_django-12856:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-10949:latest
|
||||
sweb.eval.x86_64.django_s_django-14787:latest
|
||||
sweb.eval.x86_64.django_s_django-11815:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13584:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14087:latest
|
||||
sweb.eval.x86_64.django_s_django-15388:latest
|
||||
sweb.eval.x86_64.django_s_django-11179:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-24102:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-24213:latest
|
||||
sweb.eval.x86_64.django_s_django-15781:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-8906:latest
|
||||
sweb.eval.x86_64.django_s_django-13710:latest
|
||||
sweb.eval.x86_64.django_s_django-13925:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14092:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-7373:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-25498:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-5227:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-15678:latest
|
||||
sweb.eval.x86_64.django_s_django-13551:latest
|
||||
sweb.eval.x86_64.django_s_django-14155:latest
|
||||
sweb.eval.x86_64.django_s_django-13933:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21055:latest
|
||||
sweb.eval.x86_64.django_s_django-13660:latest
|
||||
sweb.eval.x86_64.django_s_django-16527:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-5692:latest
|
||||
sweb.eval.x86_64.mwaskom_s_seaborn-3010:latest
|
||||
sweb.eval.x86_64.django_s_django-12700:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-11400:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-23117:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-20639:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-23262:latest
|
||||
sweb.eval.x86_64.django_s_django-15498:latest
|
||||
sweb.eval.x86_64.django_s_django-12453:latest
|
||||
sweb.eval.x86_64.django_s_django-14999:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13480:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21847:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-15011:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25570:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-7975:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14983:latest
|
||||
sweb.eval.x86_64.django_s_django-14534:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-14396:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-25442:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-15535:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-22714:latest
|
||||
sweb.eval.x86_64.django_s_django-15789:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21627:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-24066:latest
|
||||
sweb.eval.x86_64.pylint-dev_s_pylint-7993:latest
|
||||
sweb.eval.x86_64.django_s_django-14752:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-18835:latest
|
||||
sweb.eval.x86_64.django_s_django-17051:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-12171:latest
|
||||
sweb.eval.x86_64.pydata_s_xarray-3364:latest
|
||||
sweb.eval.x86_64.mwaskom_s_seaborn-3190:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-7168:latest
|
||||
sweb.eval.x86_64.django_s_django-12747:latest
|
||||
sweb.eval.x86_64.django_s_django-15695:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-22835:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-12481:latest
|
||||
sweb.eval.x86_64.django_s_django-15851:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-14024:latest
|
||||
sweb.eval.x86_64.django_s_django-14608:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-9359:latest
|
||||
sweb.eval.x86_64.django_s_django-16873:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-25433:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13031:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-7432:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25747:latest
|
||||
sweb.eval.x86_64.django_s_django-12286:latest
|
||||
sweb.eval.x86_64.django_s_django-11910:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-12471:latest
|
||||
sweb.eval.x86_64.pylint-dev_s_pylint-5859:latest
|
||||
sweb.eval.x86_64.django_s_django-11133:latest
|
||||
sweb.eval.x86_64.astropy_s_astropy-14365:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13496:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-19487:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-13895:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-15345:latest
|
||||
sweb.eval.x86_64.django_s_django-13590:latest
|
||||
sweb.eval.x86_64.django_s_django-13757:latest
|
||||
sweb.eval.x86_64.django_s_django-16379:latest
|
||||
sweb.eval.x86_64.django_s_django-13768:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-8365:latest
|
||||
sweb.eval.x86_64.django_s_django-14580:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-20154:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-12419:latest
|
||||
sweb.eval.x86_64.django_s_django-12125:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-24152:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-15512:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-18621:latest
|
||||
sweb.eval.x86_64.pydata_s_xarray-4248:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-11040:latest
|
||||
sweb.eval.x86_64.django_s_django-11099:latest
|
||||
sweb.eval.x86_64.django_s_django-16816:latest
|
||||
sweb.eval.x86_64.django_s_django-13265:latest
|
||||
sweb.eval.x86_64.django_s_django-16139:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-10297:latest
|
||||
sweb.eval.x86_64.django_s_django-14016:latest
|
||||
sweb.eval.x86_64.pallets_s_flask-5063:latest
|
||||
sweb.eval.x86_64.astropy_s_astropy-7746:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-24265:latest
|
||||
sweb.eval.x86_64.django_s_django-13448:latest
|
||||
sweb.eval.x86_64.django_s_django-12908:latest
|
||||
sweb.eval.x86_64.sphinx-doc_s_sphinx-8627:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-14317:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-6116:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-23191:latest
|
||||
sweb.eval.x86_64.pydata_s_xarray-5131:latest
|
||||
sweb.eval.x86_64.django_s_django-11019:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-23913:latest
|
||||
sweb.eval.x86_64.django_s_django-15790:latest
|
||||
sweb.eval.x86_64.django_s_django-12497:latest
|
||||
sweb.eval.x86_64.matplotlib_s_matplotlib-26020:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25638:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-25500:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-19007:latest
|
||||
sweb.eval.x86_64.django_s_django-12308:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-7220:latest
|
||||
sweb.eval.x86_64.django_s_django-11848:latest
|
||||
sweb.eval.x86_64.django_s_django-15347:latest
|
||||
sweb.eval.x86_64.pytest-dev_s_pytest-7490:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-18532:latest
|
||||
sweb.eval.x86_64.django_s_django-14997:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-24909:latest
|
||||
sweb.eval.x86_64.django_s_django-13220:latest
|
||||
sweb.eval.x86_64.sympy_s_sympy-21614:latest
|
||||
sweb.eval.x86_64.django_s_django-15902:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13497:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-13439:latest
|
||||
sweb.eval.x86_64.scikit-learn_s_scikit-learn-14894:latest
|
||||
sweb.eval.x86_64.django_s_django-12983:latest
|
||||
@@ -1,31 +0,0 @@
|
||||
def print_diff_ignore_order(file1, file2):
|
||||
with open(file1, 'r') as f1, open(file2, 'r') as f2:
|
||||
file1_lines = set(f1.readlines())
|
||||
file2_lines = set(f2.readlines())
|
||||
|
||||
only_in_file1 = file1_lines - file2_lines
|
||||
only_in_file2 = file2_lines - file1_lines
|
||||
|
||||
if only_in_file1:
|
||||
print(f'Lines in {file1} but not in {file2}:')
|
||||
for line in sorted(only_in_file1):
|
||||
print(f'- {line.strip()}')
|
||||
|
||||
# if only_in_file2:
|
||||
# print(f"Lines in {file2} but not in {file1}:")
|
||||
# for line in sorted(only_in_file2):
|
||||
# print(f"+ {line.strip()}")
|
||||
|
||||
if not only_in_file1 and not only_in_file2:
|
||||
print('The files have the same content (ignoring line order).')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Usage
|
||||
lite1 = 'all-swebench-lite-instance-images.txt' # Replace with the path to your first file
|
||||
lite2 = '../../swe_bench/scripts/docker/all-swebench-lite-instance-images.txt' # Replace with the path to your second file
|
||||
print_diff_ignore_order(lite1, lite2)
|
||||
|
||||
full1 = 'all-swebench-full-instance-images.txt' # Replace with the path to your first file
|
||||
full2 = '../../swe_bench/scripts/docker/all-swebench-full-instance-images.txt' # Replace with the path to your second file
|
||||
print_diff_ignore_order(full1, full2)
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Script will delete all repositories and tags in your Docker Hub account
|
||||
set -e
|
||||
|
||||
# Set username and password from command-line arguments
|
||||
UNAME=$1
|
||||
UPASS=$2
|
||||
|
||||
# Get token to interact with Docker Hub
|
||||
TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'${UNAME}'", "password": "'${UPASS}'"}' https://hub.docker.com/v2/users/login/ | jq -r .token)
|
||||
|
||||
# Ensure token retrieval was successful
|
||||
if [[ -z "$TOKEN" ]]; then
|
||||
echo "Failed to obtain authentication token. Please check your credentials."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get list of repositories for that user account
|
||||
echo "Listing repositories in Docker Hub account '${UNAME}':"
|
||||
REPO_LIST=$(curl -s -H "Authorization: JWT ${TOKEN}" "https://hub.docker.com/v2/repositories/${UNAME}/?page_size=10000" | jq -r '.results|.[]|.name')
|
||||
if [[ -z "$REPO_LIST" ]]; then
|
||||
echo "No repositories found for user '${UNAME}' or failed to fetch repositories."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Loop through each repository and delete its tags and the repository itself
|
||||
for rep in ${REPO_LIST}; do
|
||||
echo "Processing repository: ${UNAME}/${rep}"
|
||||
|
||||
# Get all tags for the repository
|
||||
IMAGES=$(curl -s -H "Authorization: JWT ${TOKEN}" "https://hub.docker.com/v2/repositories/${UNAME}/${rep}/tags/?page_size=100")
|
||||
IMAGE_TAGS=$(echo $IMAGES | jq -r '.results|.[]|.name')
|
||||
|
||||
# Delete each tag
|
||||
for tag in ${IMAGE_TAGS}; do
|
||||
echo "Deleting tag: ${UNAME}/${rep}:${tag}"
|
||||
curl -s -X DELETE -H "Authorization: JWT ${TOKEN}" "https://hub.docker.com/v2/repositories/${UNAME}/${rep}/tags/${tag}/"
|
||||
done
|
||||
|
||||
# Delete the repository itself
|
||||
echo "Deleting repository: ${UNAME}/${rep}"
|
||||
curl -s -X DELETE -H "Authorization: JWT ${TOKEN}" "https://hub.docker.com/v2/repositories/${UNAME}/${rep}/" || {
|
||||
echo "Failed to delete repository '${UNAME}/${rep}'. Please check permissions or API limits."
|
||||
}
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "Script execution completed."
|
||||
@@ -1,18 +0,0 @@
|
||||
from datasets import load_dataset
|
||||
|
||||
|
||||
def dataset_to_txt(dataset, txt_file, split='test'):
|
||||
with open(txt_file, 'w') as f:
|
||||
for datum in dataset[split]:
|
||||
instance_id = datum['instance_id'].replace('__', '_s_')
|
||||
f.write(f'sweb.eval.x86_64.{instance_id}:latest\n')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# Load the private dataset
|
||||
dataset = load_dataset('kjain14/testgeneval')
|
||||
|
||||
dataset_lite = load_dataset('kjain14/testgenevallite')
|
||||
|
||||
dataset_to_txt(dataset_lite, 'all-swebench-lite-instance-images.txt', lite=True)
|
||||
dataset_to_txt(dataset, 'all-swebench-full-instance-images.txt')
|
||||
@@ -1,173 +0,0 @@
|
||||
import argparse
|
||||
import copy
|
||||
import difflib
|
||||
import json
|
||||
import os
|
||||
import traceback
|
||||
|
||||
|
||||
def insert_line_in_string(input_string, new_str, insert_line):
|
||||
"""
|
||||
Inserts a new line into a string at the specified line number.
|
||||
|
||||
:param input_string: The original string.
|
||||
:param new_str: The string to insert.
|
||||
:param insert_line: The line number at which to insert (1-based index).
|
||||
:return: The modified string.
|
||||
"""
|
||||
file_text = input_string.expandtabs()
|
||||
new_str = new_str.expandtabs()
|
||||
|
||||
file_text_lines = file_text.split('\n')
|
||||
|
||||
new_str_lines = new_str.split('\n')
|
||||
new_file_text_lines = (
|
||||
file_text_lines[:insert_line] + new_str_lines + file_text_lines[insert_line:]
|
||||
)
|
||||
|
||||
return '\n'.join(new_file_text_lines)
|
||||
|
||||
|
||||
def print_string_diff(original, modified):
|
||||
"""
|
||||
Prints the differences between two strings line by line.
|
||||
|
||||
:param original: The original string.
|
||||
:param modified: The modified string.
|
||||
"""
|
||||
original_lines = original.splitlines(keepends=True)
|
||||
modified_lines = modified.splitlines(keepends=True)
|
||||
|
||||
diff = difflib.unified_diff(
|
||||
original_lines,
|
||||
modified_lines,
|
||||
fromfile='original',
|
||||
tofile='modified',
|
||||
lineterm='',
|
||||
)
|
||||
|
||||
print(''.join(diff))
|
||||
|
||||
|
||||
def parse_json_files(root_dir, output_dir, metadata_objs, preds_objs):
|
||||
final_output = {i: [] for i in range(25)}
|
||||
|
||||
for subdir in sorted(os.listdir(root_dir)): # Sorting ensures consistent order
|
||||
subdir_path = os.path.join(root_dir, subdir)
|
||||
# subdir_instance = subdir.rsplit('-', 1)[0]
|
||||
metadata = metadata_objs[subdir]
|
||||
orig_test_suite = metadata['test_result']['test_suite']
|
||||
|
||||
if os.path.isdir(subdir_path): # Check if it's a directory
|
||||
print(f'Processing subdirectory: {subdir}')
|
||||
|
||||
# Now loop through the JSON files in this subdirectory
|
||||
i = 0
|
||||
test_suite = preds_objs[subdir] if subdir in preds_objs else ''
|
||||
for file in sorted(
|
||||
os.listdir(subdir_path)
|
||||
): # Sorting ensures consistent order
|
||||
metadata_copy = copy.deepcopy(metadata)
|
||||
if file.endswith('.json'): # Check for JSON files
|
||||
file_path = os.path.join(subdir_path, file)
|
||||
try:
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f) # Load JSON data
|
||||
try:
|
||||
tool_calls = data['response']['choices'][0]['message'][
|
||||
'tool_calls'
|
||||
]
|
||||
if tool_calls is not None:
|
||||
for tool_call in tool_calls:
|
||||
tool_call_dict = eval(
|
||||
tool_call['function']['arguments']
|
||||
)
|
||||
|
||||
if (
|
||||
tool_call_dict is not None
|
||||
and tool_call_dict != {}
|
||||
):
|
||||
command = tool_call_dict['command']
|
||||
if command == 'create':
|
||||
test_suite = tool_call_dict['file_text']
|
||||
if (
|
||||
command != 'str_replace'
|
||||
and command != 'insert'
|
||||
and 'coverage' not in command
|
||||
):
|
||||
print(command)
|
||||
if command == 'insert':
|
||||
test_suite_new = insert_line_in_string(
|
||||
test_suite,
|
||||
tool_call_dict['new_str'],
|
||||
tool_call_dict['insert_line'],
|
||||
)
|
||||
test_suite = test_suite_new
|
||||
if command == 'str_replace':
|
||||
if (
|
||||
test_suite.count(
|
||||
tool_call_dict['old_str']
|
||||
)
|
||||
== 1
|
||||
):
|
||||
test_suite_new = test_suite.replace(
|
||||
tool_call_dict['old_str'],
|
||||
tool_call_dict['new_str'],
|
||||
)
|
||||
else:
|
||||
continue
|
||||
test_suite = test_suite_new
|
||||
except Exception:
|
||||
print(traceback.format_exc())
|
||||
continue
|
||||
|
||||
metadata_copy['test_result']['test_suite'] = test_suite
|
||||
if i < 25:
|
||||
final_output[i].append(metadata_copy)
|
||||
i += 1
|
||||
except Exception as e:
|
||||
print(traceback.format_exc())
|
||||
print(f' Error loading {file_path}: {e}')
|
||||
|
||||
for j in range(i, 24):
|
||||
final_output[j].append(metadata_copy)
|
||||
metadata_orig = copy.deepcopy(metadata)
|
||||
metadata_orig['test_result']['test_suite'] = orig_test_suite
|
||||
final_output[24].append(metadata_orig)
|
||||
|
||||
for i in range(25):
|
||||
output_file = os.path.join(output_dir, f'output_{i}.jsonl')
|
||||
with open(output_file, 'w') as f:
|
||||
for metadata in final_output[i]:
|
||||
f.write(json.dumps(metadata) + '\n')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Parse JSON file')
|
||||
parser.add_argument('--root_dir', type=str, help='Root directory', required=True)
|
||||
parser.add_argument(
|
||||
'--output_dir', type=str, help='Output directory', required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
'--starting_preds_file', type=str, help='Starting predictions', default=None
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
output_file = os.path.join(args.output_dir, 'output.jsonl')
|
||||
metadata_objs = {}
|
||||
with open(output_file, 'r') as f:
|
||||
content = f.readlines()
|
||||
for line in content:
|
||||
metadata = json.loads(line)
|
||||
metadata_objs[metadata['instance_id']] = metadata
|
||||
|
||||
starting_preds_file = args.starting_preds_file
|
||||
preds_objs = {}
|
||||
if starting_preds_file is not None:
|
||||
with open(starting_preds_file, 'r') as f:
|
||||
content = f.readlines()
|
||||
for line in content:
|
||||
pred = json.loads(line)
|
||||
preds_objs[pred['id']] = pred['preds']['full'][0]
|
||||
|
||||
parse_json_files(args.root_dir, args.output_dir, metadata_objs, preds_objs)
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
|
||||
import pandas as pd
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description='Compare two TestGenEval output JSONL files and print the resolved diff'
|
||||
)
|
||||
parser.add_argument('input_file_1', type=str)
|
||||
parser.add_argument('input_file_2', type=str)
|
||||
args = parser.parse_args()
|
||||
|
||||
df1 = pd.read_json(args.input_file_1, orient='records', lines=True)
|
||||
df2 = pd.read_json(args.input_file_2, orient='records', lines=True)
|
||||
|
||||
|
||||
# Get the intersection of the ids
|
||||
df = pd.merge(df1, df2, on='id', how='inner')
|
||||
|
||||
|
||||
def _get_coverage(report):
|
||||
if report is None:
|
||||
return False
|
||||
if isinstance(report, float):
|
||||
return False
|
||||
else:
|
||||
return report.get('test_pass', False)
|
||||
|
||||
|
||||
df['test_pass_x'] = df['test_pass_x'].apply(_get_coverage)
|
||||
df['test_pass_y'] = df['test_pass_y'].apply(_get_coverage)
|
||||
df['diff'] = df.apply(lambda x: x['test_pass_x'] != x['test_pass_y'], axis=1)
|
||||
|
||||
df_diff = df[df['diff']].sort_values(
|
||||
by=['test_pass_x', 'test_pass_y'], ascending=[False, False]
|
||||
)
|
||||
# skip if any of the pass is nan, which means one of the eval is not finished yet
|
||||
df_diff = df_diff[df_diff['test_pass_x'].notna() & df_diff['test_pass_y'].notna()]
|
||||
|
||||
print(f'X={args.input_file_1}')
|
||||
print(f'Y={args.input_file_2}')
|
||||
print(f'# diff={df_diff.shape[0]}')
|
||||
df_diff = df_diff[['id', 'test_pass_x', 'test_pass_y', 'report_x', 'report_y']]
|
||||
|
||||
# x pass but y not
|
||||
print('-' * 100)
|
||||
df_diff_x_only = df_diff[df_diff['test_pass_x'] & ~df_diff['test_pass_y']].sort_values(
|
||||
by='id'
|
||||
)
|
||||
print(f'# x pass but y not={df_diff_x_only.shape[0]}')
|
||||
print(df_diff_x_only[['id', 'report_x', 'report_y']])
|
||||
|
||||
# y pass but x not
|
||||
print('-' * 100)
|
||||
df_diff_y_only = df_diff[~df_diff['test_pass_x'] & df_diff['test_pass_y']].sort_values(
|
||||
by='id'
|
||||
)
|
||||
print(f'# y pass but x not={df_diff_y_only.shape[0]}')
|
||||
print(df_diff_y_only[['id', 'report_x', 'report_y']])
|
||||
# get instance_id from df_diff_y_only
|
||||
print('-' * 100)
|
||||
print('Instances that x pass but y not:')
|
||||
print(df_diff_x_only['id'].tolist())
|
||||
|
||||
print('-' * 100)
|
||||
print('Instances that y pass but x not:')
|
||||
print(df_diff_y_only['id'].tolist())
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
FOLDER_PATH=$1
|
||||
NEW_FOLDER_PATH=${FOLDER_PATH}.swebench_submission
|
||||
mkdir -p $NEW_FOLDER_PATH
|
||||
|
||||
# Build all_preds.jsonl
|
||||
poetry run python evaluation/testgeneval/scripts/eval/convert_oh_output_to_swe_json.py $FOLDER_PATH/output.jsonl
|
||||
mv $FOLDER_PATH/output.swebench.jsonl $NEW_FOLDER_PATH/all_preds.jsonl
|
||||
|
||||
# Build trajs/
|
||||
mkdir -p $NEW_FOLDER_PATH/trajs
|
||||
for instance_dir in $FOLDER_PATH/llm_completions/*/; do
|
||||
instance_id=$(basename "$instance_dir")
|
||||
latest_json=$(ls -t "$instance_dir"/*.json | head -n1)
|
||||
if [ -n "$latest_json" ]; then
|
||||
cat "$latest_json" | jq -r '.messages' > "$NEW_FOLDER_PATH/trajs/$instance_id.json"
|
||||
fi
|
||||
done
|
||||
|
||||
# Build logs/
|
||||
# check if $FOLDER_PATH/eval_outputs exists, if so copy over - else raise error
|
||||
if [ -d "$FOLDER_PATH/eval_outputs" ]; then
|
||||
cp -r $FOLDER_PATH/eval_outputs $NEW_FOLDER_PATH/logs
|
||||
else
|
||||
echo "Error: $FOLDER_PATH/eval_outputs does not exist. You should run the local docker eval_infer.sh first."
|
||||
exit 1
|
||||
fi
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user