[AGORA] Full export: pth + safetensors + ONNX + TRT fp16 + TRT fp32
Browse files- .gitattributes +4 -0
- README.md +75 -161
- configs/paper.toml +46 -0
- logs/training_metrics.json +5 -5
- onnx/agora_planner_v1.onnx +3 -0
- onnx/agora_planner_v1.onnx.data +3 -0
- pytorch/agora_planner_v1.pth +3 -0
- pytorch/agora_planner_v1.safetensors +3 -0
- pytorch/config.json +61 -0
- pytorch/generation_config.json +13 -0
- pytorch/tokenizer.json +3 -0
- pytorch/tokenizer_config.json +30 -0
- scripts/eval_planner.py +0 -1
- scripts/export_all.py +245 -0
- scripts/generate_planning_data.py +6 -7
- scripts/train_planner.py +12 -7
- tensorrt/agora_planner_v1_trt_fp16.engine +3 -0
- tensorrt/agora_planner_v1_trt_fp32.engine +3 -0
.gitattributes
CHANGED
|
@@ -35,3 +35,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
logs/planning_train.jsonl filter=lfs diff=lfs merge=lfs -text
|
| 37 |
planning_train.jsonl filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
logs/planning_train.jsonl filter=lfs diff=lfs merge=lfs -text
|
| 37 |
planning_train.jsonl filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
onnx/agora_planner_v1.onnx.data filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
pytorch/tokenizer.json filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
tensorrt/agora_planner_v1_trt_fp16.engine filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
tensorrt/agora_planner_v1_trt_fp32.engine filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -5,196 +5,110 @@ tags:
|
|
| 5 |
- agora
|
| 6 |
- multi-robot
|
| 7 |
- task-planning
|
| 8 |
-
- coordination
|
| 9 |
- lora
|
| 10 |
-
- qwen2.5
|
| 11 |
- robot-flow-labs
|
| 12 |
-
library_name:
|
| 13 |
-
pipeline_tag:
|
| 14 |
license: apache-2.0
|
| 15 |
base_model: Qwen/Qwen2.5-1.5B-Instruct
|
| 16 |
-
model-index:
|
| 17 |
-
- name: agora-planner-v1
|
| 18 |
-
results:
|
| 19 |
-
- task:
|
| 20 |
-
type: text-generation
|
| 21 |
-
name: Multi-Robot Task Planning
|
| 22 |
-
metrics:
|
| 23 |
-
- name: Format Valid Rate
|
| 24 |
-
type: accuracy
|
| 25 |
-
value: 1.0
|
| 26 |
-
- name: Task Coverage
|
| 27 |
-
type: accuracy
|
| 28 |
-
value: 0.533
|
| 29 |
-
- name: Train Loss
|
| 30 |
-
type: loss
|
| 31 |
-
value: 0.234
|
| 32 |
---
|
| 33 |
|
| 34 |
-
# AGORA — Multi-Robot Task Planner
|
| 35 |
|
| 36 |
-
Part of the [ANIMA
|
| 37 |
|
| 38 |
## Overview
|
| 39 |
|
| 40 |
-
AGORA (
|
| 41 |
-
(Spatio-Temporal-Embodiment Memory) framework for multi-robot collaboration. This repo
|
| 42 |
-
contains the LoRA-finetuned planner model and all training artifacts for reproducibility.
|
| 43 |
|
| 44 |
-
|
| 45 |
-
failure history) and a set of task requests, then produces optimal task-to-robot
|
| 46 |
-
assignments with structured JSON reasoning.
|
| 47 |
|
| 48 |
-
|
|
|
|
| 49 |
|
| 50 |
-
|
| 51 |
-
a server disk cleanup. **All training data, scripts, configs, and metrics are preserved**
|
| 52 |
-
for full reproducibility. Retrain with:
|
| 53 |
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
| Metric | Value |
|
| 71 |
-
|--------|-------|
|
| 72 |
-
| Train loss | 0.234 |
|
| 73 |
-
| Train runtime | 1h 50m (6620s) |
|
| 74 |
-
| Train samples/sec | 2.27 |
|
| 75 |
-
| Total steps | 939 (3 epochs) |
|
| 76 |
-
| Eval format valid rate | **100%** |
|
| 77 |
-
| Eval task coverage | 53.3% |
|
| 78 |
-
| Eval robot match rate | 18.7% |
|
| 79 |
-
| Avg inference time | 4.50s |
|
| 80 |
-
|
| 81 |
-
**Analysis:** The model produces valid JSON 100% of the time (perfect format learning).
|
| 82 |
-
Task allocation quality differs from the heuristic baseline, expected for a 1.5B model
|
| 83 |
-
learning complex multi-factor optimization. Recommended improvements: more training data
|
| 84 |
-
(10k-50k examples), larger base model (Qwen2.5-7B), or RLHF/DPO stage.
|
| 85 |
-
|
| 86 |
-
## Repository Contents
|
| 87 |
-
|
| 88 |
-
```
|
| 89 |
-
.
|
| 90 |
-
├── README.md # This model card
|
| 91 |
-
├── configs/
|
| 92 |
-
│ └── training.toml # Full training configuration
|
| 93 |
-
├── logs/
|
| 94 |
-
│ ├── training_metrics.json # Final training metrics
|
| 95 |
-
│ ├── planning_train.jsonl # 5000 training examples
|
| 96 |
-
│ └── planning_eval.jsonl # 200 evaluation examples
|
| 97 |
-
├── reports/
|
| 98 |
-
│ └── planner_eval.json # Evaluation results
|
| 99 |
-
├── scripts/
|
| 100 |
-
│ ├── train_planner.py # LoRA fine-tuning script
|
| 101 |
-
│ ├── eval_planner.py # Evaluation script
|
| 102 |
-
│ └── generate_planning_data.py # Synthetic data generator
|
| 103 |
-
├── pytorch/ # (empty — retrain to populate)
|
| 104 |
-
│ ├── merged/ # Merged model weights
|
| 105 |
-
│ └── lora_adapter/ # LoRA adapter only
|
| 106 |
-
├── onnx/ # (empty — export after retrain)
|
| 107 |
-
├── checkpoints/ # (empty — retrain to populate)
|
| 108 |
-
└── tensorrt/ # (generate on target hardware)
|
| 109 |
-
```
|
| 110 |
-
|
| 111 |
-
## Reproducing the Training
|
| 112 |
-
|
| 113 |
-
### Prerequisites
|
| 114 |
-
- 2x NVIDIA L4 (23GB each) or equivalent
|
| 115 |
-
- CUDA 12.4, PyTorch 2.6.0
|
| 116 |
-
- `transformers`, `peft`, `trl`, `datasets`
|
| 117 |
-
|
| 118 |
-
### Step 1: Generate training data (if starting fresh)
|
| 119 |
-
```python
|
| 120 |
-
python scripts/generate_planning_data.py
|
| 121 |
-
```
|
| 122 |
|
| 123 |
-
##
|
| 124 |
-
```bash
|
| 125 |
-
CUDA_VISIBLE_DEVICES=0,1 python scripts/train_planner.py \
|
| 126 |
-
--model Qwen/Qwen2.5-1.5B-Instruct \
|
| 127 |
-
--epochs 3 \
|
| 128 |
-
--batch-size 4 \
|
| 129 |
-
--grad-accum 4 \
|
| 130 |
-
--lr 2e-4 \
|
| 131 |
-
--lora-r 16 \
|
| 132 |
-
--lora-alpha 32
|
| 133 |
-
```
|
| 134 |
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
``
|
|
|
|
|
|
|
|
|
|
| 139 |
|
| 140 |
-
##
|
| 141 |
-
```python
|
| 142 |
-
# SafeTensors
|
| 143 |
-
from safetensors.torch import save_file
|
| 144 |
-
save_file(model.state_dict(), "pytorch/agora_planner_v1.safetensors")
|
| 145 |
-
|
| 146 |
-
# ONNX
|
| 147 |
-
torch.onnx.export(model, dummy_input, "onnx/agora_planner_v1.onnx", opset_version=17)
|
| 148 |
-
```
|
| 149 |
-
|
| 150 |
-
## Usage (after weights are available)
|
| 151 |
|
| 152 |
```python
|
| 153 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 154 |
|
| 155 |
-
model = AutoModelForCausalLM.from_pretrained(
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
|
| 165 |
inputs = tokenizer(prompt, return_tensors="pt")
|
| 166 |
outputs = model.generate(**inputs, max_new_tokens=512)
|
| 167 |
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
|
| 168 |
```
|
| 169 |
|
| 170 |
-
##
|
| 171 |
|
| 172 |
-
Each example in `planning_train.jsonl` is a conversation turn:
|
| 173 |
-
|
| 174 |
-
```json
|
| 175 |
-
{
|
| 176 |
-
"messages": [
|
| 177 |
-
{"role": "system", "content": "You are AGORA, a multi-robot task planner..."},
|
| 178 |
-
{"role": "user", "content": "Team state: {...}\nTasks: [...]"},
|
| 179 |
-
{"role": "assistant", "content": "{\"assignments\": [...], \"reasoning\": \"...\"}"}
|
| 180 |
-
]
|
| 181 |
-
}
|
| 182 |
```
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 198 |
|
| 199 |
## License
|
| 200 |
|
|
|
|
| 5 |
- agora
|
| 6 |
- multi-robot
|
| 7 |
- task-planning
|
|
|
|
| 8 |
- lora
|
|
|
|
| 9 |
- robot-flow-labs
|
| 10 |
+
library_name: pytorch
|
| 11 |
+
pipeline_tag: robotics
|
| 12 |
license: apache-2.0
|
| 13 |
base_model: Qwen/Qwen2.5-1.5B-Instruct
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
---
|
| 15 |
|
| 16 |
+
# AGORA Planner v1 — ANIMA Multi-Robot Task Planner
|
| 17 |
|
| 18 |
+
Part of the [ANIMA Robotics Suite](https://github.com/RobotFlow-Labs) by Robot Flow Labs.
|
| 19 |
|
| 20 |
## Overview
|
| 21 |
|
| 22 |
+
AGORA (Unified STEM Memory Framework) is a Wave-5 coordination module for multi-robot collaboration. This checkpoint is a **LoRA fine-tuned Qwen2.5-1.5B-Instruct** model trained to assign tasks to heterogeneous robot teams based on capabilities, battery, location, and failure history.
|
|
|
|
|
|
|
| 23 |
|
| 24 |
+
## Paper
|
|
|
|
|
|
|
| 25 |
|
| 26 |
+
**RoboOS-NeXT: Toward Lifelong, Scalable, and Robust Multi-Robot Collaboration** (arXiv:2510.26536)
|
| 27 |
+
Huajie Tan et al., October 2025
|
| 28 |
|
| 29 |
+
## Training
|
|
|
|
|
|
|
| 30 |
|
| 31 |
+
| Parameter | Value |
|
| 32 |
+
|-----------|-------|
|
| 33 |
+
| Base model | Qwen/Qwen2.5-1.5B-Instruct |
|
| 34 |
+
| Method | LoRA (r=16, alpha=32) |
|
| 35 |
+
| Training data | 5000 synthetic planning examples |
|
| 36 |
+
| Eval data | 200 examples |
|
| 37 |
+
| Epochs | 3 (834 steps) |
|
| 38 |
+
| Batch size | 6 per device × 3 grad accum |
|
| 39 |
+
| Learning rate | 2e-4 (cosine + 5% warmup) |
|
| 40 |
+
| Precision | bf16 |
|
| 41 |
+
| Hardware | 3x NVIDIA L4 (23GB each) |
|
| 42 |
+
| Train loss | 0.237 |
|
| 43 |
+
| Train runtime | 7338s (~2h) |
|
| 44 |
+
| Token accuracy | 92% |
|
| 45 |
+
| Format valid rate | 100% |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
+
## Exported Formats
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
+
| Format | Path | Size | Use Case |
|
| 50 |
+
|--------|------|------|----------|
|
| 51 |
+
| SafeTensors | `pytorch/agora_planner_v1.safetensors` | 2.9 GB | Fast loading, safe |
|
| 52 |
+
| PyTorch (.pth) | `pytorch/agora_planner_v1.pth` | 2.9 GB | Training, fine-tuning |
|
| 53 |
+
| ONNX | `onnx/agora_planner_v1.onnx` + `.onnx.data` | 5.8 GB | Cross-platform inference |
|
| 54 |
+
| TensorRT FP16 | `tensorrt/agora_planner_v1_trt_fp16.engine` | 3.4 GB | Edge deployment (Jetson/L4) |
|
| 55 |
+
| TensorRT FP32 | `tensorrt/agora_planner_v1_trt_fp32.engine` | 6.7 GB | Full precision inference |
|
| 56 |
|
| 57 |
+
## Usage
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
```python
|
| 60 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 61 |
|
| 62 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 63 |
+
"ilessio-aiflowlab/project_agora",
|
| 64 |
+
subfolder="pytorch",
|
| 65 |
+
trust_remote_code=True,
|
| 66 |
+
)
|
| 67 |
+
tokenizer = AutoTokenizer.from_pretrained(
|
| 68 |
+
"ilessio-aiflowlab/project_agora",
|
| 69 |
+
subfolder="pytorch",
|
| 70 |
+
trust_remote_code=True,
|
| 71 |
+
)
|
| 72 |
+
|
| 73 |
+
prompt = """You are AGORA, a multi-robot task planner.
|
| 74 |
+
Given robots: bot_a (manipulator, 90% battery), bot_b (mobile base, 60% battery)
|
| 75 |
+
Tasks: pick_object (requires manipulation), navigate_to_door (requires navigation)
|
| 76 |
+
Assign each task to the best robot."""
|
| 77 |
|
| 78 |
inputs = tokenizer(prompt, return_tensors="pt")
|
| 79 |
outputs = model.generate(**inputs, max_new_tokens=512)
|
| 80 |
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
|
| 81 |
```
|
| 82 |
|
| 83 |
+
## Files
|
| 84 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 85 |
```
|
| 86 |
+
├── README.md # This file
|
| 87 |
+
├── pytorch/
|
| 88 |
+
│ ├── agora_planner_v1.safetensors # SafeTensors (2.9 GB)
|
| 89 |
+
│ ├── agora_planner_v1.pth # PyTorch weights (2.9 GB)
|
| 90 |
+
│ ├── config.json # Model config
|
| 91 |
+
│ ├── tokenizer.json # Tokenizer
|
| 92 |
+
│ └── tokenizer_config.json
|
| 93 |
+
├── onnx/
|
| 94 |
+
│ ├── agora_planner_v1.onnx # ONNX model (4 MB + external data)
|
| 95 |
+
│ └── agora_planner_v1.onnx.data # ONNX external weights (5.8 GB)
|
| 96 |
+
├── tensorrt/
|
| 97 |
+
│ ├── agora_planner_v1_trt_fp16.engine # TRT FP16 (3.4 GB)
|
| 98 |
+
│ └── agora_planner_v1_trt_fp32.engine # TRT FP32 (6.7 GB)
|
| 99 |
+
├── configs/
|
| 100 |
+
│ ├── paper.toml # Paper-aligned config
|
| 101 |
+
│ └── training.toml # Training config
|
| 102 |
+
├── logs/
|
| 103 |
+
│ ├── training_metrics.json # Final metrics
|
| 104 |
+
│ ├── planning_train.jsonl # Training data (5000 examples)
|
| 105 |
+
│ └── planning_eval.jsonl # Eval data (200 examples)
|
| 106 |
+
└── scripts/
|
| 107 |
+
├── train_planner.py # LoRA training script
|
| 108 |
+
├── eval_planner.py # Evaluation script
|
| 109 |
+
├��─ generate_planning_data.py # Synthetic data generator
|
| 110 |
+
└── export_all.py # Export pipeline
|
| 111 |
+
```
|
| 112 |
|
| 113 |
## License
|
| 114 |
|
configs/paper.toml
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# AGORA Planner LoRA Training Config — Paper-aligned
|
| 2 |
+
# Based on RoboOS-NeXT (arXiv:2510.26536)
|
| 3 |
+
|
| 4 |
+
[training]
|
| 5 |
+
batch_size = "auto"
|
| 6 |
+
learning_rate = 0.0001
|
| 7 |
+
epochs = 3
|
| 8 |
+
optimizer = "adamw"
|
| 9 |
+
weight_decay = 0.01
|
| 10 |
+
scheduler = "cosine"
|
| 11 |
+
warmup_steps = 50
|
| 12 |
+
precision = "bf16"
|
| 13 |
+
gradient_accumulation = 1
|
| 14 |
+
max_grad_norm = 1.0
|
| 15 |
+
seed = 42
|
| 16 |
+
|
| 17 |
+
[model]
|
| 18 |
+
base_model = "Qwen/Qwen2.5-1.5B-Instruct"
|
| 19 |
+
lora_r = 16
|
| 20 |
+
lora_alpha = 32
|
| 21 |
+
lora_dropout = 0.05
|
| 22 |
+
target_modules = ["q_proj", "v_proj", "k_proj", "o_proj"]
|
| 23 |
+
|
| 24 |
+
[data]
|
| 25 |
+
train_samples = 5000
|
| 26 |
+
eval_samples = 200
|
| 27 |
+
train_path = "/mnt/artifacts-datai/logs/project_agora/planning_train.jsonl"
|
| 28 |
+
eval_path = "/mnt/artifacts-datai/logs/project_agora/planning_eval.jsonl"
|
| 29 |
+
num_workers = 4
|
| 30 |
+
pin_memory = true
|
| 31 |
+
|
| 32 |
+
[checkpoint]
|
| 33 |
+
output_dir = "/mnt/artifacts-datai/checkpoints/project_agora"
|
| 34 |
+
save_every_n_steps = 200
|
| 35 |
+
keep_top_k = 2
|
| 36 |
+
metric = "eval_loss"
|
| 37 |
+
mode = "min"
|
| 38 |
+
|
| 39 |
+
[early_stopping]
|
| 40 |
+
enabled = true
|
| 41 |
+
patience = 10
|
| 42 |
+
min_delta = 0.0001
|
| 43 |
+
|
| 44 |
+
[logging]
|
| 45 |
+
log_dir = "/mnt/artifacts-datai/logs/project_agora"
|
| 46 |
+
tensorboard_dir = "/mnt/artifacts-datai/tensorboard/project_agora"
|
logs/training_metrics.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
{
|
| 2 |
-
"train_runtime":
|
| 3 |
-
"train_samples_per_second": 2.
|
| 4 |
-
"train_steps_per_second": 0.
|
| 5 |
-
"total_flos":
|
| 6 |
-
"train_loss": 0.
|
| 7 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"train_runtime": 7338.4584,
|
| 3 |
+
"train_samples_per_second": 2.044,
|
| 4 |
+
"train_steps_per_second": 0.114,
|
| 5 |
+
"total_flos": 1.0324760367127757e+17,
|
| 6 |
+
"train_loss": 0.23725478068816006
|
| 7 |
}
|
onnx/agora_planner_v1.onnx
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b62ee8a18c9bd2a064e33ba4e7312fc4331d8323d2504ce340add944a1525d9d
|
| 3 |
+
size 4139160
|
onnx/agora_planner_v1.onnx.data
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:55110a522187029e80fcf3804f3379af378cd400c97595459cb1ba76fc638324
|
| 3 |
+
size 6174867456
|
pytorch/agora_planner_v1.pth
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:896ae923da960693dcf8942914b203df4967db9183b8cde91fa68f5d9bec1e74
|
| 3 |
+
size 3087558323
|
pytorch/agora_planner_v1.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:a20d0e9fe6be53ac64af582a5ef2b0d0ae5807325265a37d6fbf9f367cd88cb6
|
| 3 |
+
size 3087467144
|
pytorch/config.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"Qwen2ForCausalLM"
|
| 4 |
+
],
|
| 5 |
+
"attention_dropout": 0.0,
|
| 6 |
+
"bos_token_id": null,
|
| 7 |
+
"dtype": "bfloat16",
|
| 8 |
+
"eos_token_id": 151645,
|
| 9 |
+
"hidden_act": "silu",
|
| 10 |
+
"hidden_size": 1536,
|
| 11 |
+
"initializer_range": 0.02,
|
| 12 |
+
"intermediate_size": 8960,
|
| 13 |
+
"layer_types": [
|
| 14 |
+
"full_attention",
|
| 15 |
+
"full_attention",
|
| 16 |
+
"full_attention",
|
| 17 |
+
"full_attention",
|
| 18 |
+
"full_attention",
|
| 19 |
+
"full_attention",
|
| 20 |
+
"full_attention",
|
| 21 |
+
"full_attention",
|
| 22 |
+
"full_attention",
|
| 23 |
+
"full_attention",
|
| 24 |
+
"full_attention",
|
| 25 |
+
"full_attention",
|
| 26 |
+
"full_attention",
|
| 27 |
+
"full_attention",
|
| 28 |
+
"full_attention",
|
| 29 |
+
"full_attention",
|
| 30 |
+
"full_attention",
|
| 31 |
+
"full_attention",
|
| 32 |
+
"full_attention",
|
| 33 |
+
"full_attention",
|
| 34 |
+
"full_attention",
|
| 35 |
+
"full_attention",
|
| 36 |
+
"full_attention",
|
| 37 |
+
"full_attention",
|
| 38 |
+
"full_attention",
|
| 39 |
+
"full_attention",
|
| 40 |
+
"full_attention",
|
| 41 |
+
"full_attention"
|
| 42 |
+
],
|
| 43 |
+
"max_position_embeddings": 32768,
|
| 44 |
+
"max_window_layers": 21,
|
| 45 |
+
"model_type": "qwen2",
|
| 46 |
+
"num_attention_heads": 12,
|
| 47 |
+
"num_hidden_layers": 28,
|
| 48 |
+
"num_key_value_heads": 2,
|
| 49 |
+
"pad_token_id": 151643,
|
| 50 |
+
"rms_norm_eps": 1e-06,
|
| 51 |
+
"rope_parameters": {
|
| 52 |
+
"rope_theta": 1000000.0,
|
| 53 |
+
"rope_type": "default"
|
| 54 |
+
},
|
| 55 |
+
"sliding_window": null,
|
| 56 |
+
"tie_word_embeddings": true,
|
| 57 |
+
"transformers_version": "5.5.0",
|
| 58 |
+
"use_cache": false,
|
| 59 |
+
"use_sliding_window": false,
|
| 60 |
+
"vocab_size": 151936
|
| 61 |
+
}
|
pytorch/generation_config.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"do_sample": true,
|
| 3 |
+
"eos_token_id": [
|
| 4 |
+
151645,
|
| 5 |
+
151643
|
| 6 |
+
],
|
| 7 |
+
"pad_token_id": 151643,
|
| 8 |
+
"repetition_penalty": 1.1,
|
| 9 |
+
"temperature": 0.7,
|
| 10 |
+
"top_k": 20,
|
| 11 |
+
"top_p": 0.8,
|
| 12 |
+
"transformers_version": "5.5.0"
|
| 13 |
+
}
|
pytorch/tokenizer.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3fd169731d2cbde95e10bf356d66d5997fd885dd8dbb6fb4684da3f23b2585d8
|
| 3 |
+
size 11421892
|
pytorch/tokenizer_config.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_prefix_space": false,
|
| 3 |
+
"backend": "tokenizers",
|
| 4 |
+
"bos_token": null,
|
| 5 |
+
"clean_up_tokenization_spaces": false,
|
| 6 |
+
"eos_token": "<|im_end|>",
|
| 7 |
+
"errors": "replace",
|
| 8 |
+
"extra_special_tokens": [
|
| 9 |
+
"<|im_start|>",
|
| 10 |
+
"<|im_end|>",
|
| 11 |
+
"<|object_ref_start|>",
|
| 12 |
+
"<|object_ref_end|>",
|
| 13 |
+
"<|box_start|>",
|
| 14 |
+
"<|box_end|>",
|
| 15 |
+
"<|quad_start|>",
|
| 16 |
+
"<|quad_end|>",
|
| 17 |
+
"<|vision_start|>",
|
| 18 |
+
"<|vision_end|>",
|
| 19 |
+
"<|vision_pad|>",
|
| 20 |
+
"<|image_pad|>",
|
| 21 |
+
"<|video_pad|>"
|
| 22 |
+
],
|
| 23 |
+
"is_local": true,
|
| 24 |
+
"model_max_length": 131072,
|
| 25 |
+
"pad_token": "<|endoftext|>",
|
| 26 |
+
"padding_side": "right",
|
| 27 |
+
"split_special_tokens": false,
|
| 28 |
+
"tokenizer_class": "Qwen2Tokenizer",
|
| 29 |
+
"unk_token": null
|
| 30 |
+
}
|
scripts/eval_planner.py
CHANGED
|
@@ -11,7 +11,6 @@ Usage:
|
|
| 11 |
|
| 12 |
from __future__ import annotations
|
| 13 |
|
| 14 |
-
import asyncio
|
| 15 |
import json
|
| 16 |
import os
|
| 17 |
import sys
|
|
|
|
| 11 |
|
| 12 |
from __future__ import annotations
|
| 13 |
|
|
|
|
| 14 |
import json
|
| 15 |
import os
|
| 16 |
import sys
|
scripts/export_all.py
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Export AGORA planner to all formats: safetensors, ONNX, TRT FP16, TRT FP32.
|
| 3 |
+
|
| 4 |
+
Usage: CUDA_VISIBLE_DEVICES=3 python scripts/export_all.py
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
from __future__ import annotations
|
| 8 |
+
|
| 9 |
+
import gc
|
| 10 |
+
import os
|
| 11 |
+
import shutil
|
| 12 |
+
import time
|
| 13 |
+
from pathlib import Path
|
| 14 |
+
|
| 15 |
+
import torch
|
| 16 |
+
|
| 17 |
+
PROJECT = "project_agora"
|
| 18 |
+
ARTIFACTS = "/mnt/artifacts-datai"
|
| 19 |
+
MODEL_DIR = f"{ARTIFACTS}/models/{PROJECT}/agora-planner-v1"
|
| 20 |
+
EXPORT_DIR = f"{ARTIFACTS}/exports/{PROJECT}"
|
| 21 |
+
MERGED_DIR = f"{MODEL_DIR}/merged"
|
| 22 |
+
|
| 23 |
+
os.makedirs(EXPORT_DIR, exist_ok=True)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def export_safetensors():
|
| 27 |
+
"""Export merged model as safetensors (already done by training, verify)."""
|
| 28 |
+
print("\n[1/5] SAFETENSORS CHECK")
|
| 29 |
+
st_files = list(Path(MERGED_DIR).glob("*.safetensors"))
|
| 30 |
+
if st_files:
|
| 31 |
+
total_size = sum(f.stat().st_size for f in st_files)
|
| 32 |
+
print(f" Already exists: {len(st_files)} files, {total_size / 1e9:.2f} GB")
|
| 33 |
+
# Copy to exports
|
| 34 |
+
dst = Path(EXPORT_DIR) / "safetensors"
|
| 35 |
+
dst.mkdir(exist_ok=True)
|
| 36 |
+
for f in st_files:
|
| 37 |
+
shutil.copy2(f, dst / f.name)
|
| 38 |
+
# Also copy config + tokenizer
|
| 39 |
+
for name in ["config.json", "tokenizer.json", "tokenizer_config.json",
|
| 40 |
+
"generation_config.json", "special_tokens_map.json",
|
| 41 |
+
"vocab.json", "merges.txt"]:
|
| 42 |
+
src = Path(MERGED_DIR) / name
|
| 43 |
+
if src.exists():
|
| 44 |
+
shutil.copy2(src, dst / name)
|
| 45 |
+
print(f" Copied to {dst}")
|
| 46 |
+
return True
|
| 47 |
+
else:
|
| 48 |
+
print(" ERROR: No safetensors found in merged dir")
|
| 49 |
+
return False
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def export_pth():
|
| 53 |
+
"""Export as single .pth file."""
|
| 54 |
+
print("\n[2/5] PTH EXPORT")
|
| 55 |
+
from transformers import AutoModelForCausalLM
|
| 56 |
+
|
| 57 |
+
pth_path = Path(EXPORT_DIR) / "agora_planner_v1.pth"
|
| 58 |
+
if pth_path.exists():
|
| 59 |
+
print(f" Already exists: {pth_path} ({pth_path.stat().st_size / 1e9:.2f} GB)")
|
| 60 |
+
return True
|
| 61 |
+
|
| 62 |
+
print(" Loading model...")
|
| 63 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 64 |
+
MERGED_DIR,
|
| 65 |
+
dtype=torch.float16,
|
| 66 |
+
trust_remote_code=True,
|
| 67 |
+
)
|
| 68 |
+
print(f" Saving to {pth_path}...")
|
| 69 |
+
torch.save(model.state_dict(), pth_path)
|
| 70 |
+
size_gb = pth_path.stat().st_size / 1e9
|
| 71 |
+
print(f" Saved: {size_gb:.2f} GB")
|
| 72 |
+
del model
|
| 73 |
+
gc.collect()
|
| 74 |
+
torch.cuda.empty_cache()
|
| 75 |
+
return True
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def export_onnx():
|
| 79 |
+
"""Export to ONNX format using optimum for large model support."""
|
| 80 |
+
print("\n[3/5] ONNX EXPORT")
|
| 81 |
+
|
| 82 |
+
onnx_dir = Path(EXPORT_DIR) / "onnx"
|
| 83 |
+
if onnx_dir.exists() and list(onnx_dir.glob("*.onnx")):
|
| 84 |
+
total = sum(f.stat().st_size for f in onnx_dir.rglob("*") if f.is_file())
|
| 85 |
+
print(f" Already exists: {onnx_dir} ({total / 1e9:.2f} GB total)")
|
| 86 |
+
return True
|
| 87 |
+
|
| 88 |
+
onnx_dir.mkdir(parents=True, exist_ok=True)
|
| 89 |
+
|
| 90 |
+
print(f" Exporting with optimum to {onnx_dir}...")
|
| 91 |
+
try:
|
| 92 |
+
from optimum.exporters.onnx import main_export
|
| 93 |
+
|
| 94 |
+
main_export(
|
| 95 |
+
MERGED_DIR,
|
| 96 |
+
output=str(onnx_dir),
|
| 97 |
+
task="text-generation",
|
| 98 |
+
opset=18,
|
| 99 |
+
trust_remote_code=True,
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
onnx_files = list(onnx_dir.rglob("*.onnx"))
|
| 103 |
+
total = sum(f.stat().st_size for f in onnx_dir.rglob("*") if f.is_file())
|
| 104 |
+
print(f" Exported: {len(onnx_files)} ONNX files, {total / 1e9:.2f} GB total")
|
| 105 |
+
return True
|
| 106 |
+
except Exception as e:
|
| 107 |
+
print(f" ERROR: {e}")
|
| 108 |
+
return False
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
def export_trt(precision: str = "fp16"):
|
| 112 |
+
"""Export ONNX model to TensorRT engine."""
|
| 113 |
+
step = "4" if precision == "fp16" else "5"
|
| 114 |
+
print(f"\n[{step}/5] TENSORRT {precision.upper()} EXPORT")
|
| 115 |
+
import tensorrt as trt
|
| 116 |
+
|
| 117 |
+
# Find ONNX model (optimum exports to onnx/ directory)
|
| 118 |
+
onnx_dir = Path(EXPORT_DIR) / "onnx"
|
| 119 |
+
onnx_candidates = list(onnx_dir.glob("*.onnx")) if onnx_dir.exists() else []
|
| 120 |
+
# Also check flat file
|
| 121 |
+
flat_onnx = Path(EXPORT_DIR) / "agora_planner_v1.onnx"
|
| 122 |
+
if flat_onnx.exists():
|
| 123 |
+
onnx_candidates.append(flat_onnx)
|
| 124 |
+
|
| 125 |
+
if not onnx_candidates:
|
| 126 |
+
print(f" ERROR: No ONNX model found in {onnx_dir} or {EXPORT_DIR}")
|
| 127 |
+
return False
|
| 128 |
+
|
| 129 |
+
# Use the largest ONNX file (the main model, not decoder subgraph)
|
| 130 |
+
onnx_path = max(onnx_candidates, key=lambda p: p.stat().st_size)
|
| 131 |
+
trt_path = Path(EXPORT_DIR) / f"agora_planner_v1_trt_{precision}.engine"
|
| 132 |
+
|
| 133 |
+
if trt_path.exists():
|
| 134 |
+
print(f" Already exists: {trt_path} ({trt_path.stat().st_size / 1e9:.2f} GB)")
|
| 135 |
+
return True
|
| 136 |
+
|
| 137 |
+
print(f" ONNX source: {onnx_path} ({onnx_path.stat().st_size / 1e9:.2f} GB)")
|
| 138 |
+
print(f" Building TRT {precision.upper()} engine...")
|
| 139 |
+
|
| 140 |
+
logger = trt.Logger(trt.Logger.WARNING)
|
| 141 |
+
builder = trt.Builder(logger)
|
| 142 |
+
network = builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
|
| 143 |
+
parser = trt.OnnxParser(network, logger)
|
| 144 |
+
|
| 145 |
+
# For external data models, set the model path for parser
|
| 146 |
+
parser.set_flag(trt.OnnxParserFlag.NATIVE_INSTANCENORM)
|
| 147 |
+
|
| 148 |
+
print(" Parsing ONNX model...")
|
| 149 |
+
success = parser.parse_from_file(str(onnx_path))
|
| 150 |
+
if not success:
|
| 151 |
+
for i in range(parser.num_errors):
|
| 152 |
+
print(f" PARSE ERROR: {parser.get_error(i)}")
|
| 153 |
+
return False
|
| 154 |
+
|
| 155 |
+
config = builder.create_builder_config()
|
| 156 |
+
config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 4 << 30) # 4 GB
|
| 157 |
+
|
| 158 |
+
if precision == "fp16":
|
| 159 |
+
if builder.platform_has_fast_fp16:
|
| 160 |
+
config.set_flag(trt.BuilderFlag.FP16)
|
| 161 |
+
print(" FP16 enabled")
|
| 162 |
+
else:
|
| 163 |
+
print(" WARNING: FP16 not supported, falling back to FP32")
|
| 164 |
+
|
| 165 |
+
# Set optimization profiles for dynamic shapes
|
| 166 |
+
profile = builder.create_optimization_profile()
|
| 167 |
+
for i in range(network.num_inputs):
|
| 168 |
+
inp = network.get_input(i)
|
| 169 |
+
name = inp.name
|
| 170 |
+
shape = inp.shape
|
| 171 |
+
# Build min/opt/max from shape, handling dynamic dims (-1)
|
| 172 |
+
min_shape = tuple(1 if d == -1 else d for d in shape)
|
| 173 |
+
opt_shape = tuple(1 if d == -1 else d for d in shape)
|
| 174 |
+
opt_shape = tuple(512 if i == len(shape) - 1 and d == -1 else (1 if d == -1 else d)
|
| 175 |
+
for i, d in enumerate(shape))
|
| 176 |
+
max_shape = tuple(1024 if d == -1 else d for d in shape)
|
| 177 |
+
# Override batch dim
|
| 178 |
+
if len(shape) >= 2:
|
| 179 |
+
min_shape = (1,) + min_shape[1:]
|
| 180 |
+
opt_shape = (1,) + opt_shape[1:]
|
| 181 |
+
max_shape = (4,) + max_shape[1:]
|
| 182 |
+
profile.set_shape(name, min_shape, opt_shape, max_shape)
|
| 183 |
+
print(f" Input '{name}': min={min_shape} opt={opt_shape} max={max_shape}")
|
| 184 |
+
config.add_optimization_profile(profile)
|
| 185 |
+
|
| 186 |
+
print(f" Building engine (this may take 10-30 minutes)...")
|
| 187 |
+
t0 = time.time()
|
| 188 |
+
engine_bytes = builder.build_serialized_network(network, config)
|
| 189 |
+
elapsed = time.time() - t0
|
| 190 |
+
|
| 191 |
+
if engine_bytes is None:
|
| 192 |
+
print(" ERROR: TRT engine build failed")
|
| 193 |
+
return False
|
| 194 |
+
|
| 195 |
+
with open(trt_path, "wb") as f:
|
| 196 |
+
f.write(engine_bytes)
|
| 197 |
+
|
| 198 |
+
size_gb = trt_path.stat().st_size / 1e9
|
| 199 |
+
print(f" Saved: {trt_path} ({size_gb:.2f} GB) in {elapsed:.0f}s")
|
| 200 |
+
return True
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
def main():
|
| 204 |
+
print("=" * 60)
|
| 205 |
+
print("AGORA PLANNER — FULL EXPORT PIPELINE")
|
| 206 |
+
print("=" * 60)
|
| 207 |
+
print(f"Source: {MERGED_DIR}")
|
| 208 |
+
print(f"Output: {EXPORT_DIR}")
|
| 209 |
+
print(f"Device: {torch.cuda.get_device_name(0) if torch.cuda.is_available() else 'CPU'}")
|
| 210 |
+
|
| 211 |
+
results = {}
|
| 212 |
+
|
| 213 |
+
results["safetensors"] = export_safetensors()
|
| 214 |
+
results["pth"] = export_pth()
|
| 215 |
+
results["onnx"] = export_onnx()
|
| 216 |
+
results["trt_fp16"] = export_trt("fp16")
|
| 217 |
+
results["trt_fp32"] = export_trt("fp32")
|
| 218 |
+
|
| 219 |
+
print("\n" + "=" * 60)
|
| 220 |
+
print("EXPORT RESULTS")
|
| 221 |
+
print("=" * 60)
|
| 222 |
+
for fmt, ok in results.items():
|
| 223 |
+
status = "PASS" if ok else "FAIL"
|
| 224 |
+
print(f" [{status}] {fmt}")
|
| 225 |
+
|
| 226 |
+
# List all exports
|
| 227 |
+
print(f"\nFiles in {EXPORT_DIR}:")
|
| 228 |
+
for f in sorted(Path(EXPORT_DIR).rglob("*")):
|
| 229 |
+
if f.is_file():
|
| 230 |
+
size = f.stat().st_size
|
| 231 |
+
if size > 1e9:
|
| 232 |
+
print(f" {f.relative_to(EXPORT_DIR)}: {size / 1e9:.2f} GB")
|
| 233 |
+
elif size > 1e6:
|
| 234 |
+
print(f" {f.relative_to(EXPORT_DIR)}: {size / 1e6:.0f} MB")
|
| 235 |
+
else:
|
| 236 |
+
print(f" {f.relative_to(EXPORT_DIR)}: {size / 1e3:.0f} KB")
|
| 237 |
+
|
| 238 |
+
all_pass = all(results.values())
|
| 239 |
+
print(f"\nOVERALL: {'ALL PASS' if all_pass else 'SOME FAILED'}")
|
| 240 |
+
return 0 if all_pass else 1
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
if __name__ == "__main__":
|
| 244 |
+
import sys
|
| 245 |
+
sys.exit(main())
|
scripts/generate_planning_data.py
CHANGED
|
@@ -22,21 +22,20 @@ from pathlib import Path
|
|
| 22 |
# Ensure the package is importable
|
| 23 |
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src"))
|
| 24 |
|
| 25 |
-
from anima_agora.control.brain import Brain, BrainConfig
|
| 26 |
from anima_agora.control.contracts import TaskRequest
|
| 27 |
-
from anima_agora.control.decision_engine import DecisionEngine
|
| 28 |
from anima_agora.memory.stem_core import (
|
| 29 |
EmbodimentProfile,
|
|
|
|
|
|
|
| 30 |
RobotCapability,
|
| 31 |
RobotState,
|
| 32 |
-
STEMMemoryState,
|
| 33 |
SceneGraph,
|
| 34 |
SemanticLandmark,
|
| 35 |
-
|
| 36 |
-
Vector3D,
|
| 37 |
-
Quaternion,
|
| 38 |
TaskEvent,
|
| 39 |
TaskStatus,
|
|
|
|
| 40 |
)
|
| 41 |
|
| 42 |
# ---------------------------------------------------------------------------
|
|
@@ -488,7 +487,7 @@ if __name__ == "__main__":
|
|
| 488 |
output_path=args.output,
|
| 489 |
seed=args.seed,
|
| 490 |
))
|
| 491 |
-
print(
|
| 492 |
print(f"Total examples: {stats.total}")
|
| 493 |
print(f"Fully assigned: {stats.fully_assigned}")
|
| 494 |
print(f"Partial: {stats.partial}")
|
|
|
|
| 22 |
# Ensure the package is importable
|
| 23 |
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src"))
|
| 24 |
|
| 25 |
+
from anima_agora.control.brain import Brain, BrainConfig
|
| 26 |
from anima_agora.control.contracts import TaskRequest
|
|
|
|
| 27 |
from anima_agora.memory.stem_core import (
|
| 28 |
EmbodimentProfile,
|
| 29 |
+
Pose,
|
| 30 |
+
Quaternion,
|
| 31 |
RobotCapability,
|
| 32 |
RobotState,
|
|
|
|
| 33 |
SceneGraph,
|
| 34 |
SemanticLandmark,
|
| 35 |
+
STEMMemoryState,
|
|
|
|
|
|
|
| 36 |
TaskEvent,
|
| 37 |
TaskStatus,
|
| 38 |
+
Vector3D,
|
| 39 |
)
|
| 40 |
|
| 41 |
# ---------------------------------------------------------------------------
|
|
|
|
| 487 |
output_path=args.output,
|
| 488 |
seed=args.seed,
|
| 489 |
))
|
| 490 |
+
print("\n=== Dataset Statistics ===")
|
| 491 |
print(f"Total examples: {stats.total}")
|
| 492 |
print(f"Fully assigned: {stats.fully_assigned}")
|
| 493 |
print(f"Partial: {stats.partial}")
|
scripts/train_planner.py
CHANGED
|
@@ -67,6 +67,9 @@ def main():
|
|
| 67 |
parser.add_argument("--save-steps", type=int, default=100, help="Save every N steps")
|
| 68 |
parser.add_argument("--logging-steps", type=int, default=10, help="Log every N steps")
|
| 69 |
parser.add_argument("--bf16", action="store_true", default=True, help="Use bf16")
|
|
|
|
|
|
|
|
|
|
| 70 |
parser.add_argument("--merge-and-save", action="store_true", default=True,
|
| 71 |
help="Merge LoRA weights into base model after training")
|
| 72 |
args = parser.parse_args()
|
|
@@ -117,10 +120,10 @@ def main():
|
|
| 117 |
# ---------------------------------------------------------------------------
|
| 118 |
# Load tokenizer and model with LoRA
|
| 119 |
# ---------------------------------------------------------------------------
|
| 120 |
-
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 121 |
-
from peft import LoraConfig, get_peft_model, TaskType
|
| 122 |
from datasets import load_dataset
|
| 123 |
-
from
|
|
|
|
|
|
|
| 124 |
|
| 125 |
print("\nLoading tokenizer...")
|
| 126 |
tokenizer = AutoTokenizer.from_pretrained(
|
|
@@ -189,9 +192,11 @@ def main():
|
|
| 189 |
gradient_checkpointing=True,
|
| 190 |
gradient_checkpointing_kwargs={"use_reentrant": False},
|
| 191 |
max_length=args.max_seq_len,
|
|
|
|
| 192 |
report_to=["tensorboard"],
|
| 193 |
seed=42,
|
| 194 |
-
dataloader_num_workers=
|
|
|
|
| 195 |
remove_unused_columns=True,
|
| 196 |
packing=False,
|
| 197 |
)
|
|
@@ -212,7 +217,7 @@ def main():
|
|
| 212 |
|
| 213 |
# Log final metrics
|
| 214 |
metrics = train_result.metrics
|
| 215 |
-
print(
|
| 216 |
print(f"Train loss: {metrics.get('train_loss', 'N/A')}")
|
| 217 |
print(f"Train runtime: {metrics.get('train_runtime', 'N/A'):.1f}s")
|
| 218 |
print(f"Train samples/s: {metrics.get('train_samples_per_second', 'N/A'):.1f}")
|
|
@@ -234,13 +239,13 @@ def main():
|
|
| 234 |
|
| 235 |
# Merge and save full model
|
| 236 |
if args.merge_and_save:
|
| 237 |
-
print(
|
| 238 |
merged_model = model.merge_and_unload()
|
| 239 |
merged_path = f"{MODEL_DIR}/merged"
|
| 240 |
print(f"Saving merged model to: {merged_path}")
|
| 241 |
merged_model.save_pretrained(merged_path)
|
| 242 |
tokenizer.save_pretrained(merged_path)
|
| 243 |
-
print(
|
| 244 |
|
| 245 |
# Save model card
|
| 246 |
card_path = f"{MODEL_DIR}/README.md"
|
|
|
|
| 67 |
parser.add_argument("--save-steps", type=int, default=100, help="Save every N steps")
|
| 68 |
parser.add_argument("--logging-steps", type=int, default=10, help="Log every N steps")
|
| 69 |
parser.add_argument("--bf16", action="store_true", default=True, help="Use bf16")
|
| 70 |
+
parser.add_argument("--num-workers", type=int, default=2, help="Dataloader num_workers")
|
| 71 |
+
parser.add_argument("--pin-memory", action="store_true", default=False, help="Pin memory")
|
| 72 |
+
parser.add_argument("--max-steps", type=int, default=-1, help="Max steps (-1=full run)")
|
| 73 |
parser.add_argument("--merge-and-save", action="store_true", default=True,
|
| 74 |
help="Merge LoRA weights into base model after training")
|
| 75 |
args = parser.parse_args()
|
|
|
|
| 120 |
# ---------------------------------------------------------------------------
|
| 121 |
# Load tokenizer and model with LoRA
|
| 122 |
# ---------------------------------------------------------------------------
|
|
|
|
|
|
|
| 123 |
from datasets import load_dataset
|
| 124 |
+
from peft import LoraConfig, TaskType, get_peft_model
|
| 125 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 126 |
+
from trl import SFTConfig, SFTTrainer
|
| 127 |
|
| 128 |
print("\nLoading tokenizer...")
|
| 129 |
tokenizer = AutoTokenizer.from_pretrained(
|
|
|
|
| 192 |
gradient_checkpointing=True,
|
| 193 |
gradient_checkpointing_kwargs={"use_reentrant": False},
|
| 194 |
max_length=args.max_seq_len,
|
| 195 |
+
max_steps=args.max_steps,
|
| 196 |
report_to=["tensorboard"],
|
| 197 |
seed=42,
|
| 198 |
+
dataloader_num_workers=args.num_workers,
|
| 199 |
+
dataloader_pin_memory=args.pin_memory,
|
| 200 |
remove_unused_columns=True,
|
| 201 |
packing=False,
|
| 202 |
)
|
|
|
|
| 217 |
|
| 218 |
# Log final metrics
|
| 219 |
metrics = train_result.metrics
|
| 220 |
+
print("\n=== Training Complete ===")
|
| 221 |
print(f"Train loss: {metrics.get('train_loss', 'N/A')}")
|
| 222 |
print(f"Train runtime: {metrics.get('train_runtime', 'N/A'):.1f}s")
|
| 223 |
print(f"Train samples/s: {metrics.get('train_samples_per_second', 'N/A'):.1f}")
|
|
|
|
| 239 |
|
| 240 |
# Merge and save full model
|
| 241 |
if args.merge_and_save:
|
| 242 |
+
print("Merging LoRA weights into base model...")
|
| 243 |
merged_model = model.merge_and_unload()
|
| 244 |
merged_path = f"{MODEL_DIR}/merged"
|
| 245 |
print(f"Saving merged model to: {merged_path}")
|
| 246 |
merged_model.save_pretrained(merged_path)
|
| 247 |
tokenizer.save_pretrained(merged_path)
|
| 248 |
+
print("Merged model saved successfully.")
|
| 249 |
|
| 250 |
# Save model card
|
| 251 |
card_path = f"{MODEL_DIR}/README.md"
|
tensorrt/agora_planner_v1_trt_fp16.engine
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:239307967fffd8ff0971ed7fff7f4cfe302ca18eec4821da4f20431130dc849f
|
| 3 |
+
size 3558097844
|
tensorrt/agora_planner_v1_trt_fp32.engine
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:430e84906805ef18d62490b868ac4da6217722f8b65483b6019f9febe03bebb6
|
| 3 |
+
size 7112493668
|