File size: 12,140 Bytes
0b8bda6 bf25589 0b8bda6 e909dca 0b8bda6 e909dca 0b8bda6 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
---
datasets:
- lamm-mit/Bioinspired3D
language:
- en
base_model:
- meta-llama/Llama-3.2-3B-Instruct
---
# Bioinspired3D
Fine-tuned version of meta-llama/Llama-3.2-3B-Instruct using LoRA adapters for Blender code generation for bioinspired 3D models.
## Abstract
Generative AI has made rapid progress in text, image, and video synthesis, yet text-to-3D modeling for
scientific design remains particularly challenging due to limited controllability and high computational
cost. Most existing 3D generative methods rely on meshes, voxels, or point clouds which can be costly
to train and difficult to control. We introduce Bioinspired123D, a lightweight and modular code-
as-geometry pipeline that generates fabricable 3D structures directly through parametric programs
rather than dense visual representations. At the core of Bioinspired123D is Bioinspired3D, a compact
language model finetuned to translate natural language design cues into Blender Python scripts
encoding smooth, biologically inspired geometries. We curate a domain-specific dataset of over
4,000 bioinspired and geometric design scripts spanning helical, cellular, and tubular motifs with
parametric variability. The dataset is expanded and validated through an automated LLM-driven,
Blender-based quality control pipeline. Bioinspired3D is then embedded in a graph-based agentic
framework that integrates multimodal retrieval-augmented generation and a vision–language model
critic to iteratively evaluate, critique, and repair generated scripts. We evaluate performance on a new
benchmark for 3D geometry script generation and show that Bioinspired123D demonstrates a near
fourfold improvement over its unfinetuned base model, while also outperforming substantially larger
state-of-the-art language models despite using far fewer parameters and compute. By prioritizing
code-as-geometry representations, Bioinspired123D enables compute-efficient, controllable, and
interpretable text-to-3D generation, lowering barriers to AI driven scientific discovery in materials
and structural design.
## What’s in this repo (Hugging Face)
This Hugging Face release contains **Bioinspired3D only**: a LoRA adapter that you load on top of the base model to generate **Blender Python scripts from natural-language prompts**.
For the full **Bioinspired123D** agentic framework (retrieval + VLM critic + iterative repair), see the GitHub repo:
https://github.com/lamm-mit/Bioinspired123D . For training and evaluation scripts, see also the project GitHub.
## Usage
### Install
```bash
pip install -U transformers accelerate peft torch
```
### Load the base model + LoRA adapter
```bash
from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel
import torch
BASE_MODEL = "meta-llama/Llama-3.2-3B-Instruct"
LORA_ADAPTER = "rachelkluu/bioinspired3D"
# Set this to your preferred device, e.g. "cuda:0" or "cpu"
DEVICE_3D = "cuda:0"
bio3d_tok = AutoTokenizer.from_pretrained(BASE_MODEL)
base_model = AutoModelForCausalLM.from_pretrained(
BASE_MODEL,
torch_dtype=torch.float16,
device_map={"": DEVICE_3D},
)
bio3d_model = PeftModel.from_pretrained(base_model, LORA_ADAPTER)
bio3d_model.eval()
def format_input(prompt: str) -> str:
return (
"<|begin_of_text|><|start_header_id|>system<|end_header_id|>\n\n"
"You are a helpful assistant<|eot_id|>"
"<|start_header_id|>user<|end_header_id|>\n\n"
f"{prompt}<|eot_id|>"
"<|start_header_id|>assistant<|end_header_id|>\n\n"
)
```
### Load utility functions
```bash
def extract_blender_code(model_out: str) -> str:
matches = list(re.finditer(r"```python\s*(.*?)```", model_out, flags=re.DOTALL))
if matches:
return matches[-1].group(1).strip()
pos = model_out.rfind("import bpy")
return model_out[pos:].strip() if pos != -1 else model_out.strip()
def clean_blender_code(text: str) -> str:
if not text:
return "import bpy"
code = text.strip()
code = code.replace("```python", "").replace("```", "")
code = re.sub(r"[\x00-\x08\x0b-\x1f]", "", code)
if not code.lstrip().startswith("import bpy"):
code = "import bpy\n" + code
return code
```
### Generate Blender code from a natural-language prompt
```bash
prompt = """Write Blender code to make a cellular structure."""
formatted = format_input(prompt)
inputs = bio3d_tok(formatted, return_tensors="pt").to(bio3d_model.device)
with torch.no_grad():
outputs = bio3d_model.generate(
**inputs,
max_new_tokens=2048,
do_sample=True,
temperature=0.1,
top_p=0.9,
)
raw = bio3d_tok.decode(outputs[0], skip_special_tokens=True)
raw_code = extract_blender_code(raw)
blender_code = clean_blender_code(raw_code)
print(blender_code)
```
### Prompting tips
Input: Natural language design intent (for example: “tubular structure with noisy placement”, “helical material with cylindrical fibers”, “smoothed cellular structure”).
Output: A Blender Python script (intended to be executed in Blender) that constructs the requested geometry.
To encourage explicit reasoning, append a variant of: “Think step by step.” to the end of your prompt. For example: "Write Blender code to make a tubular structure with z-aligned tubules. Think step by step."
## Sample output #1
### Example prompt
```text
Write Blender code to make a cellular structure with smooth curves and layers on top and bottom
```
### Example model output (Blender Python)
```python
import bpy
import addon_utils
# Clear the scene
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
# Parameters for the sandwich structure
strut_thickness = 0.2 # Thickness of the struts
smoothness_level = 3 # Level of smoothness
slab_thickness = 0.1 # Thickness of the top and bottom slabs
def create_cellular_sandwich():
# Function to create a smooth cellular sandwich structure.
# Steps:
# 1. Create a cube.
# 2. Fracture the cube into pieces.
# 3. Apply wireframe modifier for cellular effect.
# 4. Apply subsurface modifier for smoothing.
# 5. Create top and bottom slabs.
# Enable the Fracture Cell add-on
addon_utils.enable('object_fracture_cell')
# Create a cube
bpy.ops.mesh.primitive_cube_add()
cube = bpy.context.active_object
# Scale the cube
cube.scale = (1, 1, 0.75)
bpy.ops.object.transform_apply(scale=True)
# Fracture the cube
bpy.ops.object.add_fracture_cell_objects(
source={'PARTICLE_OWN'},
source_limit=100,
source_noise=0.5,
cell_scale=(1, 1, 1),
recursion=0,
recursion_source_limit=8,
recursion_clamp=250,
recursion_chance=0.25,
recursion_chance_select='SIZE_MIN',
use_smooth_faces=False,
use_sharp_edges=True,
use_sharp_edges_apply=True,
use_data_match=True,
use_island_split=True,
margin=0.001,
material_index=0,
use_interior_vgroup=False,
mass_mode='VOLUME',
mass=1,
use_recenter=True,
use_remove_original=True,
collection_name='',
use_debug_points=False,
use_debug_redraw=True,
use_debug_bool=False
)
# Remove the original cube
if cube and cube.name in bpy.data.objects:
bpy.data.objects.remove(cube, do_unlink=True)
# Join fractured pieces
bpy.ops.object.select_all(action='DESELECT')
for obj in bpy.context.scene.objects:
if obj.type == 'MESH':
obj.select_set(True)
bpy.context.view_layer.objects.active = obj
bpy.ops.object.join()
# Clean up geometry
active_mesh = bpy.context.view_layer.objects.active
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.remove_doubles(threshold=0.2)
bpy.ops.mesh.dissolve_limited()
bpy.ops.object.mode_set(mode='OBJECT')
# Wireframe Modifier
wireframe_mod = active_mesh.modifiers.new(name='Wireframe', type='WIREFRAME')
wireframe_mod.thickness = strut_thickness
wireframe_mod.offset = -1
wireframe_mod.use_even_offset = False
wireframe_mod.use_relative_offset = True
wireframe_mod.use_replace = True
bpy.ops.object.convert(target='MESH')
# Subsurface Modifier
subsurf_mod = active_mesh.modifiers.new(name='Subdivision', type='SUBSURF')
subsurf_mod.levels = smoothness_level
subsurf_mod.render_levels = smoothness_level
# Create slabs
slab_height = 1.5
bottom_slab_z = -slab_height / 2 - slab_thickness / 2
top_slab_z = slab_height / 2 + slab_thickness / 2
# Bottom slab
bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, bottom_slab_z))
bottom_slab = bpy.context.active_object
bottom_slab.scale = (1, 1, slab_thickness / 2)
bpy.ops.object.transform_apply(scale=True)
# Top slab
bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, top_slab_z))
top_slab = bpy.context.active_object
top_slab.scale = (1, 1, slab_thickness / 2)
bpy.ops.object.transform_apply(scale=True)
# Create the sandwich structure
create_cellular_sandwich()
```
### Rendered example (image)

