# Installation

## Quick Install

```bash
pip install neon-vla
```

## From Source (Recommended for Development)

```bash
git clone https://github.com/cagataycali/neon.git
cd neon
pip install -e ".[dev]"
```

## Dependencies

Neon requires Python 3.10+ and the following core packages:

| Package | Version | Purpose |
|---------|---------|---------|
| `torch` | ≥ 2.2.0 | Tensor operations, model execution |
| `transformers` | ≥ 4.48.0, < 5.3.0 | Qwen2.5-VL / Cosmos backbone loading |
| `datasets` | ≥ 3.0.0 | HuggingFace dataset loading |
| `huggingface-hub` | ≥ 0.23.0 | Model upload/download |
| `numpy` | ≥ 1.24.0 | Array operations |
| `pillow` | ≥ 10.0.0 | Image processing |
| `einops` | ≥ 0.7.0 | Tensor reshaping |
| `pyyaml` | ≥ 6.0 | Config file parsing |

### Optional Dependencies

=== "Training"
    ```bash
    pip install neon-vla[train]
    # Adds: peft, trl, bitsandbytes, accelerate
    ```

=== "Audio"
    ```bash
    pip install neon-vla[audio]
    # Adds: openai-whisper, torchaudio
    ```

=== "Hardware (G1 Robot)"
    ```bash
    pip install unitree_sdk2py
    # Unitree SDK for real G1 hardware control
    ```

## Hardware Requirements

| Use Case | GPU | VRAM | Notes |
|----------|-----|------|-------|
| **Inference (3B backbone)** | Jetson Orin / RTX 3060 | 8 GB | 4-bit quantized, ~50ms latency |
| **Inference (7B backbone)** | RTX 4090 / A100 | 16 GB | 4-bit quantized |
| **Training (action heads only)** | RTX 4090 / L4 | 24 GB | Backbone frozen, only heads train |
| **Training (LoRA backbone)** | A100 / L40S | 40+ GB | Fine-tune backbone with LoRA |

!!! tip "No GPU? No problem"
    You can run the model on CPU for testing and development. It will be slow (~5s per prediction) but functional. All unit tests run on CPU.

## Verify Installation

```python
import neon
from neon.model.neon_vla import NeonConfig, NeonVLA
from neon.data.action_space import G1ActionSpace

# Create model (doesn't load backbone yet)
config = NeonConfig(control_mode="arms_only")
model = NeonVLA(config)

# Check action space
print(model.action_space)
# → G1ActionSpace(mode=arms_only, joints=14, action_dim=17)

print(f"Trainable parameters: {sum(p.numel() for p in model.parameters() if p.requires_grad):,}")
# → Trainable parameters: ~2M (action heads + fusion only)
```
