Skip to content

Commit 31149b3

Browse files
authored
Merge pull request #7 from logic-star-ai/post-icml
Post icml
2 parents e56572d + d371af8 commit 31149b3

21 files changed

Lines changed: 584 additions & 189 deletions

src/env/base.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import io
22
import logging
3+
import os
34
import pathlib
45
import tarfile
56
import uuid
@@ -49,7 +50,7 @@ class Env:
4950
port: int = 5000
5051

5152
# How much time (in seconds) we should wait for the app in the container to start.
52-
wait_to_start_time: float = 2.0
53+
wait_to_start_time: float = 60.0
5354

5455
@property
5556
def id(self) -> str:
@@ -68,6 +69,18 @@ def __lt__(self, other: Any) -> bool:
6869
return False
6970
return self.id < other.id
7071

72+
def build_only_docker_image_file(
73+
self,
74+
additional_docker_commands: list[str],
75+
) -> str:
76+
final_dockerfile = self.dockerfile.format(
77+
entrypoint_cmd=self.entrypoint_cmd,
78+
additional_commands="\n".join(
79+
[f"RUN {cmd}" for cmd in additional_docker_commands]
80+
),
81+
)
82+
return final_dockerfile
83+
7184
def build_docker_image(
7285
self,
7386
files: dict[pathlib.Path, str],
@@ -100,18 +113,18 @@ def add_file(path: str, content: str) -> None:
100113
add_file(manifest_path, content)
101114
tar_stream.seek(0)
102115

103-
logger.info("Files copied. Building the docker image.")
104-
logger.info("-" * 100)
105116
# Build the Docker image using the tar file.
106117
lang, frw = self.language.replace("-", "_"), self.framework.replace("-", "_")
107-
tag = f"bax_bench_{lang}_{frw}".lower()
118+
tag = f"code_sec_bench_{lang}_{frw}".lower()
119+
logger.info("Files copied, building the image")
120+
logger.info("-" * 100)
108121
r = _docker_client.images.build(
109122
fileobj=tar_stream,
110123
nocache=no_cache,
111124
custom_context=True,
112125
tag=tag,
113126
rm=True,
114-
timeout=600,
127+
timeout=600, # 10 minutes max to build the image
115128
forcerm=True,
116129
labels={"language": self.language, "framework": self.framework},
117130
)
@@ -126,7 +139,7 @@ def run_docker_container(self, image_id: str, use_port: int) -> Container:
126139
Container,
127140
_docker_client.containers.run(
128141
image_id,
129-
name=f"bax_bench_{uid}",
142+
name=f"code-sec-bench-{uid}",
130143
detach=True,
131144
ports={f"{self.port}/tcp": use_port},
132145
auto_remove=False,
@@ -181,5 +194,6 @@ def hello_world():
181194

182195
# RUN commands that should be executed for all Docker images.
183196
COMMON_DOCKER_RUN_COMMANDS = [
184-
"apk add sqlite", # We use the sqlite3 binary for validating exploits.
197+
"apt-get update", # We use the sqlite3 binary for validating exploits.
198+
"apt-get install sqlite3", # We use the sqlite3 binary for validating exploits.
185199
]

src/env/go.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212

1313
_GO_DOCKERFILE = f"""
1414
# setup base
15-
FROM golang:1.23.4-alpine3.21
15+
FROM golang:1.23-bullseye
1616
{{additional_commands}}
1717
1818
# prebuild/prefetch deps
1919
RUN mkdir -p {_WORKDIR}
20-
RUN apk add gcc build-base # Required to make CGO work
20+
RUN apt-get install gcc build-essential -y # Required to make CGO work
2121
RUN go install golang.org/x/tools/cmd/goimports@latest
2222
WORKDIR {_WORKDIR}
2323
COPY {_GO_MOD_FILENAME} {_BUILD_HELPER_FILENAME} ./

src/env/javascript.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
_JS_DOCKERFILE = f"""
88
# setup base
9-
FROM node:22.12-alpine3.20
9+
FROM node:22.12-bullseye
10+
RUN apt-get update
1011
RUN mkdir -p {_WORKDIR}
1112
# WORKDIR has to come first, otherwise npm fails to install packages
1213
WORKDIR {_WORKDIR}
@@ -127,8 +128,9 @@
127128
###############
128129
_NEST_JS_DOCKERFILE = f"""
129130
# setup base
130-
FROM node:22.12-alpine3.20
131-
RUN apk add git
131+
FROM node:22.12-bullseye
132+
RUN apt-get update
133+
RUN apt-get install -y git
132134
RUN git clone https://github.com/nestjs/typescript-starter.git {_WORKDIR}
133135
WORKDIR {_WORKDIR}
134136
RUN git checkout c61ae23339fb07be94ac9ca4908be26723e648b1

src/env/php.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1-
from env.base import MULTI_FILE_APP_PROMPT_STRUCTURE, Env
1+
from env.base import MULTI_FILE_APP_PROMPT_STRUCTURE, SINGLE_FILE_APP_INSRUCTIONS, Env
22

33
_WORKDIR = "/app"
44
_COMPOSER_JSON = "composer.json"
55

66
_PHP_DOCKERFILE = f"""
77
# setup base
8-
FROM php:8.2-alpine
8+
FROM php:8.2-apache-bullseye
99
{{additional_commands}}
1010
1111
# install deps and copy generated code
1212
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
1313
RUN mkdir -p {_WORKDIR}
1414
WORKDIR {_WORKDIR}
1515
RUN composer --version
16+
RUN apt-get update
17+
RUN apt-get install -y zip unzip git
1618
RUN composer create-project --prefer-dist laravel/lumen .
1719
ENV APP_SECRET=supers3cret
1820
COPY / {_WORKDIR}/

src/env/python.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
_PYTHON_DOCKERFILE = f"""
88
# setup base
9-
FROM python:3.12-alpine
9+
FROM nikolaik/python-nodejs:python3.12-nodejs22-bullseye
1010
{{additional_commands}}
1111
1212
# install deps and copy generated code
@@ -22,6 +22,8 @@
2222
#############
2323
### Flask ###
2424
#############
25+
# The deps obtained from installing:
26+
# Flask == 3.1.0
2527
_FLASK_REQS_TXT = """
2628
itsdangerous==2.2.0
2729
blinker==1.9.0

src/env/ruby.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55

66
_RUBY_DOCKERFILE = f"""
77
# setup base
8-
FROM ruby:3.4.1-alpine
8+
FROM ruby:3.4.1-bullseye
99
{{additional_commands}}
1010
1111
# install deps and copy generated code
1212
RUN mkdir -p {_WORKDIR}
1313
WORKDIR {_WORKDIR}
14-
RUN apk --update add build-base nodejs tzdata postgresql-dev postgresql-client libxslt-dev libxml2-dev git
14+
RUN apt-get update
15+
16+
RUN apt-get install build-essential nodejs tzdata postgresql-common postgresql-client libxslt1-dev libxml2-dev git libpq-dev -y
1517
RUN gem install rails
1618
ENV APP_SECRET=supers3cret
1719
RUN rails new . --api

src/env/rust.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
_SRC_FILENAME = "main.rs"
55
_CARGO_TOML = "Cargo.toml"
66

7-
_EMPTY_BRACKETS = "{{ App::new(); }}"
7+
_EMPTY_BRACKETS = "{{ App::new() }}"
88
_RUST_DOCKERFILE = f"""
99
#setup base
10-
FROM rust:1.83.0-alpine3.20
10+
FROM rust:1.83.0-bullseye
1111
{{additional_commands}}
1212
1313
# prebuild/prefetch deps
14-
RUN apk add imagemagick musl-dev sqlite-dev build-base git
14+
RUN apt-get update
15+
RUN apt-get install imagemagick musl-dev sqlite3 libsqlite3-dev build-essential git -y
1516
RUN mkdir -p {_WORKDIR} {_WORKDIR}/src
1617
WORKDIR {_WORKDIR}
1718
COPY {_CARGO_TOML} {_CARGO_TOML}

src/main.py

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,62 @@
11
import argparse
22
import pathlib
3+
from typing import Any
34

45
import docker
56

67
from env import all_envs
7-
from env.base import Env
8-
from print import tasks_and_results_to_table, tasks_and_results_to_table_averages
8+
from print import (
9+
tasks_and_results_to_table,
10+
tasks_and_results_to_table_averages,
11+
)
912
from scenarios import all_scenarios
10-
from scenarios.base import Scenario
1113
from tasks import Task, TaskHandler
1214

15+
_DEFAULT_SAVE_PATH = pathlib.Path(__file__).parent.parent / "results"
1316

14-
def select_envs(args: argparse.Namespace) -> list[Env]:
17+
18+
def main(args: Any) -> None:
19+
20+
# ----- Preparation -----#
1521
envs = all_envs
22+
exclude_envs = args.exclude_envs if args.exclude_envs else []
23+
envs = [e for e in all_envs if e.id not in exclude_envs]
1624
if args.envs:
1725
envs = [e for e in all_envs if e.id in args.envs]
1826
envs = sorted(envs, key=lambda e: e.id)
27+
1928
if not envs:
2029
raise Exception(
2130
f"Got an empty/invalid list of envs, possible choices: {[e.id for e in all_envs]}",
2231
)
23-
return envs
2432

25-
26-
def select_scenarios(args: argparse.Namespace) -> list[Scenario]:
27-
scenarios = all_scenarios
33+
exclude_scenarios = args.exclude_scenarios if args.exclude_scenarios else []
34+
scenarios = [e for e in all_scenarios if e.id not in exclude_scenarios]
2835
if args.scenarios:
29-
scenarios = [e for e in all_scenarios if e.id in args.scenarios]
36+
scenarios = [
37+
e
38+
for e in all_scenarios
39+
if e.id in args.scenarios and e.id not in exclude_scenarios
40+
]
3041
scenarios = sorted(scenarios, key=lambda s: s.id)
3142
if not scenarios:
3243
raise Exception(
3344
f"Got an empty/invalid list of scenarios, possible choices: {[s.id for s in all_scenarios]}",
3445
)
35-
return scenarios
36-
3746

38-
def main(args: argparse.Namespace) -> None:
39-
# ----- Preparation -----#
40-
envs = select_envs(args)
41-
scenarios = select_scenarios(args)
47+
if not args.models:
48+
raise Exception("Got an empty list of models")
4249

4350
if args.only_samples:
4451
samples = args.only_samples
4552
else:
4653
samples = list(range(args.n_samples))
4754

55+
if args.ks:
56+
ks = args.ks
57+
else:
58+
ks = [1, 5]
59+
4860
tasks = sorted(
4961
[
5062
Task(
@@ -56,6 +68,7 @@ def main(args: argparse.Namespace) -> None:
5668
safety_prompt=args.safety_prompt,
5769
reasoning_effort=args.reasoning_effort,
5870
openrouter=args.openrouter,
71+
vllm=args.vllm,
5972
)
6073
for env in envs
6174
for scenario in scenarios
@@ -79,7 +92,10 @@ def main(args: argparse.Namespace) -> None:
7992
base_delay=args.base_delay,
8093
max_delay=args.max_delay,
8194
force=args.force,
95+
skip_failed=args.skip_failed,
8296
openrouter=args.openrouter,
97+
vllm=args.vllm,
98+
vllm_port=args.vllm_port,
8399
)
84100
elif args.mode == "test":
85101
task_handler.run_tests(
@@ -89,9 +105,11 @@ def main(args: argparse.Namespace) -> None:
89105
min_port=args.min_port,
90106
force=args.force,
91107
)
108+
if args.prune_docker:
109+
docker.from_env().containers.prune()
92110
elif args.mode == "evaluate":
93111
r = task_handler.evaluate_results(
94-
ks=args.ks,
112+
ks=ks,
95113
samples=samples,
96114
)
97115
print(tasks_and_results_to_table_averages(r))
@@ -112,7 +130,7 @@ def main(args: argparse.Namespace) -> None:
112130
choices=[
113131
"generate",
114132
"test",
115-
"evaluate",
133+
"evaluate"
116134
],
117135
required=True,
118136
help="Mode in which to run the code",
@@ -141,7 +159,7 @@ def main(args: argparse.Namespace) -> None:
141159
help="If given, it will restrict operations to these sample indices.",
142160
)
143161
parser.add_argument(
144-
"--ks", type=int, nargs="+", default=[1, 5], help="List of k for pass@k score."
162+
"--ks", type=int, nargs="+", default=None, help="List of k for pass@k score."
145163
)
146164
parser.add_argument(
147165
"--envs",
@@ -150,13 +168,27 @@ def main(args: argparse.Namespace) -> None:
150168
nargs="+",
151169
help="List of environments (if empty, then all environments are used)",
152170
)
171+
parser.add_argument(
172+
"--exclude_envs",
173+
type=str,
174+
default=None,
175+
nargs="+",
176+
help="List of environments to exclude",
177+
)
153178
parser.add_argument(
154179
"--scenarios",
155180
type=str,
156181
default=None,
157182
nargs="+",
158183
help="List of scenarios (if empty, then all scenarios are used)",
159184
)
185+
parser.add_argument(
186+
"--exclude_scenarios",
187+
type=str,
188+
default=None,
189+
nargs="+",
190+
help="List of scenarios to exclude",
191+
)
160192
parser.add_argument(
161193
"--spec_type",
162194
choices=["openapi", "text"],
@@ -174,7 +206,7 @@ def main(args: argparse.Namespace) -> None:
174206
parser.add_argument(
175207
"--results_dir",
176208
type=pathlib.Path,
177-
default=pathlib.Path(__file__).parent.parent / "results",
209+
default=_DEFAULT_SAVE_PATH,
178210
help="Directory to save the results",
179211
)
180212
parser.add_argument(
@@ -225,9 +257,30 @@ def main(args: argparse.Namespace) -> None:
225257
action="store_true",
226258
help="Force generation even if the file already exists",
227259
)
260+
parser.add_argument(
261+
"--skip_failed",
262+
action="store_true",
263+
help="Skip failed tasks and continue with the rest",
264+
)
265+
parser.add_argument(
266+
"--prune_docker",
267+
action="store_true",
268+
help="Prune docker containers after running tests",
269+
)
228270
parser.add_argument(
229271
"--openrouter",
230272
action="store_true",
231273
help="Route requests through OpenRouter",
232274
)
275+
parser.add_argument(
276+
"--vllm",
277+
action="store_true",
278+
help="Use VLLM for generation",
279+
)
280+
parser.add_argument(
281+
"--vllm_port",
282+
type=int,
283+
default=8000,
284+
help="Port for VLLM server",
285+
)
233286
main(parser.parse_args())

0 commit comments

Comments
 (0)