|
Download README.md from living-models/Botanic1-M: direct link, hf CLI and curl.
- Browser
- Download file 14.1 kB
-
https://huggingface.co/living-models/Botanic1-M/resolve/main/README.md
- Command line
-
hf download hf://living-models/Botanic1-M/README.md
-
curl -L -H "Authorization: Bearer $HF_TOKEN" -o README.md https://huggingface.co/living-models/Botanic1-M/resolve/main/README.md
14.1 kB
| license: other | |
| license_name: livingmodels-research | |
| license_link: LICENSE | |
| extra_gated_prompt: >- | |
| Botanic1 is released for non-commercial research use only (see LICENSE). | |
| Access is granted automatically; your Hugging Face username and e-mail | |
| address are shared with Living Models when you accept. | |
| extra_gated_fields: | |
| Affiliation: text | |
| I agree to use this model for non-commercial research only: checkbox | |
| # **BOTANIC-1 — Botanic1-M** | |
| > **Botanic1** is a family of plant genome foundation models from | |
| > [**Living Models**](https://www.dotomics.bio/): bidirectional Mamba-2 | |
| > (**BiMamba2**) encoders pre-trained with **masked language modeling** on | |
| > single-nucleotide tokens. Training windows come from **320 embryophyte | |
| > species**, **314.6B tokens**, in **8,192-token sequences** (`<cls>` + | |
| > 8,191 bases). | |
| **If you use Botanic1 in your research, please cite the [technical report on bioRxiv](https://www.biorxiv.org/content/10.64898/2026.09.04.749355v2):** | |
| ```bibtex | |
| @article{Barozet2026.09.04.749355, | |
| author = {Barozet, Am{\'e}lie and Cabeli, Vincent and Ogier du Terrail, Jean | |
| and Rukhovich, Alexey and Janssoone, Thomas and Klajer, Gary | |
| and Sheikhitarghi, Zeinab and Andrews, Gregory and Veran, Cyril | |
| and Strouk, L{\'e}onard}, | |
| title = {BOTANIC-1: a series of long-context plant genomic foundation | |
| models in the agentic era}, | |
| journal = {bioRxiv}, | |
| year = {2026}, | |
| elocation-id = {2026.09.04.749355}, | |
| doi = {10.64898/2026.09.04.749355}, | |
| publisher = {Cold Spring Harbor Laboratory}, | |
| URL = {https://www.biorxiv.org/content/early/2026/09/09/2026.09.04.749355}, | |
| eprint = {https://www.biorxiv.org/content/early/2026/09/09/2026.09.04.749355.full.pdf}, | |
| } | |
| ``` | |
| --- | |
| ## ⚠️ Research use only | |
| **These models are intended for research use only.** They must not be used in | |
| production, clinical, or diagnostic contexts, or for any purpose other than | |
| non-commercial research and experimentation. Living Models and the model | |
| providers disclaim any liability for use outside this scope. | |
| --- | |
| ## Model variants | |
| | Model | Params | Hidden size | Layers | fp32 weights | S_bal^train | Access | | |
| |-------|-------:|------------:|-------:|-------------:|------------:|--------| | |
| | S (`living-models/Botanic1-S`) | 318M | 1024 | 24 | 1.3 GB | 0.735 | public, gated | | |
| | M (`living-models/Botanic1-M`) | 688M | 1024 | 52 | 2.8 GB | 0.743 | public, gated | | |
| | L (`living-models/Botanic1-L`) | 2.1B | 1536 | 72 | 8.4 GB | 0.746 | public, gated | | |
| | XL (`living-models/Botanic1-XL`) | 3.2B | 1792 | 80 | 12.7 GB | 0.748 | private | | |
| **S_bal^train** is the species-balanced composite of the technical report | |
| (mean over 9 task families of per-family species means) computed on the | |
| benchmark's **train split**. The report's leaderboard reports **S_bal^test** | |
| on the held-out test split. The two are not interchangeable; take | |
| leaderboard numbers from the report, not from this table. | |
| **This card: Botanic1-M** (688M, hidden size 1024, | |
| 52 BiMamba2 blocks, d_state 128, headdim 64, expand 2). | |
| - **Tokenizer**: single-nucleotide (`A/T/C/G/N`, one token per base) plus | |
| `<cls>`, `<mask>`, `<pad>`, `<unk>`. A `<cls>` token is prepended; no | |
| BOS/EOS. The model embeds 9 token ids. Lower-case input is upper-cased. | |
| - **Architecture**: each block runs two independent Mamba-2 scans (forward and | |
| time-reversed) and averages them — bidirectional without attention, no | |
| positional embeddings. | |
| - **Context**: pre-training sequences are 8,192 tokens (`<cls>` + 8,191 | |
| bases). `max_seqlen` in `config.json` is 8,194 tokens; `embed_sequences` | |
| truncates to it and `score_variant_zero_shot` rejects longer inputs. The | |
| SSM has no positional embeddings, so longer inputs run when called directly | |
| but are untested. | |
| - **Pre-training**: MLM (15% mask probability), 314.6B tokens, WSD schedule, | |
| fully decayed at the released checkpoint, reverse-complement augmentation | |
| with probability 0.5. | |
| --- | |
| ## Installation | |
| Access to `living-models/Botanic1-M` is gated: while logged in to Hugging Face, accept the | |
| terms at the top of the model page (your username and e-mail address are | |
| shared with Living Models), then authenticate locally so the download can use | |
| your token. | |
| ```bash | |
| pip install "torch>=2.8" "transformers>=4.57" "huggingface_hub>=0.36" | |
| hf auth login | |
| ``` | |
| For the tutorials (2–4 below): | |
| ```bash | |
| pip install "datasets>=3" "xgboost>=3" "peft>=0.20" scikit-learn pandas tqdm | |
| brew install libomp # macOS only: the xgboost wheel links Homebrew's OpenMP | |
| ``` | |
| `datasets<3` fails against current `pyarrow` with | |
| `AttributeError: module 'pyarrow' has no attribute 'PyExtensionType'`; keep | |
| the `>=3` pin. | |
| Tested from scratch in two fresh virtual environments on macOS 15 (Apple M4 | |
| Pro, 24 GB) and, for the CUDA numbers, on one H200: | |
| | | venv A | venv B | | |
| |---|---|---| | |
| | Python | 3.12 | 3.11 | | |
| | torch | 2.14.0 | 2.8.0 | | |
| | transformers | 5.16.1 | 4.57.6 | | |
| | huggingface_hub | 1.30.0 | 0.36.2 | | |
| | datasets | 5.0.1 | 5.0.1 | | |
| | xgboost | 3.4.1 | 3.2.0 | | |
| | peft | 0.20.0 | 0.20.0 | | |
| | scikit-learn | 1.9.0 | 1.9.0 | | |
| The tutorial scripts live in this repo's *Files* tab. Download them (they | |
| share `tutorial_common.py`): | |
| ```bash | |
| hf download living-models/Botanic1-M tutorial_common.py zero_shot_llr.py \ | |
| frozen_probe_tis.py finetune_tis.py benchmark_paths.py --local-dir botanic1_tutorials | |
| cd botanic1_tutorials | |
| ``` | |
| Tutorials 3 and 4 also download the PlantCAD2 TIS split | |
| (`kuleshov-group/cross-species-single-nucleotide-annotation`, `TIS/train.tsv` | |
| + `TIS/valid.tsv`, ~130 MB) on first run. | |
| ### Devices, memory and batch sizes | |
| The implementation is self-contained pure PyTorch and runs on **CPU, Apple | |
| Silicon (MPS) and CUDA** in fp32. Every tutorial picks `cuda`, then `mps`, | |
| then `cpu`, and takes `--device` to override (`finetune_tis.py` uses the | |
| Hugging Face Trainer's device selection and `--cpu`). | |
| On CUDA, the `mamba_ssm` + `causal_conv1d` kernels are used automatically | |
| when installed (`pip install mamba-ssm causal-conv1d`). Set | |
| `BOTANIC1_FORCE_PURE_TORCH=1` to disable them. Parity of the two paths, | |
| measured on H200 for all four sizes: argmax agreement 1.000000, Pearson | |
| ≥ 0.9999993 on logits, max |Δ log-prob| ≤ 0.06. MPS vs CPU (S and M): max | |
| |Δ logit| ≤ 3e-5, argmax agreement 1.0. Forward-pass throughput of this | |
| size, measured with `benchmark_paths.py` (fp32 weights, random 513-token | |
| windows, 5 timed iterations after a warm-up): | |
| | Measured on | batch × tokens | pure torch tok/s | kernels tok/s | speed-up | max \|Δlogit\| / argmax agreement | | |
| |---|---|---:|---:|---:|---| | |
| | H200 (CUDA, `mamba_ssm` kernels), scripts of this card | 32 × 513 | 13,392 | 24,558 | ×1.8 | 3.2e-02 / 1.000000 | | |
| | H200 (CUDA, `mamba_ssm` kernels), scripts of this card | 8 × 513 | 12,053 | 22,467 | ×1.9 | 9.4e-03 / 1.000000 | | |
| Measure it on your own hardware: | |
| ```bash | |
| python benchmark_paths.py --model living-models/Botanic1-M --batch-size 8 --out bench.json | |
| ``` | |
| Memory: loading needs the fp32 weights (2.8 GB for this | |
| size) plus the pure-torch scan's transient, which grows linearly with | |
| batch × sequence length. For 513-token windows the tutorials default to batch | |
| 32 on CUDA and 8 on CPU/MPS; raise `--batch-size` until memory runs out. | |
| Botanic1-S at batch 32 × 513 tokens peaks at 3.5 GiB of transient memory per | |
| scan on CPU. | |
| ### Padding behavior | |
| Like at training time, the SSM scans do **not** mask pad tokens: pads | |
| participate in the recurrence, so padding is not neutral. Because the model | |
| is bidirectional, pad tokens at the end of a sequence change the outputs of | |
| the real tokens before them. `attention_mask` is accepted for API | |
| compatibility but ignored by the backbone. Prefer batches of equal-length | |
| sequences. | |
| --- | |
| ## Examples of use | |
| ### 1. Generating embeddings | |
| ```python | |
| from transformers import AutoModel, AutoTokenizer | |
| model_name = "living-models/Botanic1-M" | |
| model = AutoModel.from_pretrained(model_name, trust_remote_code=True) | |
| tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True) | |
| model.to("cuda") # or "mps" / "cpu" | |
| embeddings = model.embed_sequences( | |
| ["ACGTACGTNNACGT", "ACGTACGTACGTAC"], | |
| tokenizer, | |
| average_with_reverse_complement=True, | |
| )["post_encoder_norm"] # (batch, seq_len, 1024) | |
| sequence_embedding = embeddings.mean(dim=1) # mean-pool -> (batch, 1024) | |
| ``` | |
| `average_with_reverse_complement=True` embeds the reverse complement as a | |
| second pass and averages the two outputs **position by position**. Position | |
| *i* of the reverse-complement pass describes base *L−1−i* of the input, so | |
| the averaged per-position vectors are **not nucleotide-aligned**. Use the | |
| option only ahead of pooling (as above) to get a strand-agnostic | |
| sequence-level vector. For per-nucleotide features, embed each strand | |
| separately and flip the reverse-complement output along the sequence axis | |
| yourself. | |
| Other layers: `layer_names=[0, 11, "post_encoder_norm"]` (block indices or | |
| submodule names). | |
| ### 2. Zero-shot variant effect scoring (LLR) | |
| LLR = log P(alt) − log P(ref) from the masked logits at the variant position | |
| (one nucleotide = one token, so exactly one token is masked). Deleterious | |
| variants score negative. On the whole-suite zero-shot LLR benchmark of the | |
| technical report, Botanic1-M reaches **AUROC 0.713**. | |
| ```python | |
| # PHYB gene (AT2G18790) in Arabidopsis thaliana | |
| # 500 bp around the ATG start codon: 5'UTR (pos 0-249) | CDS (pos 250+) | |
| sequence = ( | |
| "TTTTTTTTTGTTATCTCTCTCTATCTGAGAGGCACACATTTTGCTTCGTCTTCTTCAATTTATTTTATTGGTTTCTC" | |
| "CACTTATCTCCGATCTCAATTCTCCCCATTTTCTTCTTCCTCAAGTTCAAAATTCTTGAGAATTTAGCTCTACCAGA" | |
| "ATTCGTCTCCGATAACTAGTGGATGATGATTCACCCTAAATCCTTCCTTGTCTCAAGGTAATTCTGAGAAATTTCTC" | |
| "AAATTCAAAATCAAACGGCATGGTTTCCGGAGTCGGGGGTAGTGGCGGTGGCCGTGGCGGTGGCCGTGGCGGAGAA" | |
| "GAAGAACCGTCGTCAAGTCACACTCCTAATAACCGAAGAGGAGGAGAACAAGCTCAATCGTCGGGAACGAAATCTC" | |
| "TCAGACCAAGAAGCAACACTGAATCAATGAGCAAAGCAATTCAACAGTACACCGTCGACGCAAGACTCCACGCCGT" | |
| "TTTCGAACAATCCGGCGAATCAGGGAAATCATTCGACTACT" | |
| ) | |
| # Start codon: mutate the T of ATG | |
| llr_atg = model.score_variant_zero_shot( | |
| sequence=sequence, tokenizer=tokenizer, variant_pos=251, variant_char="C", | |
| ) | |
| # 5'UTR position | |
| llr_utr = model.score_variant_zero_shot( | |
| sequence=sequence, tokenizer=tokenizer, variant_pos=155, variant_char="A", | |
| ) | |
| print(f"ATG T->C: {llr_atg:+.4f} 5'UTR T->A: {llr_utr:+.4f}") | |
| ``` | |
| Full script with device selection and a results JSON: `zero_shot_llr.py` | |
| (`python zero_shot_llr.py --model living-models/Botanic1-M`). Values it produced: | |
| | Measured on | ATG T→C (pos 251) | 5'UTR T→A (pos 155) | | |
| |---|---:|---:| | |
| | H200 (CUDA, `mamba_ssm` kernels), scripts of this card | -4.4086 | -0.2816 | | |
| A strongly negative LLR flags the start-codon change as disruptive. A | |
| near-zero LLR means the model finds both alleles about equally likely in | |
| this 500 bp context; it is **not** evidence that the variant is neutral. The | |
| model sees no expression, phenotype, or population data, and LLR magnitudes | |
| are not calibrated across positions or species. | |
| ### 3. XGBoost probing on frozen embeddings (PlantCAD-TIS) | |
| Frozen-probe protocol on the "TIS" (translation initiation site) binary task | |
| from the PlantCAD2 dataset suite (Zhai et al. 2025): embed each 512 bp window, | |
| take the middle-nucleotide embedding (token index 1 + 256), train XGBoost on | |
| the train split, score the valid split. Full script: `frozen_probe_tis.py`. | |
| ```bash | |
| python frozen_probe_tis.py --model living-models/Botanic1-M --num-samples 1000 # -1 = full dataset | |
| ``` | |
| The script saves the embeddings (`embeddings_*.npy`, `labels_*.npy`), the | |
| classifier (`xgb_model.json`) and `results.json` under | |
| `botanic1_tis_probe/Botanic1-M/n<num-samples>/`. Retrain the classifier | |
| without re-embedding with `--reuse-embeddings`; reload the classifier with | |
| `xgb.XGBClassifier().load_model(path)`. | |
| Values it produced (strand-aware: minus-strand windows are reverse-complemented): | |
| | Setting | Measured on | AUC-PR | AUROC | | |
| |---|---|---:|---:| | |
| | N=1000 samples | H200 (CUDA, `mamba_ssm` kernels), scripts of this card | 0.9228 | 0.9677 | | |
| | Full dataset | H200 (CUDA, `mamba_ssm` kernels), scripts of this card | 0.9298 | 0.9747 | | |
| For reference, the technical report's PlantCAD-TIS score on **Arabidopsis | |
| thaliana** (stratified, species-balanced, different protocol) is | |
| 0.909 for this model. | |
| ### 4. Fine-tuning (LoRA or full) | |
| `Botanic1ForSequenceClassification` adds a CLS-pooled classification head. | |
| Full script: `finetune_tis.py` (LoRA via `peft` targeting the SSM | |
| `in_proj`/`out_proj` with the head trained fully, or full fine-tuning). | |
| ```bash | |
| python finetune_tis.py --model living-models/Botanic1-M --mode lora --num-samples 2000 --epochs 3 | |
| ``` | |
| Memory for training is set by the per-device batch: backward through the | |
| pure-torch scan keeps the chunk intermediates of every layer. Botanic1-S | |
| trains at `--batch-size 16` on one H200 (kernel path) but needs | |
| `--batch-size 2 --grad-accum 8` (same effective batch of 16) on a 24 GB | |
| Apple M4 Pro, where batch 8 exhausts MPS memory; Botanic1-XL needs | |
| `--batch-size 8 --grad-accum 2` even on an H200. The `batch × grad-accum` | |
| column below records what each measurement used. | |
| The seed (`--seed`, default 0) is applied before the data subsample, the | |
| adapter and the classifier head are created. The trained weights (adapter + | |
| head for LoRA, full model otherwise) and the tokenizer land in | |
| `botanic1_tis_ft/Botanic1-M/lora_n2000/final/`; the script reloads them | |
| and checks the logits before exiting. Reload a LoRA run with | |
| `PeftModel.from_pretrained(base_model, final_dir)`, a full run with | |
| `AutoModelForSequenceClassification.from_pretrained(final_dir, trust_remote_code=True)`. | |
| Values it produced (LoRA, N=2000, 3 epochs, seed 0): | |
| | Measured on | batch × grad-accum | AUC-PR | AUROC | | |
| |---|---|---:|---:| | |
| | H200 (CUDA, `mamba_ssm` kernels), scripts of this card | 16 × 1 | 0.8250 | 0.9481 | | |
| --- | |
| ## License | |
| - **Model**: see the [LICENSE](LICENSE) for terms of use and citation. | |
| --- | |
| *Model card maintained by Living Models. For questions or issues, please | |
| contact Living Models.* | |