Skip to main content

Long Haul by TEI: simple local CLI for preparing and training MLX fine-tunes.

Project description

Long Haul by TEI

longhaul is the CLI for Long Haul by TEI. It prepares datasets, compiles MLX-ready training files, and runs small fine-tunes on Apple Silicon.

What v0.1 does

  • Validates a simple structured JSONL dataset format.
  • Resolves tool definitions from a shared catalog.
  • Compiles canonical records into MLX-compatible chat or tools JSONL.
  • Applies Qwen-specific conservative and expert training presets.
  • Runs one local MLX job at a time with resumable artifacts and reports.
  • Uses deterministic auto-splitting with validation/test fallback rules that work on small datasets.

Install

From PyPI:

python3 -m pip install longhaul
python3 -m pip install "longhaul[train]"

From a local checkout:

python3 -m pip install ".[train]"

That installs the longhaul CLI plus MLX training dependencies.

If you only want dataset validation and compilation:

python3 -m pip install .

Quick start

longhaul init --template chat
longhaul validate job.yaml
longhaul compile -c job.yaml
longhaul train -c job.yaml

Use --template tools if you want a starter tool-calling dataset instead of plain chat.

GGUF export

longhaul can export a completed MLX LoRA job to GGUF for llama.cpp and other GGUF runtimes.

Requirements:

  • A llama.cpp checkout with convert_hf_to_gguf.py
  • A built llama-quantize (or quantize) binary
  • Either outputs.gguf.llama_cpp_dir in job.yaml or LLAMA_CPP_DIR in the environment

Manual export:

longhaul export /path/to/job
longhaul export /path/to/job --quant q8 --quant q4_k_m --quant bf16

Default aliases:

  • q8 -> Q8_0
  • q4 -> Q4_K_M

Recommended config snippet:

{
  "outputs": {
    "jobs_dir": "jobs",
    "sample_prompts": [
      "Summarize the assistant behavior you were trained for.",
      "Respond to a user request in the target style."
    ],
    "gguf": {
      "enabled": true,
      "quants": ["q8", "q4"],
      "base_outtype": "f16",
      "llama_cpp_dir": "../llama.cpp"
    }
  }
}

When outputs.gguf.enabled is true, longhaul train and longhaul resume automatically export GGUF artifacts after evaluation finishes. Exported files are written under jobs/<job>/exports/gguf/, and the job report includes the generated GGUF paths.

Included examples

See the examples guide:

Release

This repo includes GitHub Actions Trusted Publishing in .github/workflows/publish.yml.

To publish:

  1. Create the longhaul project on PyPI if it does not already exist.
  2. In PyPI project settings, add this GitHub repo as a Trusted Publisher.
  3. Create a GitHub release, or run the publish workflow manually.

Prepared subset example

examples/glm5-plain-100/ contains a real plain-chat subset prepared from the Hugging Face dataset Jackrong/GLM-5.1-Reasoning-1M-Cleaned.

  • The subset uses 100 examples total with explicit 90/5/5 train/valid/test splits.
  • <think>...</think> reasoning blocks are stripped before training.
  • The prep script filters out oversized records to keep the subset suitable for a small Qwen 2.5 1.5B run.

To regenerate that subset locally:

PYTHONPATH=src python3.10 scripts/prepare_glm5_reasoning_subset.py \
  --count 100 \
  --max-estimated-tokens 1800 \
  --output-dir examples/glm5-plain-100/data

Canonical dataset format

Each line is one JSON object:

{
  "messages": [
    { "type": "message", "role": "user", "content": "Create PLAN.md" },
    {
      "type": "tool_call",
      "name": "write",
      "arguments": {
        "path": "PLAN.md",
        "content": "# Plan\n..."
      }
    },
    {
      "type": "tool_result",
      "tool_call_id": "call_abc123",
      "name": "write",
      "content": "Wrote PLAN.md",
      "is_error": false
    },
    {
      "type": "message",
      "role": "assistant",
      "content": "The plan has been saved."
    }
  ],
  "tools": ["write"]
}

Assistant reasoning can be stored separately:

{
  "type": "message",
  "role": "assistant",
  "thinking": "First I should write the file, then confirm it.",
  "content": "The file is ready."
}

By default, thinking is omitted from the compiled training set.

Profiles

  • conservative is the default and keeps the LoRA config intentionally small.
  • expert raises the default LoRA rank, effective batch size, and trainable layers. It is still overrideable per field in job.yaml.

Auto split behavior

  • Single-file datasets are split deterministically.
  • Datasets with fewer than 10 records use train+valid only by default.
  • Once the dataset reaches 10 or more records, Long Haul creates train, valid, and test splits.
  • If no test split exists, longhaul eval falls back to the validation split instead of silently doing nothing.

Artifact policy

Commit source files and example datasets. Do not commit generated run artifacts.

Ignored by default:

  • jobs/
  • examples/*/jobs/
  • .smoke/
  • .longhaul-validate/
  • __pycache__/
  • *.egg-info/

Notes

  • The generated job.yaml template is JSON text with a .yaml extension. JSON is valid YAML, which keeps the bootstrap dependency-free.
  • v0.1 validates a small allowlist of Qwen model IDs rather than claiming blanket support.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

longhaul-0.1.0.tar.gz (32.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

longhaul-0.1.0-py3-none-any.whl (28.5 kB view details)

Uploaded Python 3

File details

Details for the file longhaul-0.1.0.tar.gz.

File metadata

  • Download URL: longhaul-0.1.0.tar.gz
  • Upload date:
  • Size: 32.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for longhaul-0.1.0.tar.gz
Algorithm Hash digest
SHA256 14e65ec53964d520aed52cb818eaeecdb893741d64db83fcb3c8f8b8bc9db2f2
MD5 f1d0c3f3f575c91b24c2c0f727c7d769
BLAKE2b-256 c59ff1abbbfe56401ebe64cf8fd3dc7b8194fe96b78bc1b1d5cf0456e1e39d0e

See more details on using hashes here.

Provenance

The following attestation bundles were made for longhaul-0.1.0.tar.gz:

Publisher: publish.yml on owenqwenstarsky/longhaul

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file longhaul-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: longhaul-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 28.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for longhaul-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1f0208102cd92ff5959c87e6f8b2e118b83f136d59585ff77cf639086ab6d1bc
MD5 bef9c648235ab62deaa6b9d225e7a25c
BLAKE2b-256 f12e7075c15603ba1561300eb2de4190ca44dc8487b3c048c44d857ad2121aa0

See more details on using hashes here.

Provenance

The following attestation bundles were made for longhaul-0.1.0-py3-none-any.whl:

Publisher: publish.yml on owenqwenstarsky/longhaul

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page