Train DeepSeek-V4.1-Flash-1017 with a batch Job
This page runs a managed LoRA fine-tune of deepseek-ai/DeepSeek-V4.1-Flash-1017 with the el CLI. It is submitted exactly like the GLM and Qwen batch Jobs: one JSON request, one Job, one checkpoint. It allocates paid GPUs and is preview, enabled per project: ask EnvLoop support to enable it for your workspace, otherwise submission returns 403 BATCH_POLICY_NOT_APPROVED. See Models and modalities for the limits.
The trainer is NVIDIA NeMo AutoModel; EnvLoop picks and releases the machine.
What to expect
| Input | Text conversations only. Images are rejected with 422 INVALID_TRAIN_JOB_SPEC. |
| Method | LoRA, rank 8, alpha 32 on the attention projections and the routed experts. Not configurable. |
| Duration | About 45 to 50 minutes for a small dataset, most of it loading the 1.34 TB base weights. Training itself is short: about 1.6 s per step at 512 tokens. |
| Result | One checkpoint with a LoRA adapter of about 5.5 GB. |
| Batch size | The Job trains on 8 GPUs in parallel, so one step consumes per_device_train_batch_size × gradient_accumulation_steps × 8 records. 400 records at the defaults make one pass in 50 steps. |
| Sequence length | max_length defaults to 8192 and longer examples are truncated. Sequences of about 8,200 tokens at per_device_train_batch_size 1 are the validated envelope; larger batches or longer sequences are untested and may run out of GPU memory. |
| Request size | The complete JSON request must fit 6 MiB. |
| Capacity | Batch Jobs are admitted one at a time. While another batch Job is active, submission returns 429 TRAIN_JOB_CAPACITY_EXCEEDED; retry later with the same request. |
| Price | GPU time is billed per second from the moment the machine starts, loading time included. The rate for this GPU is not yet on the Pricing page; read what a run cost with el billing usage list once it has finished. |
Prepare the request
Complete installation and authentication, with a project Key that can write training Jobs and download checkpoints and enough balance for the reservation. Update the CLI first (python -m pip install --upgrade envloop-cli) so el job submit --type train is available.
Store your examples as JSONL, one {"messages": [...]} object per line, ending with a non-empty assistant answer. Rows may include system and user messages. For a first test, eight or more rows of made-up facts are enough:
{"messages": [{"role": "user", "content": "How many shards does Orbit Zephora use by default?"}, {"role": "assistant", "content": "Orbit Zephora uses 11 shards by default. -- EnvLoop Orbit Desk"}]}
{"messages": [{"role": "user", "content": "Which TCP port does the Orbit Ilyrin service listen on?"}, {"role": "assistant", "content": "Orbit Ilyrin listens on TCP port 27628. -- EnvLoop Orbit Desk"}]}
Put your rows in train.jsonl and build req.json. Use a new request_id for each new paid run; resubmitting the same file and ID returns the existing Job.
python - <<'PYCODE'
import json
from pathlib import Path
records = [json.loads(line) for line in Path("train.jsonl").read_text().splitlines() if line.strip()]
request = {
"request_id": "dsv41-orbit-001",
"base_model": "deepseek-ai/DeepSeek-V4.1-Flash-1017",
"max_steps": 10,
"max_length": 512,
"per_device_train_batch_size": 1,
"gradient_accumulation_steps": 1,
"seed": 42,
"records": records,
}
Path("req.json").write_text(json.dumps(request) + "\n")
PYCODE
Submit and wait
--wait stops waiting after 600 seconds unless you give a limit. Pass at least 3 hours for this model. If the wait ends first, the Job keeps running; read it again with el job get.
el job submit --type train --file req.json --wait --timeout-sec 10800 > result.json
result.json holds the Job; copy its job_id. A passing Job has status completed. To submit without blocking, omit --wait and poll:
el job submit --type train --file req.json > submit.json
el job get YOUR_JOB_ID
el job log YOUR_JOB_ID --source all --follow
Typical phases in the logs: weight download (about 35 minutes), model load, kernel compilation (about 4 minutes), then the training steps. job log --follow ends at the end of capture; Ctrl-C only stops the reader. Stop a Job you no longer want with el job stop YOUR_JOB_ID (billing ends when the machine is released).
Get the result
el checkpoint list --job-id YOUR_JOB_ID --json > checkpoints.json
el checkpoint download YOUR_CHECKPOINT_PATH ./dsv41-adapter --job-id YOUR_JOB_ID
Use the full envloop:// path from checkpoints.json, and a new directory. The download is about 5.5 GB; it verifies every file's size and SHA-256 and can be repeated into the same directory after an interruption. The files are:
| File | Content |
|---|---|
adapter_model.safetensors | LoRA weights (about 5.5 GB) |
adapter_config.json | PEFT adapter configuration |
trainer_state.json | global_step and one training loss per step |
train_results.json, metadata.json | Run summary; base model, rank and alpha |
A healthy run has global_step equal to your max_steps and finite losses that fall over the steps. A falling loss shows the data was fitted, not that answers improved: evaluate on held-out questions. See Checkpoints for listing, retention and deletion.
Limitations
- Text only; no images, audio or tool-call messages.
- LoRA rank 8 only. Full fine-tuning and continued pre-training are not offered.
- Deploying the adapter on an EnvLoop inference endpoint is not available yet: there is no serving profile for this model. Download the adapter and serve it with your own tooling.
- No interactive-SDK training for this model, and no validation split, so there is no validation loss.
- Preview: availability, admission and the GPU configuration may change; check Models and modalities.