brickagent 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- brickagent-0.1.0/.gitignore +4 -0
- brickagent-0.1.0/LICENSE +21 -0
- brickagent-0.1.0/PKG-INFO +176 -0
- brickagent-0.1.0/README.md +159 -0
- brickagent-0.1.0/pyproject.toml +34 -0
- brickagent-0.1.0/src/brickagent/__init__.py +46 -0
- brickagent-0.1.0/src/brickagent/_data/v1/bounds.json.xz +0 -0
- brickagent-0.1.0/src/brickagent/_data/v1/colors.json +2795 -0
- brickagent-0.1.0/src/brickagent/_data/v1/ids.json.xz +0 -0
- brickagent-0.1.0/src/brickagent/_data/v1/keywords.json.xz +0 -0
- brickagent-0.1.0/src/brickagent/_data/v1/mirrors.json.xz +0 -0
- brickagent-0.1.0/src/brickagent/_data/v1/seating.json.xz +0 -0
- brickagent-0.1.0/src/brickagent/catalog.py +119 -0
- brickagent-0.1.0/src/brickagent/check.py +148 -0
- brickagent-0.1.0/src/brickagent/export.py +60 -0
- brickagent-0.1.0/src/brickagent/joints.py +223 -0
- brickagent-0.1.0/src/brickagent/model.py +304 -0
- brickagent-0.1.0/src/brickagent/physics.py +225 -0
- brickagent-0.1.0/src/brickagent/pose.py +84 -0
- brickagent-0.1.0/src/brickagent/reflection.py +56 -0
- brickagent-0.1.0/src/brickagent/search.py +88 -0
- brickagent-0.1.0/src/brickagent/view.py +42 -0
- brickagent-0.1.0/src/brickagent/viewer/LDrawLoader.js +2538 -0
- brickagent-0.1.0/src/brickagent/viewer/README.md +63 -0
- brickagent-0.1.0/src/brickagent/viewer/index.html +43 -0
- brickagent-0.1.0/src/brickagent/viewer/package-lock.json +119 -0
- brickagent-0.1.0/src/brickagent/viewer/package.json +13 -0
- brickagent-0.1.0/src/brickagent/viewer/view.mjs +43 -0
- brickagent-0.1.0/src/brickagent/viewer/viewer.js +302 -0
brickagent-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Peter Kulits
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: brickagent
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Programmatic LEGO design
|
|
5
|
+
Project-URL: Paper, https://brickben.ch
|
|
6
|
+
Author: Peter Kulits
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Requires-Dist: bricknet>=0.1.1
|
|
13
|
+
Requires-Dist: numpy
|
|
14
|
+
Requires-Dist: pybullet
|
|
15
|
+
Requires-Dist: scipy
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
<div align="center">
|
|
19
|
+
|
|
20
|
+
# BrickAgent: Programmatic LEGO Design
|
|
21
|
+
[Peter Kulits](https://kulits.github.io/) [Yiqing Xu](https://eeching.github.io/) [R. Kenny Jones](https://rkjones4.github.io/) [Cordelia Schmid](https://cordeliaschmid.github.io/) [Jiajun Wu](https://jiajunwu.com/)
|
|
22
|
+
|
|
23
|
+
[\[Project Page\]](https://brickben.ch) | [\[Gallery\]](https://gallery.brickben.ch)
|
|
24
|
+
|
|
25
|
+
<img src="https://raw.githubusercontent.com/kulits/BrickAgent/master/docs/images/teaser_mosaic.avif" alt="BrickBench teaser" width="800">
|
|
26
|
+
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
BrickAgent is the environment of BrickBench, a benchmark for agentic text-conditioned LEGO-set design. Coding agents
|
|
30
|
+
use it to programmatically construct, inspect, and validate LEGO assemblies, placing parts through the connector system
|
|
31
|
+
of [BrickNet](https://github.com/kulits/BrickNet).
|
|
32
|
+
|
|
33
|
+
This repository contains:
|
|
34
|
+
- **`brickagent`** (`src/brickagent/`), the environment, on PyPI.
|
|
35
|
+
- **BrickBench**: 300 task prompts (`benchmark/`), the agent prompt, validator, and evaluation (`scripts/`), and the
|
|
36
|
+
agent container (`Dockerfile`).
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
```bash
|
|
40
|
+
pip install brickagent
|
|
41
|
+
python -m bricknet fetch-meshes
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`fetch-meshes` downloads BrickNet's convex colliders (1 GB), which collision and stability checks need, into the
|
|
45
|
+
platform user-data directory; to use another location, export `BRICKNET_DATA` before fetching and keep it set.
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
```python
|
|
49
|
+
from brickagent import Assembly
|
|
50
|
+
|
|
51
|
+
wall = Assembly("wall")
|
|
52
|
+
base = wall.add("plate 2x8", color="dark gray")
|
|
53
|
+
top = base.stud
|
|
54
|
+
for course in range(4):
|
|
55
|
+
next_top, column = [], 0
|
|
56
|
+
for width in (4, 4) if course % 2 == 0 else (2, 4, 2):
|
|
57
|
+
brick = wall.attach(f"brick 2x{width}", to=top[2 * column], by=("hole", 0), color="tan")
|
|
58
|
+
next_top.extend(brick.stud)
|
|
59
|
+
column += width
|
|
60
|
+
top = next_top
|
|
61
|
+
wall.write("wall.mpd", check=True)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`add` places a part or subassembly at a pose; `attach` places it by an exact connector fit. Connectors are indexed in
|
|
65
|
+
BrickNet order (`part.stud[i]`, `part.hole[i]`, ...).
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
# continues the example above
|
|
69
|
+
from brickagent import find, describe, name, connectors, check, view
|
|
70
|
+
|
|
71
|
+
beams = [stem for stem in find("technic beam") if len(connectors(stem, "socket")) == 5]
|
|
72
|
+
print(beams[0], name(beams[0]))
|
|
73
|
+
print(describe("6629"))
|
|
74
|
+
check(wall)
|
|
75
|
+
view(wall, "wall.png") # needs the Rendering setup below
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`check` raises `ValueError` on collisions, inexact connections, exceeded inventory, or instability, naming the parts
|
|
79
|
+
involved. Each connected component is simulated as a rigid body under gravity in PyBullet. Only parts that BrickNet
|
|
80
|
+
supports can be used; `find` lists them. The full API guide, with examples, is the agent prompt, `scripts/prompt.md`.
|
|
81
|
+
|
|
82
|
+
## Building from a Restricted Part Set
|
|
83
|
+
`BRICKAGENT_SET` limits building to an inventory that maps LDraw part numbers to color names and maximum quantities
|
|
84
|
+
(`null` for any); `check` enforces the colors and counts:
|
|
85
|
+
```json
|
|
86
|
+
{"3001": {"red": 8, "blue": 6}, "3020": {"tan": 2}, "3062b": {"white": null}}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Rendering
|
|
90
|
+
`view` needs Node 22.14+ or 23.6+, Mesa (`libegl1`, `libgles2`, `libegl-mesa0`, `libgl1-mesa-dri`), a C++ runtime
|
|
91
|
+
from GCC 11 or newer (Ubuntu 22.04+), the viewer's npm packages, and the LDraw snapshot used in the experiments:
|
|
92
|
+
```bash
|
|
93
|
+
npm ci --prefix "$(python -c 'from importlib.resources import files; print(files("brickagent") / "viewer")')"
|
|
94
|
+
curl -L https://codeload.github.com/kulits/ldraw-parts/tar.gz/b61b905f1173f120f528be9521bb870619c36785 | tar -xz
|
|
95
|
+
export BRICKAGENT_LDRAW="$PWD/ldraw-parts-b61b905f1173f120f528be9521bb870619c36785/ldraw"
|
|
96
|
+
# Render with Mesa, as in the experiments; NVIDIA's EGL driver currently renders washed-out colors.
|
|
97
|
+
export EGL_PLATFORM=surfaceless LIBGL_ALWAYS_SOFTWARE=1
|
|
98
|
+
export __EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
To explore a model in a browser instead, see the [viewer README](https://github.com/kulits/BrickAgent/blob/master/src/brickagent/viewer/README.md#browser).
|
|
102
|
+
|
|
103
|
+
## BrickBench
|
|
104
|
+
### Settings
|
|
105
|
+
| Setting | Prompts | Questions | Requirement |
|
|
106
|
+
| --- | --- | --- | --- |
|
|
107
|
+
| `Model` | 100 | 1,719 | At most 400 parts |
|
|
108
|
+
| `Set` | 100 | 2,369 | 400–4000 parts |
|
|
109
|
+
| `Alt-Build` | 100 | 1,182 | Only the pieces of retail set 10698 (`benchmark/alt-build/inventory.json`) |
|
|
110
|
+
|
|
111
|
+
Each setting's `benchmark/<setting>/tasks.json` lists its prompts, each decomposed into a question graph in the style of
|
|
112
|
+
[DSG](https://arxiv.org/abs/2310.18235): every question has a `key`, its text, a `kind` and `subtype`, and the keys it
|
|
113
|
+
depends on.
|
|
114
|
+
|
|
115
|
+
### Running an Agent
|
|
116
|
+
The agent needs the setup above, either installed directly or through the container used in the experiments. Render the
|
|
117
|
+
prompt for a task:
|
|
118
|
+
```bash
|
|
119
|
+
pip install jinja2
|
|
120
|
+
python scripts/prompt.py "$(jq -r '.[0].prompt' benchmark/model/tasks.json)" --split model > prompt.txt
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Give it to a coding agent in an empty workspace outside this repository, without web search, in a shell where the
|
|
124
|
+
variables above are exported. The experiments ran Codex in the container:
|
|
125
|
+
```bash
|
|
126
|
+
docker build -t brickagent .
|
|
127
|
+
docker build -t brickagent-codex - <<< $'FROM brickagent\nRUN npm install --global @openai/codex'
|
|
128
|
+
mkdir -p work
|
|
129
|
+
docker run --rm -v "$PWD/work:/work" -e OPENAI_API_KEY brickagent-codex \
|
|
130
|
+
codex exec --skip-git-repo-check --dangerously-bypass-approvals-and-sandbox -c web_search=disabled \
|
|
131
|
+
"$(cat prompt.txt)"
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
For `Alt-Build`, export `BRICKAGENT_SET=$PWD/benchmark/alt-build/inventory.json` (in Docker, also pass
|
|
135
|
+
`-v "$BRICKAGENT_SET:$BRICKAGENT_SET:ro" -e BRICKAGENT_SET`). The agent delivers `build.py`, whose `build()` returns the assembly, and `model.mpd`.
|
|
136
|
+
|
|
137
|
+
### Evaluation
|
|
138
|
+
**Valid.** `verify.py` rebuilds the assembly from `build.py` and checks the setting's part requirements, collisions,
|
|
139
|
+
and stability (for `Alt-Build`, with the same `BRICKAGENT_SET`):
|
|
140
|
+
```bash
|
|
141
|
+
python scripts/verify.py work --split model # or set, alt-build; writes work/verification.json, exits 1 if invalid
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Assemblies are rendered from eight views with [BrickNet-Render](https://github.com/kulits/BrickNet-Render) and judged
|
|
145
|
+
by Gemma 4 31B ([google/gemma-4-31B-it](https://huggingface.co/google/gemma-4-31B-it), revision `842da37`), loaded
|
|
146
|
+
with Transformers (about 62 GB of GPU memory). The scripts read `RENDERS/<system>/<task id>/`, e.g.
|
|
147
|
+
`RENDERS/my-agent/alt-001/`. BrickNet-Render needs Python 3.13:
|
|
148
|
+
```bash
|
|
149
|
+
pip install bricknet-render "bpy>=5.1" transformers torch torchvision accelerate pillow
|
|
150
|
+
python -m bricknet_render fetch-glbs
|
|
151
|
+
python scripts/flatten.py work/model.mpd work/model.ldr
|
|
152
|
+
bricknet-render work/model.ldr RENDERS/my-agent/model-001 --views 8 --resolution 1024x1024 --samples 64
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**VQA.** The judge answers each assembly's question graph from its eight views; a question counts only if the
|
|
156
|
+
questions it depends on also hold.
|
|
157
|
+
```bash
|
|
158
|
+
python scripts/vqa.py RENDERS --out vqa.jsonl
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
**ELO.** For each prompt, every pair of assemblies from different systems is judged from four views each, in both
|
|
162
|
+
orders, on alignment with the prompt and on design by the standard of an official set. A Bradley--Terry fit gives
|
|
163
|
+
`Align ELO` and `Design ELO`; `ELO` is their average after rescaling to a common spread over the `--core` systems.
|
|
164
|
+
```bash
|
|
165
|
+
python scripts/judge.py RENDERS --question align --out align.jsonl
|
|
166
|
+
python scripts/judge.py RENDERS --question design --out design.jsonl
|
|
167
|
+
python scripts/elo.py align.jsonl design.jsonl
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Submitting Results
|
|
171
|
+
Submit through the [form](https://forms.gle/GP8FX43EzfaTxkTT9). Upload one zip of at most 10 MB with a folder per task,
|
|
172
|
+
named by task id (`model-001/`, `set-001/`, `alt-001/`, ...), holding `build.py`, `model.mpd`, or both; `build.py` is
|
|
173
|
+
preferred. Missing tasks count as invalid. Check the zip first:
|
|
174
|
+
```bash
|
|
175
|
+
python scripts/check_submission.py submission.zip
|
|
176
|
+
```
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# BrickAgent: Programmatic LEGO Design
|
|
4
|
+
[Peter Kulits](https://kulits.github.io/) [Yiqing Xu](https://eeching.github.io/) [R. Kenny Jones](https://rkjones4.github.io/) [Cordelia Schmid](https://cordeliaschmid.github.io/) [Jiajun Wu](https://jiajunwu.com/)
|
|
5
|
+
|
|
6
|
+
[\[Project Page\]](https://brickben.ch) | [\[Gallery\]](https://gallery.brickben.ch)
|
|
7
|
+
|
|
8
|
+
<img src="https://raw.githubusercontent.com/kulits/BrickAgent/master/docs/images/teaser_mosaic.avif" alt="BrickBench teaser" width="800">
|
|
9
|
+
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
BrickAgent is the environment of BrickBench, a benchmark for agentic text-conditioned LEGO-set design. Coding agents
|
|
13
|
+
use it to programmatically construct, inspect, and validate LEGO assemblies, placing parts through the connector system
|
|
14
|
+
of [BrickNet](https://github.com/kulits/BrickNet).
|
|
15
|
+
|
|
16
|
+
This repository contains:
|
|
17
|
+
- **`brickagent`** (`src/brickagent/`), the environment, on PyPI.
|
|
18
|
+
- **BrickBench**: 300 task prompts (`benchmark/`), the agent prompt, validator, and evaluation (`scripts/`), and the
|
|
19
|
+
agent container (`Dockerfile`).
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
```bash
|
|
23
|
+
pip install brickagent
|
|
24
|
+
python -m bricknet fetch-meshes
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`fetch-meshes` downloads BrickNet's convex colliders (1 GB), which collision and stability checks need, into the
|
|
28
|
+
platform user-data directory; to use another location, export `BRICKNET_DATA` before fetching and keep it set.
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
```python
|
|
32
|
+
from brickagent import Assembly
|
|
33
|
+
|
|
34
|
+
wall = Assembly("wall")
|
|
35
|
+
base = wall.add("plate 2x8", color="dark gray")
|
|
36
|
+
top = base.stud
|
|
37
|
+
for course in range(4):
|
|
38
|
+
next_top, column = [], 0
|
|
39
|
+
for width in (4, 4) if course % 2 == 0 else (2, 4, 2):
|
|
40
|
+
brick = wall.attach(f"brick 2x{width}", to=top[2 * column], by=("hole", 0), color="tan")
|
|
41
|
+
next_top.extend(brick.stud)
|
|
42
|
+
column += width
|
|
43
|
+
top = next_top
|
|
44
|
+
wall.write("wall.mpd", check=True)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`add` places a part or subassembly at a pose; `attach` places it by an exact connector fit. Connectors are indexed in
|
|
48
|
+
BrickNet order (`part.stud[i]`, `part.hole[i]`, ...).
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
# continues the example above
|
|
52
|
+
from brickagent import find, describe, name, connectors, check, view
|
|
53
|
+
|
|
54
|
+
beams = [stem for stem in find("technic beam") if len(connectors(stem, "socket")) == 5]
|
|
55
|
+
print(beams[0], name(beams[0]))
|
|
56
|
+
print(describe("6629"))
|
|
57
|
+
check(wall)
|
|
58
|
+
view(wall, "wall.png") # needs the Rendering setup below
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`check` raises `ValueError` on collisions, inexact connections, exceeded inventory, or instability, naming the parts
|
|
62
|
+
involved. Each connected component is simulated as a rigid body under gravity in PyBullet. Only parts that BrickNet
|
|
63
|
+
supports can be used; `find` lists them. The full API guide, with examples, is the agent prompt, `scripts/prompt.md`.
|
|
64
|
+
|
|
65
|
+
## Building from a Restricted Part Set
|
|
66
|
+
`BRICKAGENT_SET` limits building to an inventory that maps LDraw part numbers to color names and maximum quantities
|
|
67
|
+
(`null` for any); `check` enforces the colors and counts:
|
|
68
|
+
```json
|
|
69
|
+
{"3001": {"red": 8, "blue": 6}, "3020": {"tan": 2}, "3062b": {"white": null}}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Rendering
|
|
73
|
+
`view` needs Node 22.14+ or 23.6+, Mesa (`libegl1`, `libgles2`, `libegl-mesa0`, `libgl1-mesa-dri`), a C++ runtime
|
|
74
|
+
from GCC 11 or newer (Ubuntu 22.04+), the viewer's npm packages, and the LDraw snapshot used in the experiments:
|
|
75
|
+
```bash
|
|
76
|
+
npm ci --prefix "$(python -c 'from importlib.resources import files; print(files("brickagent") / "viewer")')"
|
|
77
|
+
curl -L https://codeload.github.com/kulits/ldraw-parts/tar.gz/b61b905f1173f120f528be9521bb870619c36785 | tar -xz
|
|
78
|
+
export BRICKAGENT_LDRAW="$PWD/ldraw-parts-b61b905f1173f120f528be9521bb870619c36785/ldraw"
|
|
79
|
+
# Render with Mesa, as in the experiments; NVIDIA's EGL driver currently renders washed-out colors.
|
|
80
|
+
export EGL_PLATFORM=surfaceless LIBGL_ALWAYS_SOFTWARE=1
|
|
81
|
+
export __EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
To explore a model in a browser instead, see the [viewer README](https://github.com/kulits/BrickAgent/blob/master/src/brickagent/viewer/README.md#browser).
|
|
85
|
+
|
|
86
|
+
## BrickBench
|
|
87
|
+
### Settings
|
|
88
|
+
| Setting | Prompts | Questions | Requirement |
|
|
89
|
+
| --- | --- | --- | --- |
|
|
90
|
+
| `Model` | 100 | 1,719 | At most 400 parts |
|
|
91
|
+
| `Set` | 100 | 2,369 | 400–4000 parts |
|
|
92
|
+
| `Alt-Build` | 100 | 1,182 | Only the pieces of retail set 10698 (`benchmark/alt-build/inventory.json`) |
|
|
93
|
+
|
|
94
|
+
Each setting's `benchmark/<setting>/tasks.json` lists its prompts, each decomposed into a question graph in the style of
|
|
95
|
+
[DSG](https://arxiv.org/abs/2310.18235): every question has a `key`, its text, a `kind` and `subtype`, and the keys it
|
|
96
|
+
depends on.
|
|
97
|
+
|
|
98
|
+
### Running an Agent
|
|
99
|
+
The agent needs the setup above, either installed directly or through the container used in the experiments. Render the
|
|
100
|
+
prompt for a task:
|
|
101
|
+
```bash
|
|
102
|
+
pip install jinja2
|
|
103
|
+
python scripts/prompt.py "$(jq -r '.[0].prompt' benchmark/model/tasks.json)" --split model > prompt.txt
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Give it to a coding agent in an empty workspace outside this repository, without web search, in a shell where the
|
|
107
|
+
variables above are exported. The experiments ran Codex in the container:
|
|
108
|
+
```bash
|
|
109
|
+
docker build -t brickagent .
|
|
110
|
+
docker build -t brickagent-codex - <<< $'FROM brickagent\nRUN npm install --global @openai/codex'
|
|
111
|
+
mkdir -p work
|
|
112
|
+
docker run --rm -v "$PWD/work:/work" -e OPENAI_API_KEY brickagent-codex \
|
|
113
|
+
codex exec --skip-git-repo-check --dangerously-bypass-approvals-and-sandbox -c web_search=disabled \
|
|
114
|
+
"$(cat prompt.txt)"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
For `Alt-Build`, export `BRICKAGENT_SET=$PWD/benchmark/alt-build/inventory.json` (in Docker, also pass
|
|
118
|
+
`-v "$BRICKAGENT_SET:$BRICKAGENT_SET:ro" -e BRICKAGENT_SET`). The agent delivers `build.py`, whose `build()` returns the assembly, and `model.mpd`.
|
|
119
|
+
|
|
120
|
+
### Evaluation
|
|
121
|
+
**Valid.** `verify.py` rebuilds the assembly from `build.py` and checks the setting's part requirements, collisions,
|
|
122
|
+
and stability (for `Alt-Build`, with the same `BRICKAGENT_SET`):
|
|
123
|
+
```bash
|
|
124
|
+
python scripts/verify.py work --split model # or set, alt-build; writes work/verification.json, exits 1 if invalid
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Assemblies are rendered from eight views with [BrickNet-Render](https://github.com/kulits/BrickNet-Render) and judged
|
|
128
|
+
by Gemma 4 31B ([google/gemma-4-31B-it](https://huggingface.co/google/gemma-4-31B-it), revision `842da37`), loaded
|
|
129
|
+
with Transformers (about 62 GB of GPU memory). The scripts read `RENDERS/<system>/<task id>/`, e.g.
|
|
130
|
+
`RENDERS/my-agent/alt-001/`. BrickNet-Render needs Python 3.13:
|
|
131
|
+
```bash
|
|
132
|
+
pip install bricknet-render "bpy>=5.1" transformers torch torchvision accelerate pillow
|
|
133
|
+
python -m bricknet_render fetch-glbs
|
|
134
|
+
python scripts/flatten.py work/model.mpd work/model.ldr
|
|
135
|
+
bricknet-render work/model.ldr RENDERS/my-agent/model-001 --views 8 --resolution 1024x1024 --samples 64
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**VQA.** The judge answers each assembly's question graph from its eight views; a question counts only if the
|
|
139
|
+
questions it depends on also hold.
|
|
140
|
+
```bash
|
|
141
|
+
python scripts/vqa.py RENDERS --out vqa.jsonl
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**ELO.** For each prompt, every pair of assemblies from different systems is judged from four views each, in both
|
|
145
|
+
orders, on alignment with the prompt and on design by the standard of an official set. A Bradley--Terry fit gives
|
|
146
|
+
`Align ELO` and `Design ELO`; `ELO` is their average after rescaling to a common spread over the `--core` systems.
|
|
147
|
+
```bash
|
|
148
|
+
python scripts/judge.py RENDERS --question align --out align.jsonl
|
|
149
|
+
python scripts/judge.py RENDERS --question design --out design.jsonl
|
|
150
|
+
python scripts/elo.py align.jsonl design.jsonl
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Submitting Results
|
|
154
|
+
Submit through the [form](https://forms.gle/GP8FX43EzfaTxkTT9). Upload one zip of at most 10 MB with a folder per task,
|
|
155
|
+
named by task id (`model-001/`, `set-001/`, `alt-001/`, ...), holding `build.py`, `model.mpd`, or both; `build.py` is
|
|
156
|
+
preferred. Missing tasks count as invalid. Check the zip first:
|
|
157
|
+
```bash
|
|
158
|
+
python scripts/check_submission.py submission.zip
|
|
159
|
+
```
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "brickagent"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Programmatic LEGO design"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
authors = [{ name = "Peter Kulits" }]
|
|
14
|
+
dependencies = ["numpy", "scipy", "pybullet", "bricknet>=0.1.1"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Paper = "https://brickben.ch"
|
|
22
|
+
|
|
23
|
+
[tool.hatch.build]
|
|
24
|
+
exclude = ["**/node_modules/**"]
|
|
25
|
+
|
|
26
|
+
[tool.hatch.build.targets.wheel]
|
|
27
|
+
packages = ["src/brickagent"]
|
|
28
|
+
|
|
29
|
+
[tool.hatch.build.targets.sdist]
|
|
30
|
+
include = ["/src/brickagent", "/README.md", "/LICENSE", "/pyproject.toml"]
|
|
31
|
+
exclude = ["**/node_modules/**"]
|
|
32
|
+
|
|
33
|
+
[tool.black]
|
|
34
|
+
line-length = 120
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""BrickAgent: Programmatic LEGO Design."""
|
|
2
|
+
|
|
3
|
+
from .catalog import color, name, resolve
|
|
4
|
+
from .export import ldraw, write
|
|
5
|
+
from .joints import Connector, NoMate, compatible, placement
|
|
6
|
+
from .model import Assembly, Occurrence, Placed, attachments, connectors, measure, parts
|
|
7
|
+
from .pose import BRICK, ID, PLATE, STUD, UP, Pose, at, move, spin
|
|
8
|
+
from .search import describe, find
|
|
9
|
+
from .check import check, clashes, connections
|
|
10
|
+
from .view import view
|
|
11
|
+
|
|
12
|
+
__version__ = "0.1.0"
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"Assembly",
|
|
16
|
+
"BRICK",
|
|
17
|
+
"Connector",
|
|
18
|
+
"ID",
|
|
19
|
+
"NoMate",
|
|
20
|
+
"Occurrence",
|
|
21
|
+
"PLATE",
|
|
22
|
+
"Placed",
|
|
23
|
+
"Pose",
|
|
24
|
+
"STUD",
|
|
25
|
+
"UP",
|
|
26
|
+
"at",
|
|
27
|
+
"attachments",
|
|
28
|
+
"check",
|
|
29
|
+
"clashes",
|
|
30
|
+
"color",
|
|
31
|
+
"compatible",
|
|
32
|
+
"connections",
|
|
33
|
+
"connectors",
|
|
34
|
+
"describe",
|
|
35
|
+
"find",
|
|
36
|
+
"ldraw",
|
|
37
|
+
"measure",
|
|
38
|
+
"move",
|
|
39
|
+
"name",
|
|
40
|
+
"parts",
|
|
41
|
+
"placement",
|
|
42
|
+
"resolve",
|
|
43
|
+
"spin",
|
|
44
|
+
"view",
|
|
45
|
+
"write",
|
|
46
|
+
]
|
|
Binary file
|