## Sample output #2
### Example prompt
```text
Write Blender code to make a helical bioinspired structure with flat rectangular struts in each layer
```
### Example model output (Blender Python)
```python
import bpy
import math
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
# Parameters for the helical fiber structure
ply_count = 7 # Number of plies in the structure
angle_increment = 10 # Rotation angle for each ply
fiber_form ='rect' # Shape of the fibers
# Dimensions of the structure
structure_height = 2 # Total height of the structure
plate_dimension = 2 # Width and length of each plate
thickness_per_ply = structure_height / ply_count # Thickness of each ply
fiber_gap = 0.01 # Gap between fibers
def create_fiber(form, diameter, x, y, z, thickness):
if form =='rect':
bpy.ops.mesh.primitive_cube_add(size=1.0, location=(x, y, z), rotation=(0, math.radians(90), 0))
fiber = bpy.context.object
fiber.dimensions = (thickness, diameter, plate_dimension)
return fiber
def generate_ply(index):
# Generate a ply of fibers in a helical arrangement.
z_position = index * thickness_per_ply
rotation_angle = index * angle_increment
bpy.ops.object.empty_add(type='PLAIN_AXES', location=(0, 0, z_position))
empty_object = bpy.context.object
fiber_diameter = thickness_per_ply
fiber_distance = fiber_diameter + fiber_gap
fiber_count = max(1, int(plate_dimension / fiber_distance))
total_fiber_space = fiber_count * fiber_distance
start_y_position = -plate_dimension / 2 + fiber_distance / 2 + (plate_dimension - total_fiber_space) / 2
for i in range(fiber_count):
fiber_y_center = start_y_position + i * fiber_distance
fiber_instance = create_fiber(fiber_form, fiber_diameter, 0, fiber_y_center, z_position, thickness_per_ply)
fiber_instance.parent = empty_object
fiber_instance.matrix_parent_inverse = empty_object.matrix_world.inverted()
empty_object.rotation_euler[2] = math.radians(rotation_angle)
return empty_object
# Create the helical structure
for i in range(ply_count):
generate_ply(i)
```
### Rendered example (image)

## Notes:
This adapter is meant to be used with the specified base model. Generated scripts should be treated like code: run in a sandboxed environment and validate geometry as needed.
## Citation
If you use Bioinspired3D or the broader Bioinspired123D framework in your work, please cite:
```bibtex
@article{luu2026bioinspired123d,
title={Bioinspired123D: Generative 3D Modeling System for Bioinspired Structures},
author={Luu, Rachel K. and Buehler, Markus J.},
year={2026}
}
|