B3rrYang/3D-SynthPlace_indoor_scenes_dataset
Updated • 544 • 2
An open-source reproduction of OptiScene (OptiScene: LLM-driven Indoor Scene Layout Generation via Scaled Human-aligned Data Synthesis and Multi-Stage Preference Optimization, NeurIPS 2025, arXiv:2506.07570) built on Qwen/Qwen3-8B and trained on 8 × NVIDIA A100-SXM4-80GB GPUs.
/): Full 16 GB merged bfloat16 model weights after all three training stages (Stage 1 SFT + Stage 2 DPO-Stage1 + Stage 3 DPO-Stage2), ready for direct AutoModelForCausalLM.from_pretrained("Prisoner/OptiScene-Qwen3-8B") or vLLM inference.lora_adapters/stage1_sft/: Stage 1 SFT LoRA adapter ($r=16, \alpha=32$).lora_adapters/stage2_dpo1/: Stage 2 DPO-Stage1 LoRA adapter ($r=32, \alpha=16$, trained on top of Stage 1 merged model).lora_adapters/stage3_dpo2/: Stage 3 DPO-Stage2 LoRA adapter ($r=32, \alpha=16$, trained on top of Stage 2 merged model).eval_results_summary.json: Quantitative evaluation results across 120 stratified test scenes (Bedroom, Living room, Kitchen, Bathroom).sample_response.txt: Sample 3D living-room layout output generated by the final model (OOR = 0.0099).| Stage | Dataset | Samples (80/20 split) | LoRA Config | Epochs | Final Metric |
|---|---|---|---|---|---|
| Stage 1: SFT (w/ Reasoning) | sft_prompts.json |
12,253 | $r=16, \alpha=32$ | 1 | train_loss = 0.3144, token_acc = 95.54% |
| Stage 2: DPO Stage 1 | dpo_prompts.json |
7,951 | $r=32, \alpha=16$ | 10 (1,990 steps) | train_loss = 0.2468, rewards/margins = 8.05 |
| Stage 3: DPO Stage 2 | dpo2_prompts.json |
8,410 | $r=32, \alpha=16$ | 10 (2,110 steps) | train_loss = 0.058, rewards/margins = 9.86 |
Evaluated across 30 scenes per room type (Bedroom, Living room, Kitchen, Bathroom) using the Object Overlap Rate ($\text{OOR} \downarrow$) metric defined in Appendix D.2 of the OptiScene paper:
| Model Stage | Overall OOR ↓ | Bedroom OOR ↓ | Living room OOR ↓ | Kitchen OOR ↓ | Bathroom OOR ↓ | Valid JSON % ↑ |
|---|---|---|---|---|---|---|
| Stage 1: SFT (w/ Reasoning) | 0.1305 |
0.2028 |
0.1478 |
0.1251 |
0.0464 |
100.0% |
| Stage 2: SFT + DPO Stage 1 | 0.0762 (-41.6%) |
0.0933 |
0.0756 |
0.1146 |
0.0212 |
100.0% |
| Stage 3: OptiScene (SFT + DPO1 + DPO2) | 0.0706 (-45.9%) |
0.0799 (-60.6%) |
0.0774 |
0.0927 (-25.9%) |
0.0325 |
100.0% |
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "Prisoner/OptiScene-Qwen3-8B"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id,
torch_dtype=torch.bfloat16,
device_map="auto",
)
messages = [{"role": "user", "content": prompt}]
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
enable_thinking=False,
)
inputs = tokenizer([text], return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_new_tokens=2048, do_sample=False)
print(tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True))