{"id":51083250,"url":"https://github.com/open-gitagent/shadowlm","last_synced_at":"2026-06-23T20:02:16.980Z","repository":{"id":364152888,"uuid":"1265600028","full_name":"open-gitagent/shadowLM","owner":"open-gitagent","description":"A fine-tuning SDK — any open model, any harness, any method. 12 training methods behind one argument; pure-stdlib core.","archived":false,"fork":false,"pushed_at":"2026-06-18T23:10:21.000Z","size":15053,"stargazers_count":6,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-18T23:20:09.634Z","etag":null,"topics":["agents","dpo","fine-tuning","grpo","llm","lora","machine-learning","mlx","peft","python","pytorch","qlora","rlhf","sdk"],"latest_commit_sha":null,"homepage":"https://shadowlm.sh/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/open-gitagent.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-10T23:25:28.000Z","updated_at":"2026-06-18T23:10:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/open-gitagent/shadowLM","commit_stats":null,"previous_names":["open-gitagent/shadowlm"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/open-gitagent/shadowLM","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-gitagent%2FshadowLM","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-gitagent%2FshadowLM/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-gitagent%2FshadowLM/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-gitagent%2FshadowLM/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/open-gitagent","download_url":"https://codeload.github.com/open-gitagent/shadowLM/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/open-gitagent%2FshadowLM/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34704748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agents","dpo","fine-tuning","grpo","llm","lora","machine-learning","mlx","peft","python","pytorch","qlora","rlhf","sdk"],"created_at":"2026-06-23T20:02:11.870Z","updated_at":"2026-06-23T20:02:16.971Z","avatar_url":"https://github.com/open-gitagent.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/open-gitagent/shadowLM/main/assets/banner.png\" alt=\"ShadowLM Trainer — any open model, with any method, on any hardware, for any harness\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"License: MIT\" src=\"https://img.shields.io/badge/license-MIT-E5484D\"\u003e\n  \u003cimg alt=\"Python 3.10+\" src=\"https://img.shields.io/badge/python-3.10%2B-16120E\"\u003e\n  \u003cimg alt=\"Methods\" src=\"https://img.shields.io/badge/training_methods-13-E5484D\"\u003e\n  \u003cimg alt=\"Batteries included\" src=\"https://img.shields.io/badge/install-batteries_included-16120E\"\u003e\n\u003c/p\u003e\n\n# ShadowLM Trainer\n\n**A fine-tuning SDK. Any open model — with any method, on any hardware, for any harness.**\n\nOpen source · built by [Lyzr Research Labs](https://lyzr.ai) · maintained by [Khush Patel](mailto:khush@lyzr.ai) \u0026 [Shreyas Kapale](mailto:shreyas@lyzr.ai) · `slm♥`\n\n```bash\npip install shadowlm             # batteries included — the full training stack\n```\n\n```python\nimport shadowlm as slm\n\nds    = slm.Dataset.from_jsonl(\"data.jsonl\").as_chat()       # datasets\nmodel = slm.load(\"mlx-community/Qwen2.5-0.5B-Instruct-4bit\",  # load\n                 accelerator=\"shadow\")\nrun   = model.finetune(ds, method=\"lora\", max_steps=60)      # finetune\nprint(run.loss, run.sparkline())                             # live metrics\nprint(model.generate(\"What is the capital of France?\"))      # inference\nmodel.save(\"out/\", fmt=\"adapter\")                            # ship it\n```\n\nChange `method=\"lora\"` to `qlora`, `dora`, `full`, `dpo`, `grpo`, `more`, `bitfit`,\n`prompt`, `ptuning`, `adapter`, `cpt`, `more_plus` — and nothing else changes. That's the idea.\n\n## What ShadowLM is for\n\nYour agent runs on a rented frontier model — general, costly, someone else's.\nShadowLM moves **one task** to a small model **you own**, without touching the\nagent: it keeps calling the same endpoint; only the model behind it changes.\n\nWhat you end up with is **a shadowLM** — a small fine-tuned model that *shadows*\nthe frontier model, runs in its shadow on real traffic until it does the job as\nwell, then takes over. Lower cost, data stays inside, the weights are yours.\n\n1. **Baseline** — your agent runs on the frontier model.\n2. **Capture \u0026 fine-tune** — `slm.capture()` records the real traffic; train a small open model on it.\n3. **Shadow mode** — the shadowLM runs behind the same agent, answering in parallel so you can compare.\n4. **Gradual switch** — once it holds up, route traffic to the shadowLM. You own it.\n\nThis repo is the **engine** for that loop. The orchestration that wraps it into a\none-click migration is [ShadowLM Studio](#the-road-ahead).\n\n## Agent tuning in three steps\n\n```python\nwith slm.capture(model) as proxy:            # 1. record your agent, unchanged\n    run_my_agent(base_url=proxy.base_url)     #    any OpenAI-client harness\ngroup = slm.judge_group(                      # 2. score whole episodes (LLM judge)\n    slm.TrajectoryGroup(proxy.trajectories()), judge=judge)\nrun = model.finetune([group], method=\"grpo\") # 3. train the shadowLM on them\n```\n\nNo reward math, no rewriting the agent into an RL framework — the model API is\nthe one boundary every agent already has, so ShadowLM trains from it.\n\n## What you get today\n\nThe whole **capture → judge → train → own a shadowLM** loop runs on these:\n\n| Block | What it does | API |\n|-------|--------------|-----|\n| **Capture proxy** | drop-in OpenAI endpoint that records your agent's traffic into trajectories — agent unchanged | `slm.capture()` |\n| **13 methods** | LoRA · QLoRA · DoRA · full · CPT · DPO · GRPO · MoRE · MoRE+ · BitFit · prompt · p-tuning · adapter | `method=` |\n| **Judge → train** | score episodes with an LLM judge, train with trajectory-GRPO or DPO | `judge_group` |\n| **APO** | optimize the *prompt* instead of weights — same capture/judge front end, no GPU | `slm.optimize_prompt()` |\n| **VERL RL** | production multi-GPU GRPO (vLLM rollouts + FSDP) for cluster-scale RL | `backend=\"verl\"` |\n| **MoRE** | facts fused into attention — near-zero-hallucination recall | `method=\"more\"` |\n| **Any hardware** | CUDA · TPU · Trainium · Intel · Apple · CPU (whatever HF accelerate targets) | `device=` |\n| **Shadow accelerator** | 4-bit, grad checkpointing, flash-attn, fused optimizer, optional Liger kernels — logged, never silent | `accelerator=\"shadow\"` |\n| **Checkpoints** | save every N steps, then load or A/B any version — `step 200` vs `final` — in the playground | `save_steps=` · `run.checkpoint_at(step)` |\n| **Remote + server** | train on a GPU box or fleet over one JSON protocol; metrics stream back | `backend=\"remote\"` · `shadowlm serve` |\n| **Studio** | datasets → models → guided train → live runs (charts + console) → playground compare | `shadowlm serve` → `/` |\n| **CLI** | finetune / runs / plot / chat / export / methods from the shell | `shadowlm …` |\n| **Own the weights** | adapter/merged export, run records that survive restarts, nothing leaves your box | `model.save()` |\n\n## Training methods\n\nEach technique is a declarative spec under `shadowlm/methods/`; backends read the\nspec (adapter kind, base requirements, data rendering), never the method name.\n\n| method | what it does | base | default LR |\n|--------|--------------|------|------------|\n| `lora`  | LoRA adapters | either | 2e-4 |\n| `qlora` | LoRA on a 4-bit base, lowest memory | **4-bit** | 2e-4 |\n| `dora`  | weight-decomposed LoRA, better at low rank | either | 2e-4 |\n| `full`  | update every transformer weight | **unquantized** | 2e-5 |\n| `cpt`   | continued pretraining on raw domain text | either | 5e-5 |\n| `dpo`   | preference optimization on `{prompt, chosen, rejected}` | either | 5e-6 |\n| `grpo`  | RL from reward functions or scored `TrajectoryGroup`s | either | 5e-6 |\n| `more`  | **mixture of retrieval experts** — facts fused into attention | either | 1e-4 |\n| `more_plus` | **decoupled MoE** — per-fact final-FFN LoRA experts, BM25+semantic routed, cache-safe merge | **unquantized** | 1e-4 |\n| `bitfit`| train only the bias terms (~0.1% of params) | **unquantized** | 5e-4 |\n| `prompt`/`ptuning` | soft prompts / p-tuning — learned virtual tokens | either | 5e-3 |\n| `adapter` | bottleneck adapter modules after each layer | either | 1e-4 |\n\nBase requirements are enforced with clear errors (e.g. `qlora` on a 16-bit model\ntells you to load a 4-bit one). Adding your own method is one file —\n`methods.register(TrainingMethod(...))`.\n\n## Backends \u0026 hardware\n\n`torch` (CUDA) is the production backend; `mlx` is the local-dev loop on Apple\nSilicon; `remote` runs the same API against any ShadowLM server; `verl` is the\nproduction, multi-GPU RL engine (vLLM rollouts + FSDP) for cluster-scale GRPO —\n`pip install shadowlm[verl]`, then `slm.load(model, backend=\"verl\").finetune(ds,\nmethod=\"grpo\", reward_fns=[…])`. `auto` picks the right one for SFT/local work.\nThe torch path rides HuggingFace `Trainer` + `accelerate`, so it trains on **any\naccelerator HuggingFace supports** — pick it with `device=`:\n\n| ecosystem | how |\n|-----------|-----|\n| NVIDIA CUDA | `device=\"cuda\"` (+ 4-bit, flash-attn, fused optim) |\n| AWS Trainium · Google TPU | `device=\"xla\"` (Neuron / `torch-xla`) |\n| Intel GPU | `device=\"xpu\"` · Apple `backend=\"mlx\"` · CPU `device=\"cpu\"` |\n\nOn Microsoft Azure / any cloud you run on NVIDIA GPUs — the `cuda` path, nothing\nto configure.\n\n## Install\n\nOne command — installs the right backend for your machine and opens the studio:\n\n```bash\ncurl -fsSL https://install.shadowlm.sh | sh\n```\n\nIt detects your hardware and installs the matching stack — Apple Silicon → mlx,\nNVIDIA → torch + Liger fused kernels, otherwise torch CPU — into an isolated env\nin `~/.shadowlm/venv`, then launches `shadowlm serve` at `http://127.0.0.1:8329`.\nRe-run any time to upgrade. Override with `SHADOWLM_EXTRAS=cli` (UI only),\n`SHADOWLM_PORT=…`, or `SHADOWLM_NO_SERVE=1` (install without launching).\n\nOr with pip — `pip install shadowlm` ships the full training stack (torch +\nHuggingFace, retrieval, CLI). On Apple Silicon the mlx dev backend is pulled in\nautomatically. Two extras stay opt-in for specialized hardware:\n\n| extra | adds |\n|-------|------|\n| `[kernels]` | fused Triton kernels on NVIDIA (Liger, Apache-2.0) |\n| `[verl]` | the VERL distributed-RL backend (`backend=\"verl\"`) |\n\n```bash\ngit clone https://github.com/open-gitagent/shadowLM \u0026\u0026 cd shadowLM\npython3 -m venv .venv \u0026\u0026 source .venv/bin/activate \u0026\u0026 pip install -e .\npython examples/quickstart.py    # datasets → finetune → inference, end to end\n```\n\nNo hardware handy? Test-drive the whole thing — checkpoints, faiss MoRE, APO —\non a free Colab GPU:\n[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/open-gitagent/shadowLM/blob/main/examples/colab_test_drive.ipynb)\n\nRun output (mlx, a 0.5B model, ~3.5s):\n\n```\n[shadow] enabled: gradient checkpointing\n[mlx:gpu] finetuning Qwen2.5-0.5B-Instruct-4bit · lora · 40 iters · lora r=16\n  [████████████████████████] step 40/40  loss 0.0718  lr 5.00e-05  1,048 tok/s\n  loss  ▇▆█▇▆▇▇█▅▅▄▅▃▂▃▃▁▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁  4.2120 → 0.0718\n  ♥ succeeded · 40 steps · 3.5s\n```\n\n## CLI \u0026 studio\n\n```bash\nshadowlm finetune data.jsonl --model Qwen/Qwen2.5-0.5B-Instruct --method lora\nshadowlm finetune --config run.yaml --dry-run   # reproducible runs, preview first\nshadowlm chat out/adapter/                       # talk to what you trained\nshadowlm serve                                   # studio UI + API on one port\n```\n\nHeadline hyperparameters are typed flags; every other `TrainConfig` field is\nreachable via `--set field=value` or a `--config` file (flags override config\noverride defaults). `shadowlm serve` opens the **studio** at `http://127.0.0.1:8329`\n— Datasets (upload + HuggingFace) → Models → guided Train → live Runs (loss\ncharts + training console) → Playground (compare base ↔ finetuned). It's the\nbuilt React app, shipped in the wheel; the same JSON protocol powers\n`backend=\"remote\"`.\n\n## The shadow accelerator\n\n`accelerator=\"shadow\"` turns on the optimizations that are safe for your model\nand hardware — gradient checkpointing, flash-attention-2, a fused 8-bit\noptimizer, 4-bit QLoRA, and optional [Liger](https://github.com/linkedin/Liger-Kernel)\nfused Triton kernels (`[kernels]` extra, NVIDIA). Modes: `auto` / `shadow` /\n`none`. It logs exactly what it enabled and no-ops when something isn't\navailable — ShadowLM integrates proven optimizations rather than shipping its own\nGPU kernels, so no magic multipliers, just the standard wins turned on safely.\n\n## The road ahead\n\nThe engine ships first; **ShadowLM Studio** (the hosted tier) wraps this exact\nAPI — nothing reimplemented — to turn the blocks into a one-click migration:\n\n- **Decision inbox** — captured traces surfaced for human approve/correct into chosen-vs-rejected pairs (today: auto-scored by an LLM judge).\n- **Eval gates** — advance only when quality holds *and* savings beat cost: task-level evals + cost-per-task on the run records.\n- **Shadow router** — the capture proxy evolved: run the shadowLM in parallel behind the live agent, then shift traffic % frontier → owned.\n- **Fleet + teams** — GPU job queue, shared run history, dataset/adapter registry.\n\n```\n[x] SDK — datasets → finetune → inference on mlx / torch / remote\n[x] 13 methods incl. MoRE, MoRE+ (decoupled MoE), trajectory GRPO, judge rewards\n[x] Capture proxy · shadow accelerator · any-hardware\n[x] Remote backend + reference server + the studio dashboard + CLI\n[ ] Studio orchestration — decision inbox · eval gates · shadow router · switch\n```\n\n## Contributing\n\nAdding a training method is one file; bug reports with a failing snippet are\ngold. Fork → branch → PR. ⭐ the repo if it trains something for you — it helps\nothers find it.\n\n[![Star History Chart](https://api.star-history.com/svg?repos=open-gitagent/shadowLM\u0026type=Date)](https://star-history.com/#open-gitagent/shadowLM\u0026Date)\n\n## License\n\n[MIT](./LICENSE) · `slm♥`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-gitagent%2Fshadowlm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopen-gitagent%2Fshadowlm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopen-gitagent%2Fshadowlm/lists"}