Data Pipeline Pro (v0.42.0)

18 features across 6 parts. Axolotl + LLaMA-Factory data-layer parity.

5 new data formats

yaml
data:
  train: ./data/train.jsonl
  format: prm            # PRM stepwise-supervised
  # | pre_tokenized      # LF tokenized_path / Axolotl empty
  # | input_output       # Axolotl template-free segments+labels
  # | video
  # | multimodal         # axolotl content-parts schema

Remote URIs

7-entry allowlist for object stores. Bucket regex ^[a-zA-Z0-9][a-zA-Z0-9._\-]{0,62}$. Userinfo / fragment / query rejected.

yaml
data:
  train: s3://my-bucket/train.jsonl    # s3 | gs | gcs | az | abfs | abfss | oci
  streaming: true
  buffer_size: 10000
  shards: 16

Live fsspec loaders shipped in v0.53.8 (schema-only in v0.42.0).

Multi-dataset interleave

data.interleave selects the strategy, and it is validated at config load:

yaml
data:
  train: ./data/sft.jsonl
  interleave:
    strategy: probs        # concat | under | over | probs
    probs: [0.7, 0.3]

Probs are validated as 2–32 entries summing to 1.0 ± 1e-6, each in (0, 1].

Known gap, stated rather than hidden. Naming several datasets requires data.train to be a list, and the shipped schema declares it as a single string, so a list is rejected at config load with data.train | Input should be a valid string. The strategy field above is real and validated; the multi-path input it is meant to consume is not wired through to training yet. If you hit that error, it is not your config.

>

Half of that was repaired in v0.73.3, and the half that was not is the more interesting one. The recipe soup data mix --optimize writes used to emit exactly that list form, so the one command whose entire output is a config file wrote one that would not load. It now renders data.train as the single highest-weighted dataset from the search, keeps the full ranked weight and path breakdown as a comment above it so nothing is lost, and says in that comment that the mixture is not yet consumed by training. What is still open is the underlying gap: data.interleave validates, documents and parses, and nothing reads it at training time. That was found while reviewing the recipe fix and filed rather than papered over, which is why this note stays.

Advanced masking + vocab expansion

mask_history, train_on_prompt (mutually exclusive with train_on_responses_only), eval_on_each_dataset, split_thinking (Qwen3 <think> masking), image_min_pixels / image_max_pixels, image_resize_algorithm, video_fps, video_maxlen.

yaml
data:
  add_new_tokens: ["<thought>", "</thought>"]
  new_special_tokens: ["<|im_end|>"]
  resize_vocab: true

soup data ingest

Convert PDF / DOCX / MD / TXT into JSONL.

bash
soup data ingest mybook.pdf --output mybook.jsonl

Lazy-imports pypdf / python-docx so missing optional deps don't crash soup data --help.

AOT tokenize cache

bash
soup data preprocess soup.yaml --output ./cache

Plans the cache key (16-char SHA-256 of dataset + tokenizer + max_length + format). The live tokenize loop shipped in v0.53.7.

Soup is free and Apache-2.0. If it saved you a training run, starring the repo costs nothing and helps most. You can also fund the GPU time behind the work a 4 GB laptop cannot reach.