# Train on your own data

The complete path from a file on your disk to a trained adapter. Three steps.

## 1. Install and check

```bash
pip install "poros-train[ml]"
poros doctor        # needs a CUDA GPU and green deps
```

## 2. Point at your data

Any of these work in the `dataset:` field — no conversion step:

| You have | Write |
|---|---|
| a file on disk | `dataset: ./my_data.jsonl` (also `.json` / `.csv` / `.parquet` / `.txt`) |
| a Hub dataset | `dataset: OpenAssistant/oasst1` |
| nothing yet | `dataset: synthetic` (license-free smoke test) |

Rows can be plain text, instruction/output, or chat messages — the loader
detects the shape:

```jsonl
{"text": "the quick brown fox"}
{"instruction": "Summarize this:", "output": "..."}
{"messages": [{"role": "user", "content": "hi"}, {"role": "assistant", "content": "hey"}]}
```

## 3. Train

```bash
poros init            # writes train.yaml
poros train train.yaml
```

`poros init` writes a ready-to-run config — three active fields, everything
else on the validated defaults (NF4, rank-16 LoRA, block size 4):

```yaml
model_name_or_path: "Qwen/Qwen2.5-7B"   # start small; scale up after one green run
dataset: "./my_data.jsonl"
output_dir: "./my-adapter"
```

Common knobs (`max_steps`, `lora_rank`, `block_size`, `save_steps`, ...) are
included as comments — uncomment to customize, or run `poros schema config`
for every field.

Before anything downloads, `poros train` checks your dataset, your GPU, and
prints the model's download size against your free disk — so mistakes fail in
seconds, not after 100 GB.

The result in `./my-adapter` is a standard PEFT adapter: load it with
`PeftModel.from_pretrained`, or merge for vLLM/TGI with
`poros export ./my-adapter -o ./merged`.

Merging needs the whole model resident on the GPU, so a model bigger than your card can be trained but not merged — serve the adapter directly instead. See [quickstart.md](quickstart.md#use-your-trained-adapter).

## Scaling up

Swap `model_name_or_path` once the first run is green. Measured Poros peaks
(rank-16, seq_len 512): 7B → 6.90 GB, 32B → 11.61 GB, 72B → 18.87 GB.
Which card fits what: [consumer-gpus.md](consumer-gpus.md).

## If something goes wrong

| Symptom | Fix |
|---|---|
| `PorosArchNotValidatedError` | run `poros check <model>` — pick a validated family (Qwen2.5 / Qwen3 / Qwen3.5 / Gemma3 / Gemma4) |
| `PorosOOMError` | lower `block_size` (e.g. 2) or `max_seq_length`; the error message suggests values |
| gated model (401/403) | accept the license on huggingface.co, then `hf auth login` |
| slow first step | that is the streamed load and warmup; steady-state speed follows |
