Skip to content

Repository files navigation

Introducing Lotus 1.2 Mini

A sentiment-routed medical Mixture-of-Experts (MoE) LLM

a tiny sentiment classifier routes each patient query to one of two LoRA expert adapters, all sharing a single 4-bit quantized Gemma 3 4B base model (QLoRA) from Ollama, trained by Google Deepmind.

Lotus 1.2 Mini is a open-sourced, specialized patient-centered Mixture-of-Experts architecture built around a LoRA-adapted Gemma 3 fine-tuned by CodeTheCure Labs.

user prompt
  |--> SentimentRouter  (DistilBERT SST-2 via ONNX)
  |        P(POS) >= 0.5  -> POS expert  (grateful / reassured patients)
  |        else            -> NEG expert  (worried / anxious patients)
  v
shared 4-bit Gemma 3 4B (mlx-community/gemma-3-4b-it-4bit)
  + teh chosen expert's LoRA adapter
  v
some kind of medical answer

how to run Lotus 1.2 mini

Requires (for now… because fine-tuning was run on MLX, which is macOS-native) macOS with Apple Silicon (not Intel) and uv.

git clone https://github.com/2028badivi/lotus-mini.git
cd lotus-mini

./scripts/setup.sh  #should be around 256 ish MB, excluding the 3.4 GB download for the gemma 3 4b base model
uv run moe.py "I've had chest pain for three days and I'm scared.” # or whatever example you would like to test

First inference downloads the ~3.4 GB 4-bit base model from Hugging Face once, then caches it under ~/.cache/huggingface.

for inference/usage

uv run moe.py "<question>"                        # routed by sentiment
uv run moe.py --expert NEG "just a dry cough"     # force an expert (remembr that experts are rooted by negative or positive sentiment classified under DistilBERT) 
uv run moe.py --compare "<question>"              # base vs NEG vs POS
uv run moe.py --interactive                       # chat loop
uv run moe.py --verbosity 2 "<question>"          # longer answers
uv run moe.py --verbose "<question>"              # debug logs

how to re-fine-tune Lotus 1.2 mini from scratch (not recommended but still possible)

uv run prepare_data.py # download medical dataset originally used to train Lotus 1.2 mini
uv run train.py # orig script w/o verbosity
#uv run train.py --experts POS #if you want to do only certain experts
#uv run train.py —verbose #recommended if you want to retrain w/ verbosity

Training streams a live tqdm bar (loss, tok/s, ETA) plus a heartbeat every 20 s, and writes full logs to logs/<expert>_train.log.

Project layout

lotus/                core package
  constants.py        paths + model/dataset config
  router.py           SentimentRouter (ONNX) + auto-download of artifacts
  expert.py           ExpertLoader : hot-swaps LoRA adapters on the shared base
  chat.py             chat-template / dataset formatting helpers
  trainer.py          QLoRA training driver (tqdm + heartbeat streaming)
moe.py                inference CLI (sentiment-routed MoE)
prepare_data.py       dataset download + sentiment stratification
train.py              training CLI (both experts)
scripts/
  setup.sh            one-command setup (deps + router + smoke test)
  download_router.py  fetch the ONNX router artifacts from HF
  smoke_test.py       verify the setup (router-only, or full inference)
  upload_hf.py        publish adapters + router + model card to HF Hub
router/               gitignored: downloaded ONNX artifacts (see setup.sh)
data/                 sentiment-stratified JSONL expert subsets + manifest
experts/              trained LoRA adapters (neg/, pos/) : committed
logs/                 gitignored: per-expert training logs

Notable design details

  • Router is auto-downloaded. The ~256 MB ONNX model is never committed to git; SentimentRouter fetches it from Hugging Face on first use, and scripts/setup.sh pre-fetches it.
  • Expert hot-swap. All experts live on one in-memory base model; switching experts is a ~0.01 s adapter-weight swap, so routing costs nothing at inference.
  • No torch. The router runs on onnxruntime (CPU) and the LLM runs on Apple's MLX, so a full clone does not technically install PyTorch.
  • Deadlock-free trainer streaming. The trainer consumes the child process's byte stream (including tqdm \r redraws) so a pipe-buffer stall can never freeze training silently.

Disclaimer

Research/demo only. Trained on medical Q&A data; not a substitute for professional medical advice, diagnosis, or treatment.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages