Spaces:
Running
on
A100
Running
on
A100
Commit
·
def3000
1
Parent(s):
27e7d1f
Squash commits
Browse files- .gitattributes +2 -0
- .gitignore +21 -0
- .gitmodules +4 -0
- .python-version +1 -0
- ImportLDraw +1 -0
- README.md +71 -8
- app.py +150 -0
- examples/60066a5369f1354e631a23fef2ba638b.png +3 -0
- examples/60790035c8126a677645b4fdaedbc34.png +3 -0
- examples/8981c0ffae1af00a50fc88ed745bdb67.png +3 -0
- examples/9c1b0058dfe027cbf519adc9991b5f11.png +3 -0
- examples/e488826128fe3854b300c4ca2f51c01b.png +3 -0
- examples/e5c8853f28328d0c2511f68da65f4c4.png +3 -0
- examples/examples.json +44 -0
- pyproject.toml +14 -0
- render_lego.py +4 -0
- requirements.txt +91 -0
- uv.lock +0 -0
.gitattributes
CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
37 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Python-generated files
|
2 |
+
__pycache__/
|
3 |
+
*.py[oc]
|
4 |
+
build/
|
5 |
+
dist/
|
6 |
+
wheels/
|
7 |
+
*.egg-info
|
8 |
+
|
9 |
+
# Virtual environments
|
10 |
+
.venv
|
11 |
+
|
12 |
+
# Gurobi files
|
13 |
+
gurobi.lic
|
14 |
+
|
15 |
+
# LDraw files
|
16 |
+
ldraw
|
17 |
+
complete.zip
|
18 |
+
|
19 |
+
.idea
|
20 |
+
.gradio
|
21 |
+
out
|
.gitmodules
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[submodule "ImportLDraw"]
|
2 |
+
path = ImportLDraw
|
3 |
+
url = https://github.com/sgebbie/ImportLDraw.git
|
4 |
+
branch = bugfix/material-fabric-warning
|
.python-version
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
3.11
|
ImportLDraw
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
Subproject commit 7fe64deef48c8f726e44a30341d04b5fa396ff35
|
README.md
CHANGED
@@ -1,13 +1,76 @@
|
|
1 |
---
|
2 |
-
title: LegoGPT
|
3 |
-
emoji:
|
4 |
-
|
5 |
-
|
6 |
sdk: gradio
|
7 |
sdk_version: 5.29.0
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
---
|
12 |
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
---
|
2 |
+
title: LegoGPT-Demo
|
3 |
+
emoji: 🧱
|
4 |
+
short_description: Generate stable LEGO structures from text prompts.
|
5 |
+
app_file: app.py
|
6 |
sdk: gradio
|
7 |
sdk_version: 5.29.0
|
8 |
+
python_version: 3.11
|
9 |
+
models:
|
10 |
+
- AvaLovelace/LegoGPT
|
11 |
---
|
12 |
|
13 |
+
# LegoGPT Demo
|
14 |
+
|
15 |
+
Gradio demo for LegoGPT.
|
16 |
+
|
17 |
+
## Prerequisites
|
18 |
+
|
19 |
+
- **Llama-3.2-1B-Instruct:** LegoGPT is fine-tuned from meta-llama/Llama-3.2-1B-Instruct, a gated model. Request access
|
20 |
+
to the model [here](https://huggingface.co/meta-llama/Llama-3.2-1B-Instruct), then generate
|
21 |
+
a [Hugging Face user access token](https://huggingface.co/docs/hub/en/security-tokens).
|
22 |
+
- *If running locally,* set your access token as an environment variable: `export HF_TOKEN=<your_token>`
|
23 |
+
- *If running on Hugging Face Spaces,* set your access token as the `HF_TOKEN` secret in the Settings tab of your
|
24 |
+
Space.
|
25 |
+
|
26 |
+
The model will be
|
27 |
+
automatically downloaded upon running the code.
|
28 |
+
- **Gurobi:** Running stability analysis requires a [Gurobi licence](https://www.gurobi.com/downloads/) to use Gurobi.
|
29 |
+
Academics may request a free licence from the Gurobi
|
30 |
+
website [here](https://www.gurobi.com/academia/academic-program-and-licenses/).
|
31 |
+
- *If running locally,* place the Gurobi licence file in your *home directory* or
|
32 |
+
another [recommended location](https://support.gurobi.com/hc/en-us/articles/360013417211-Where-do-I-place-the-Gurobi-license-file-gurobi-lic).
|
33 |
+
- *If running on Hugging Face Spaces,* the licence type must be **Web License Service (WLS)**. Set the
|
34 |
+
`WLSACCESSID`, `WLSSECRET`, and `LICENSEID` secrets in the Settings tab of your Space to their values in your
|
35 |
+
Gurobi licence file.
|
36 |
+
- **ImportLDraw:** Rendering LEGO visualizations requires ImportLDraw, provided as a Git submodule.
|
37 |
+
- *If running locally,* follow these instructions to install ImportLDraw:
|
38 |
+
- Download [Git LFS](https://git-lfs.com), then run `git lfs install`.
|
39 |
+
- Install Git submodules with `git submodule update --init`.
|
40 |
+
- Download the [LDraw parts library](https://library.ldraw.org/library/updates/complete.zip) and
|
41 |
+
extract it in your *home directory*:
|
42 |
+
`(cd ~ && wget https://library.ldraw.org/library/updates/complete.zip && unzip complete.zip)`.
|
43 |
+
- If you wish to put the LDraw parts library in a different directory, set the environment variable
|
44 |
+
`LDRAW_LIBRARY_PATH` to the path of the `ldraw` directory: `export LDRAW_LIBRARY_PATH=path/to/ldraw`.
|
45 |
+
- *If running on Hugging Face Spaces,* ImportLDraw and the LDraw parts library will automatically be downloaded and
|
46 |
+
installed by the `app.py` script.
|
47 |
+
|
48 |
+
## Running locally
|
49 |
+
|
50 |
+
Install the Python project manager [uv](https://docs.astral.sh/uv). Then run the demo with:
|
51 |
+
|
52 |
+
```zsh
|
53 |
+
uv run app.py
|
54 |
+
```
|
55 |
+
|
56 |
+
## Running on Hugging Face Spaces
|
57 |
+
|
58 |
+
Make sure the origin of this repo is set to your Space:
|
59 |
+
|
60 |
+
```zsh
|
61 |
+
git remote set-url origin [email protected]:spaces/<your_username>/<your_space_name>
|
62 |
+
```
|
63 |
+
|
64 |
+
Then commit and push your changes to your Space with
|
65 |
+
|
66 |
+
```
|
67 |
+
git add -A && git commit -m "Update" && git push
|
68 |
+
```
|
69 |
+
|
70 |
+
> [!NOTE]
|
71 |
+
> If you've changed the dependencies in `pyproject.toml`, update the `requirements.txt` file accordingly:
|
72 |
+
> ```zsh
|
73 |
+
> uv export --format requirements-txt --no-hashes > requirements.txt
|
74 |
+
> ```
|
75 |
+
> Then, `git commit` and `git push` the changes to your Space. You may have to restart the Space for the changes to take
|
76 |
+
> effect.
|
app.py
ADDED
@@ -0,0 +1,150 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
import os
|
3 |
+
import subprocess
|
4 |
+
import time
|
5 |
+
import uuid
|
6 |
+
import zipfile
|
7 |
+
from dataclasses import fields
|
8 |
+
from urllib.request import urlretrieve
|
9 |
+
|
10 |
+
import gradio as gr
|
11 |
+
import transformers
|
12 |
+
from legogpt.models import LegoGPT, LegoGPTConfig
|
13 |
+
|
14 |
+
|
15 |
+
def setup():
|
16 |
+
# Set up Gurobi licence
|
17 |
+
licence_filename = 'gurobi.lic'
|
18 |
+
licence_lines = []
|
19 |
+
for secret_name in ['WLSACCESSID', 'WLSSECRET', 'LICENSEID']:
|
20 |
+
secret = os.environ.get(secret_name)
|
21 |
+
if not secret:
|
22 |
+
raise ValueError(f'Env variable {secret_name} not found. Please set it in the Hugging Face Space settings.')
|
23 |
+
licence_lines.append(f'{secret_name}={secret}\n')
|
24 |
+
with open(licence_filename, 'w') as f:
|
25 |
+
f.writelines(licence_lines)
|
26 |
+
os.environ['GRB_LICENSE_FILE'] = os.path.abspath(licence_filename)
|
27 |
+
|
28 |
+
# Download LDraw part library and set LDraw library path
|
29 |
+
ldraw_zip_url = 'https://library.ldraw.org/library/updates/complete.zip'
|
30 |
+
ldraw_zip_filename = 'complete.zip'
|
31 |
+
urlretrieve(ldraw_zip_url, ldraw_zip_filename)
|
32 |
+
with zipfile.ZipFile(ldraw_zip_filename) as zip_ref:
|
33 |
+
zip_ref.extractall()
|
34 |
+
os.environ['LDRAW_LIBRARY_PATH'] = os.path.abspath('ldraw')
|
35 |
+
|
36 |
+
|
37 |
+
def main():
|
38 |
+
if os.environ.get('IS_HF_SPACE') == '1':
|
39 |
+
print('Running in Hugging Face Space, setting up environment...')
|
40 |
+
setup()
|
41 |
+
|
42 |
+
model_cfg = LegoGPTConfig(max_regenerations=10)
|
43 |
+
model = LegoGPT(model_cfg)
|
44 |
+
|
45 |
+
def generate_lego(
|
46 |
+
prompt: str,
|
47 |
+
temperature: float | None,
|
48 |
+
seed: int | None,
|
49 |
+
max_bricks: int | None,
|
50 |
+
max_brick_rejections: int | None,
|
51 |
+
max_regenerations: int | None,
|
52 |
+
):
|
53 |
+
# Set model parameters
|
54 |
+
if temperature is not None: model.temperature = temperature
|
55 |
+
if max_bricks is not None: model.max_bricks = max_bricks
|
56 |
+
if max_brick_rejections is not None: model.max_brick_rejections = max_brick_rejections
|
57 |
+
if max_regenerations is not None: model.max_regenerations = max_regenerations
|
58 |
+
if seed is not None: transformers.set_seed(seed)
|
59 |
+
|
60 |
+
# Generate LEGO
|
61 |
+
print(f'Generating LEGO for prompt: "{prompt}"')
|
62 |
+
start_time = time.time()
|
63 |
+
output = model(prompt)
|
64 |
+
|
65 |
+
# Write output LDR to file
|
66 |
+
output_dir = os.path.abspath('out')
|
67 |
+
output_uuid = str(uuid.uuid4())
|
68 |
+
os.makedirs(output_dir, exist_ok=True)
|
69 |
+
ldr_filename = os.path.join(output_dir, f'{output_uuid}.ldr')
|
70 |
+
with open(ldr_filename, 'w') as f:
|
71 |
+
f.write(output['lego'].to_ldr())
|
72 |
+
print(f'Finished generation in {time.time() - start_time:.1f}s!')
|
73 |
+
|
74 |
+
# Render LEGO model to image
|
75 |
+
print('Rendering image...')
|
76 |
+
start_time = time.time()
|
77 |
+
img_filename = os.path.join(output_dir, f'{output_uuid}.png')
|
78 |
+
subprocess.run(['python', 'render_lego.py', '--in_file', ldr_filename, '--out_file', img_filename],
|
79 |
+
check=True) # Run render as a subprocess to prevent issues with Blender
|
80 |
+
print(f'Finished rendering in {time.time() - start_time:.1f}s!')
|
81 |
+
|
82 |
+
return img_filename, output['lego']
|
83 |
+
|
84 |
+
# Define inputs and outputs
|
85 |
+
in_prompt = gr.Textbox(label='Prompt', placeholder='Enter a prompt to generate a LEGO model.')
|
86 |
+
in_temperature = gr.Slider(0.01, 2.0, value=model_cfg.temperature, step=0.01,
|
87 |
+
label='Temperature', info=get_help_string('temperature'))
|
88 |
+
in_seed = gr.Number(value=42, label='Seed', info='Random seed for generation.', precision=0, step=1)
|
89 |
+
in_bricks = gr.Number(value=model_cfg.max_bricks, label='Max bricks', info=get_help_string('max_bricks'),
|
90 |
+
precision=0, minimum=1, step=1)
|
91 |
+
in_rejections = gr.Number(value=model_cfg.max_brick_rejections, label='Max brick rejections',
|
92 |
+
info=get_help_string('max_brick_rejections'), precision=0, minimum=0, step=1)
|
93 |
+
in_regenerations = gr.Number(value=model_cfg.max_regenerations, label='Max regenerations',
|
94 |
+
info=get_help_string('max_regenerations'), precision=0, minimum=0, step=1)
|
95 |
+
out_img = gr.Image(label='Output image', format='png')
|
96 |
+
out_txt = gr.Textbox(label='Output LEGO bricks', lines=5, max_lines=5, show_copy_button=True,
|
97 |
+
info='The LEGO structure in text format. Each line of the form "hxw (x,y,z)" represents a '
|
98 |
+
'1-unit-tall rectangular brick with dimensions hxw placed at coordinates (x,y,z).')
|
99 |
+
|
100 |
+
# Define Gradio interface
|
101 |
+
demo = gr.Interface(
|
102 |
+
fn=generate_lego,
|
103 |
+
title='LegoGPT Demo',
|
104 |
+
description='Official demo for [LegoGPT](https://avalovelace1.github.io/LegoGPT/), the first approach for generating physically stable LEGO brick models from text prompts.\n\n'
|
105 |
+
'The model is restricted to creating structures made of 1-unit-tall cuboid bricks on a 20x20x20 grid. It was trained on a dataset of 21 object categories: '
|
106 |
+
'*basket, bed, bench, birdhouse, bookshelf, bottle, bowl, bus, camera, car, chair, guitar, jar, mug, piano, pot, sofa, table, tower, train, vessel.* '
|
107 |
+
'Performance on prompts from outside these categories may be limited. This demo does not include texturing or coloring.',
|
108 |
+
inputs=[in_prompt],
|
109 |
+
additional_inputs=[in_temperature, in_seed, in_bricks, in_rejections, in_regenerations],
|
110 |
+
outputs=[out_img, out_txt],
|
111 |
+
flagging_mode='never',
|
112 |
+
)
|
113 |
+
with demo:
|
114 |
+
with gr.Row():
|
115 |
+
examples = get_examples()
|
116 |
+
dummy_name = gr.Textbox(visible=False, label='Name')
|
117 |
+
dummy_out_img = gr.Image(visible=False, label='Result')
|
118 |
+
gr.Examples(
|
119 |
+
examples=[[name, example['prompt'], example['temperature'], example['seed'], example['output_img']]
|
120 |
+
for name, example in examples.items()],
|
121 |
+
inputs=[dummy_name, in_prompt, in_temperature, in_seed, dummy_out_img],
|
122 |
+
outputs=[out_img, out_txt],
|
123 |
+
fn=lambda *args: (args[-1], examples[args[0]]['output_txt']),
|
124 |
+
run_on_click=True,
|
125 |
+
)
|
126 |
+
demo.launch(share=True)
|
127 |
+
|
128 |
+
|
129 |
+
def get_help_string(field_name: str) -> str:
|
130 |
+
"""
|
131 |
+
:param field_name: Name of a field in LegoGPTConfig.
|
132 |
+
:return: Help string for the field.
|
133 |
+
"""
|
134 |
+
data_fields = fields(LegoGPTConfig)
|
135 |
+
name_field = next(f for f in data_fields if f.name == field_name)
|
136 |
+
return name_field.metadata['help']
|
137 |
+
|
138 |
+
|
139 |
+
def get_examples(example_dir: str = os.path.abspath('examples')) -> dict[str, dict[str, str]]:
|
140 |
+
examples_file = os.path.join(example_dir, 'examples.json')
|
141 |
+
with open(examples_file) as f:
|
142 |
+
examples = json.load(f)
|
143 |
+
|
144 |
+
for example in examples.values():
|
145 |
+
example['output_img'] = os.path.join(example_dir, example['output_img'])
|
146 |
+
return examples
|
147 |
+
|
148 |
+
|
149 |
+
if __name__ == '__main__':
|
150 |
+
main()
|
examples/60066a5369f1354e631a23fef2ba638b.png
ADDED
![]() |
Git LFS Details
|
examples/60790035c8126a677645b4fdaedbc34.png
ADDED
![]() |
Git LFS Details
|
examples/8981c0ffae1af00a50fc88ed745bdb67.png
ADDED
![]() |
Git LFS Details
|
examples/9c1b0058dfe027cbf519adc9991b5f11.png
ADDED
![]() |
Git LFS Details
|
examples/e488826128fe3854b300c4ca2f51c01b.png
ADDED
![]() |
Git LFS Details
|
examples/e5c8853f28328d0c2511f68da65f4c4.png
ADDED
![]() |
Git LFS Details
|
examples/examples.json
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"table": {
|
3 |
+
"prompt": "Table featuring a flat rectangular surface over four evenly spaced legs.",
|
4 |
+
"temperature": 0.6,
|
5 |
+
"seed": 42,
|
6 |
+
"output_img": "9c1b0058dfe027cbf519adc9991b5f11.png",
|
7 |
+
"output_txt": "1x2 (16,18,0)\n1x2 (16,13,0)\n2x2 (0,18,0)\n2x2 (0,13,0)\n1x2 (16,18,1)\n1x2 (16,13,1)\n2x2 (0,18,1)\n2x2 (0,13,1)\n1x1 (16,18,2)\n1x2 (16,13,2)\n2x1 (0,18,2)\n2x2 (0,13,2)\n1x2 (16,17,3)\n1x1 (16,14,3)\n2x2 (0,17,3)\n2x1 (0,14,3)\n1x2 (16,17,4)\n1x2 (16,14,4)\n2x2 (0,17,4)\n2x2 (0,14,4)\n1x2 (16,17,5)\n1x2 (16,14,5)\n2x2 (0,17,5)\n2x2 (0,14,5)\n1x1 (16,18,6)\n1x2 (16,16,6)\n1x1 (16,14,6)\n8x1 (8,17,6)\n2x1 (0,18,6)\n8x1 (0,17,6)\n2x1 (0,16,6)\n2x1 (0,14,6)\n2x6 (16,13,7)\n1x6 (15,13,7)\n2x6 (13,13,7)\n2x6 (11,13,7)\n8x1 (10,19,7)\n2x6 (9,13,7)\n6x2 (3,17,7)\n6x2 (3,15,7)\n6x2 (3,13,7)\n8x1 (2,19,7)\n1x6 (2,13,7)\n2x6 (0,14,7)\n2x1 (0,13,7)\n1x6 (17,14,8)\n2x6 (15,14,8)\n1x6 (14,14,8)\n2x6 (12,14,8)\n8x1 (10,13,8)\n4x2 (8,14,8)\n2x1 (8,13,8)\n6x2 (6,18,8)\n6x2 (6,16,8)\n2x2 (6,14,8)\n2x6 (4,14,8)\n2x6 (2,14,8)\n2x6 (0,14,8)\n8x1 (0,13,8)\n"
|
8 |
+
},
|
9 |
+
"sofa": {
|
10 |
+
"prompt": "Compact sofa with a geometric design.",
|
11 |
+
"temperature": 0.6,
|
12 |
+
"seed": 42,
|
13 |
+
"output_img": "8981c0ffae1af00a50fc88ed745bdb67.png",
|
14 |
+
"output_txt": "1x2 (16,17,0)\n1x1 (16,13,0)\n2x2 (0,17,0)\n2x1 (0,13,0)\n1x1 (17,18,1)\n1x6 (17,12,1)\n2x6 (15,12,1)\n1x6 (14,12,1)\n8x1 (9,18,1)\n1x1 (8,18,1)\n6x2 (8,16,1)\n6x2 (8,14,1)\n6x2 (8,12,1)\n6x2 (2,16,1)\n6x2 (2,14,1)\n6x2 (2,12,1)\n8x1 (0,18,1)\n2x6 (0,12,1)\n2x6 (16,13,2)\n2x1 (16,12,2)\n1x1 (15,18,2)\n2x6 (14,12,2)\n1x6 (13,12,2)\n2x6 (11,12,2)\n6x1 (9,18,2)\n2x6 (9,12,2)\n2x6 (7,13,2)\n2x6 (5,13,2)\n4x1 (5,12,2)\n1x1 (4,18,2)\n2x6 (3,12,2)\n2x1 (2,18,2)\n2x6 (1,12,2)\n2x1 (0,18,2)\n1x6 (0,12,2)\n1x6 (17,12,3)\n2x1 (16,18,3)\n1x1 (16,17,3)\n1x2 (15,17,3)\n2x4 (15,13,3)\n2x1 (15,12,3)\n2x1 (13,18,3)\n8x1 (5,18,3)\n1x1 (4,18,3)\n2x1 (2,18,3)\n2x6 (0,13,3)\n2x1 (0,12,3)\n1x1 (17,18,4)\n2x6 (16,12,4)\n1x2 (15,17,4)\n6x2 (9,18,4)\n1x2 (8,18,4)\n6x2 (2,18,4)\n2x1 (0,18,4)\n2x6 (0,12,4)\n2x1 (16,16,5)\n2x4 (16,12,5)\n6x2 (12,17,5)\n8x1 (9,19,5)\n1x1 (8,19,5)\n6x2 (6,17,5)\n8x1 (0,19,5)\n6x2 (0,17,5)\n2x1 (0,16,5)\n2x4 (0,12,5)\n1x2 (17,18,6)\n2x1 (16,17,6)\n4x2 (13,18,6)\n6x2 (7,18,6)\n1x2 (6,18,6)\n6x2 (0,18,6)\n2x1 (0,17,6)\n1x2 (16,18,7)\n2x2 (14,18,7)\n6x2 (8,18,7)\n6x2 (2,18,7)\n2x2 (0,18,7)\n"
|
15 |
+
},
|
16 |
+
"car": {
|
17 |
+
"prompt": "Small car featuring a rectangular body, flat top, and stepped edges.",
|
18 |
+
"temperature": 0.6,
|
19 |
+
"seed": 42,
|
20 |
+
"output_img": "60066a5369f1354e631a23fef2ba638b.png",
|
21 |
+
"output_txt": "1x2 (7,15,0)\n1x1 (7,13,0)\n1x2 (7,5,0)\n2x2 (6,7,0)\n1x1 (6,5,0)\n2x6 (5,11,0)\n2x2 (5,3,0)\n2x6 (3,11,0)\n2x6 (3,3,0)\n2x6 (1,11,0)\n6x2 (1,9,0)\n2x2 (1,3,0)\n1x2 (0,15,0)\n1x1 (0,13,0)\n2x2 (0,7,0)\n1x2 (0,5,0)\n1x1 (7,18,1)\n1x4 (7,8,1)\n2x6 (6,12,1)\n2x6 (6,2,1)\n1x1 (5,19,1)\n2x6 (4,12,1)\n2x2 (4,2,1)\n2x1 (3,19,1)\n2x6 (2,12,1)\n2x2 (2,2,1)\n6x2 (1,10,1)\n6x2 (1,8,1)\n2x6 (0,14,1)\n2x2 (0,12,1)\n1x4 (0,8,1)\n6x2 (0,6,1)\n6x2 (0,4,1)\n2x1 (0,3,1)\n1x1 (7,18,2)\n1x4 (7,13,2)\n1x1 (7,2,2)\n2x6 (6,7,2)\n2x2 (6,5,2)\n2x1 (6,3,2)\n2x6 (5,14,2)\n1x6 (5,7,2)\n1x2 (5,3,2)\n2x6 (3,14,2)\n2x6 (3,7,2)\n1x2 (3,5,2)\n2x2 (3,3,2)\n4x1 (3,2,2)\n1x1 (2,2,2)\n2x6 (1,14,2)\n6x1 (1,13,2)\n2x4 (1,9,2)\n2x6 (1,3,2)\n1x1 (0,18,2)\n1x4 (0,13,2)\n1x1 (0,12,2)\n1x1 (7,13,3)\n1x2 (7,11,3)\n1x8 (7,3,3)\n2x2 (6,18,3)\n2x1 (6,16,3)\n2x2 (6,14,3)\n1x1 (5,19,3)\n1x2 (5,15,3)\n1x1 (4,16,3)\n2x1 (3,19,3)\n1x2 (3,15,3)\n6x1 (1,17,3)\n2x2 (1,15,3)\n2x1 (1,14,3)\n1x1 (1,13,3)\n6x2 (1,11,3)\n6x2 (1,9,3)\n6x2 (1,7,3)\n6x2 (1,5,3)\n6x2 (1,3,3)\n2x1 (0,18,3)\n1x1 (0,15,3)\n1x1 (0,14,3)\n1x1 (0,12,3)\n1x1 (7,18,4)\n2x6 (6,12,4)\n2x2 (6,10,4)\n1x1 (4,9,4)\n4x1 (3,18,4)\n1x2 (3,16,4)\n4x2 (2,10,4)\n1x1 (1,18,4)\n2x6 (1,12,4)\n1x1 (1,11,4)\n1x1 (1,10,4)\n1x1 (0,12,4)\n"
|
22 |
+
},
|
23 |
+
"train": {
|
24 |
+
"prompt": "Train with rectangular body and geometric components.",
|
25 |
+
"temperature": 0.6,
|
26 |
+
"seed": 42,
|
27 |
+
"output_img": "e5c8853f28328d0c2511f68da65f4c4.png",
|
28 |
+
"output_txt": "1x2 (3,17,0)\n1x2 (3,13,0)\n2x2 (2,2,0)\n2x2 (1,17,0)\n2x2 (1,13,0)\n1x2 (0,17,0)\n4x1 (0,6,0)\n2x2 (0,2,0)\n1x1 (3,18,1)\n1x2 (3,16,1)\n1x2 (3,12,1)\n1x2 (3,2,1)\n2x2 (2,14,1)\n2x6 (2,6,1)\n1x1 (2,3,1)\n2x1 (1,18,1)\n2x2 (1,16,1)\n1x2 (1,14,1)\n1x6 (1,6,1)\n2x1 (1,2,1)\n1x1 (0,18,1)\n1x2 (0,16,1)\n2x2 (0,12,1)\n1x2 (0,10,1)\n1x8 (0,2,1)\n1x2 (3,9,2)\n1x1 (3,2,2)\n2x6 (2,13,2)\n2x4 (2,5,2)\n2x1 (1,2,2)\n2x6 (0,13,2)\n4x2 (0,11,2)\n1x2 (0,9,2)\n2x4 (0,5,2)\n4x2 (0,3,2)\n1x1 (0,2,2)\n1x8 (3,10,3)\n1x6 (3,4,3)\n2x6 (1,12,3)\n2x6 (1,6,3)\n2x2 (1,4,3)\n4x1 (0,18,3)\n1x8 (0,10,3)\n1x6 (0,4,3)\n4x2 (0,2,3)\n2x6 (2,10,4)\n2x6 (2,3,4)\n4x1 (0,18,4)\n4x2 (0,16,4)\n2x6 (0,10,4)\n4x1 (0,9,4)\n2x6 (0,3,4)\n1x2 (2,17,5)\n1x4 (2,11,5)\n2x2 (1,9,5)\n2x2 (0,17,5)\n2x2 (0,13,5)\n2x2 (0,11,5)\n1x2 (0,9,5)\n"
|
29 |
+
},
|
30 |
+
"chair-1": {
|
31 |
+
"prompt": "Square-seated chair featuring an upright, rectangular backrest and straight legs.",
|
32 |
+
"temperature": 0.6,
|
33 |
+
"seed": 42,
|
34 |
+
"output_img": "e488826128fe3854b300c4ca2f51c01b.png",
|
35 |
+
"output_txt": "1x2 (7,18,0)\n1x2 (7,11,0)\n2x2 (0,18,0)\n2x2 (0,11,0)\n1x2 (7,18,1)\n1x2 (7,11,1)\n2x2 (0,18,1)\n2x2 (0,11,1)\n1x1 (7,18,2)\n1x2 (7,11,2)\n2x1 (0,18,2)\n2x2 (0,11,2)\n1x2 (7,17,3)\n1x2 (7,11,3)\n2x2 (0,17,3)\n2x2 (0,11,3)\n1x2 (7,17,4)\n1x2 (7,11,4)\n2x2 (0,17,4)\n2x2 (0,11,4)\n1x2 (7,17,5)\n1x2 (7,11,5)\n2x2 (0,17,5)\n2x2 (0,11,5)\n1x1 (7,18,6)\n1x2 (7,11,6)\n2x1 (6,17,6)\n1x1 (6,12,6)\n1x1 (1,12,6)\n6x1 (0,17,6)\n2x1 (0,18,6)\n1x1 (0,12,6)\n2x1 (0,11,6)\n1x6 (7,13,7)\n6x2 (2,11,7)\n6x1 (1,18,7)\n1x1 (1,17,7)\n1x4 (1,13,7)\n1x6 (0,13,7)\n2x2 (0,11,7)\n1x2 (7,17,8)\n1x1 (7,16,8)\n2x2 (7,14,8)\n1x2 (7,12,8)\n1x1 (6,18,8)\n4x1 (2,18,8)\n6x2 (1,16,8)\n6x2 (1,14,8)\n6x2 (1,12,8)\n2x1 (0,18,8)\n1x6 (0,12,8)\n2x6 (6,13,9)\n2x1 (6,12,9)\n2x6 (4,13,9)\n2x6 (2,13,9)\n4x1 (2,12,9)\n1x1 (1,18,9)\n1x6 (1,12,9)\n1x2 (7,17,10)\n6x2 (1,17,10)\n6x2 (2,17,11)\n1x2 (1,17,11)\n1x2 (7,17,12)\n6x2 (1,17,12)\n6x2 (2,17,13)\n1x2 (1,17,13)\n1x2 (7,17,14)\n6x2 (1,17,14)\n6x2 (2,17,15)\n1x2 (1,17,15)\n1x2 (7,18,16)\n6x2 (1,18,16)\n6x2 (2,18,17)\n1x2 (1,18,17)\n"
|
36 |
+
},
|
37 |
+
"chair-2": {
|
38 |
+
"prompt": "Compact chair with a tall backrest and serrated seat.",
|
39 |
+
"temperature": 0.6,
|
40 |
+
"seed": 42,
|
41 |
+
"output_img": "60790035c8126a677645b4fdaedbc34.png",
|
42 |
+
"output_txt": "1x2 (7,17,0)\n1x2 (7,13,0)\n2x2 (0,17,0)\n2x2 (0,13,0)\n1x2 (7,17,1)\n1x2 (7,13,1)\n2x2 (0,17,1)\n2x2 (0,13,1)\n1x1 (7,18,2)\n1x6 (7,12,2)\n2x2 (0,17,2)\n2x2 (0,13,2)\n1x2 (7,17,3)\n1x2 (7,12,3)\n2x2 (0,17,3)\n2x2 (0,12,3)\n1x2 (7,17,4)\n1x2 (7,12,4)\n2x2 (0,17,4)\n2x2 (0,12,4)\n1x2 (7,17,5)\n1x2 (7,12,5)\n2x2 (0,17,5)\n2x2 (0,12,5)\n1x1 (7,18,6)\n1x6 (7,12,6)\n4x1 (3,17,6)\n4x1 (3,13,6)\n1x1 (2,17,6)\n1x1 (2,13,6)\n2x1 (0,18,6)\n2x6 (0,12,6)\n1x1 (7,18,7)\n1x1 (7,12,7)\n6x1 (2,17,7)\n6x1 (2,13,7)\n2x1 (0,18,7)\n2x6 (0,12,7)\n1x1 (7,18,8)\n1x1 (7,12,8)\n2x1 (0,18,8)\n2x1 (0,12,8)\n1x8 (7,11,9)\n1x1 (6,18,9)\n1x1 (6,17,9)\n1x6 (6,11,9)\n4x1 (2,18,9)\n4x1 (2,11,9)\n2x6 (0,13,9)\n2x2 (0,11,9)\n1x2 (7,17,10)\n2x6 (6,11,10)\n1x6 (5,11,10)\n2x6 (3,11,10)\n6x2 (1,17,10)\n2x6 (1,11,10)\n1x1 (0,18,10)\n1x6 (0,12,10)\n1x1 (7,18,11)\n6x1 (1,18,11)\n1x2 (7,18,12)\n1x2 (6,18,12)\n4x2 (2,18,12)\n1x1 (1,18,12)\n1x1 (7,18,13)\n6x1 (2,19,13)\n1x1 (1,19,13)\n6x1 (1,18,13)\n1x2 (7,18,14)\n6x2 (1,18,14)\n6x2 (2,18,15)\n1x2 (1,18,15)\n1x2 (7,18,16)\n6x2 (1,18,16)\n1x2 (5,18,17)\n2x2 (3,18,17)\n"
|
43 |
+
}
|
44 |
+
}
|
pyproject.toml
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[project]
|
2 |
+
name = "legogpt-demo"
|
3 |
+
version = "0.1.0"
|
4 |
+
description = "LegoGPT demo webapp"
|
5 |
+
readme = "README.md"
|
6 |
+
requires-python = ">=3.11"
|
7 |
+
dependencies = [
|
8 |
+
"bpy<=4.3.0", # lower version of bpy needed to run on Hugging Face A100
|
9 |
+
"gradio>=5.29.0",
|
10 |
+
"legogpt",
|
11 |
+
]
|
12 |
+
|
13 |
+
[tool.uv.sources]
|
14 |
+
legogpt = { git = "https://github.com/AvaLovelace1/LegoGPT.git" }
|
render_lego.py
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from legogpt.render_lego import main as render_lego_main
|
2 |
+
|
3 |
+
if __name__ == '__main__':
|
4 |
+
render_lego_main()
|
requirements.txt
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# This file was autogenerated by uv via the following command:
|
2 |
+
# uv export --format requirements-txt --no-hashes
|
3 |
+
accelerate==1.6.0
|
4 |
+
aiofiles==24.1.0
|
5 |
+
annotated-types==0.7.0
|
6 |
+
anyio==4.9.0
|
7 |
+
audioop-lts==0.2.1 ; python_full_version >= '3.13'
|
8 |
+
bpy==4.3.0
|
9 |
+
certifi==2025.4.26
|
10 |
+
cffi==1.17.1 ; platform_python_implementation == 'PyPy'
|
11 |
+
charset-normalizer==3.4.2
|
12 |
+
click==8.1.8 ; sys_platform != 'emscripten'
|
13 |
+
colorama==0.4.6 ; sys_platform == 'win32'
|
14 |
+
cython==3.1.0
|
15 |
+
fastapi==0.115.12
|
16 |
+
ffmpy==0.5.0
|
17 |
+
filelock==3.18.0
|
18 |
+
fsspec==2025.3.0
|
19 |
+
gradio==5.29.0
|
20 |
+
gradio-client==1.10.0
|
21 |
+
groovy==0.1.2
|
22 |
+
gurobipy==12.0.2
|
23 |
+
h11==0.16.0
|
24 |
+
httpcore==1.0.9
|
25 |
+
httpx==0.28.1
|
26 |
+
huggingface-hub==0.30.2
|
27 |
+
idna==3.10
|
28 |
+
jinja2==3.1.6
|
29 |
+
legogpt @ git+https://github.com/AvaLovelace1/LegoGPT.git@c95d35119d98ee4833d2c74d8d6046e5835c2c1c
|
30 |
+
markdown-it-py==3.0.0 ; sys_platform != 'emscripten'
|
31 |
+
markupsafe==3.0.2
|
32 |
+
mdurl==0.1.2 ; sys_platform != 'emscripten'
|
33 |
+
mpmath==1.3.0
|
34 |
+
networkx==3.4.2
|
35 |
+
numpy==1.26.4
|
36 |
+
nvidia-cublas-cu12==12.6.4.1 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
37 |
+
nvidia-cuda-cupti-cu12==12.6.80 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
38 |
+
nvidia-cuda-nvrtc-cu12==12.6.77 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
39 |
+
nvidia-cuda-runtime-cu12==12.6.77 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
40 |
+
nvidia-cudnn-cu12==9.5.1.17 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
41 |
+
nvidia-cufft-cu12==11.3.0.4 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
42 |
+
nvidia-cufile-cu12==1.11.1.6 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
43 |
+
nvidia-curand-cu12==10.3.7.77 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
44 |
+
nvidia-cusolver-cu12==11.7.1.2 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
45 |
+
nvidia-cusparse-cu12==12.5.4.2 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
46 |
+
nvidia-cusparselt-cu12==0.6.3 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
47 |
+
nvidia-nccl-cu12==2.26.2 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
48 |
+
nvidia-nvjitlink-cu12==12.6.85 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
49 |
+
nvidia-nvtx-cu12==12.6.77 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
50 |
+
orjson==3.10.18
|
51 |
+
packaging==25.0
|
52 |
+
pandas==2.2.3
|
53 |
+
peft==0.15.2
|
54 |
+
pillow==11.2.1
|
55 |
+
psutil==7.0.0
|
56 |
+
pycparser==2.22 ; platform_python_implementation == 'PyPy'
|
57 |
+
pydantic==2.11.4
|
58 |
+
pydantic-core==2.33.2
|
59 |
+
pydub==0.25.1
|
60 |
+
pygments==2.19.1 ; sys_platform != 'emscripten'
|
61 |
+
python-dateutil==2.9.0.post0
|
62 |
+
python-multipart==0.0.20
|
63 |
+
pytz==2025.2
|
64 |
+
pyyaml==6.0.2
|
65 |
+
regex==2024.11.6
|
66 |
+
requests==2.32.3
|
67 |
+
rich==14.0.0 ; sys_platform != 'emscripten'
|
68 |
+
ruff==0.11.8 ; sys_platform != 'emscripten'
|
69 |
+
safehttpx==0.1.6
|
70 |
+
safetensors==0.5.3
|
71 |
+
semantic-version==2.10.0
|
72 |
+
setuptools==80.4.0 ; (python_full_version >= '3.12' and platform_machine != 'x86_64') or (python_full_version >= '3.12' and sys_platform != 'linux') or (platform_machine == 'x86_64' and sys_platform == 'linux')
|
73 |
+
shellingham==1.5.4 ; sys_platform != 'emscripten'
|
74 |
+
six==1.17.0
|
75 |
+
sniffio==1.3.1
|
76 |
+
starlette==0.46.2
|
77 |
+
sympy==1.14.0
|
78 |
+
tokenizers==0.21.1
|
79 |
+
tomlkit==0.13.2
|
80 |
+
torch==2.7.0
|
81 |
+
tqdm==4.67.1
|
82 |
+
transformers==4.51.3
|
83 |
+
triton==3.3.0 ; platform_machine == 'x86_64' and sys_platform == 'linux'
|
84 |
+
typer==0.15.3 ; sys_platform != 'emscripten'
|
85 |
+
typing-extensions==4.13.2
|
86 |
+
typing-inspection==0.4.0
|
87 |
+
tzdata==2025.2
|
88 |
+
urllib3==2.4.0
|
89 |
+
uvicorn==0.34.2 ; sys_platform != 'emscripten'
|
90 |
+
websockets==15.0.1
|
91 |
+
zstandard==0.23.0
|
uv.lock
ADDED
The diff for this file is too large to render.
See raw diff
|
|