Single-cell foundation model — ov.llm.SCLLMManager
When to use this skill
Pick this skill when the user wants a transformer-style per-cell representation that is structurally richer than PCA: e.g. cell embedding, zero-shot or fine-tuned cell-type annotation, batch integration on the foundation-model latent, or (model permitting) perturbation prediction. The five fully-supported backends are scGPT, Geneformer, scFoundation, UCE, CellPLM; pick by data type, hardware, and gene-ID convention.
This skill does not cover marker-rule annotators (CellTypist / SCSA / gpt4celltype) or reference-mapping annotators (popV / scmap / SingleR). For those, prefer the single-cell-annotation skill — both can coexist; the foundation embedding is often used as the input space for downstream annotation/integration.
Backend selection cheatsheet
| Model |
Tasks supported |
Species |
Gene IDs |
Min VRAM |
CPU? |
Strengths |
| scGPT |
embed, integrate, fine-tune→annotate |
human, mouse |
symbol |
8 GB |
yes |
General RNA, longest-running, multi-modal extensions |
| Geneformer |
embed, integrate, fine-tune→annotate |
human |
ENSEMBL |
4 GB |
yes |
Ensembl-id pipelines, low-VRAM |
| scFoundation |
embed, integrate |
human |
symbol |
16 GB |
no |
xTrimoGene architecture; perturbation work upstream |
| UCE |
embed, integrate |
7 species (cross-species) |
symbol |
16 GB |
no |
Zebrafish / macaque / pig / frog / lemur transfer |
| CellPLM |
embed, integrate, annotate (zero-shot) |
human |
symbol |
8 GB |
yes |
Fastest inference; cell-centric pretraining |
Common pitfalls the agent should avoid:
- Don't pick scGPT for an
annotate task without first calling fine_tune(task='annotation') — scGPT's pretrained weights only emit embeddings; annotation is the fine-tuned head.
- Don't feed Geneformer gene symbols — its tokenizer expects ENSEMBL IDs. Convert via
ov.utils.geneid_to_ensembl(...) first.
- Don't attempt
predict_perturbation on scGPT/Geneformer/UCE/CellPLM — that path is scFoundation- or domain-specific. If perturbation is required, prefer the single-cell-perturbation skill.
Canonical pipeline
import omicverse as ov
import scanpy as sc
adata = sc.read_h5ad("query.h5ad")
# 1) Pick a backend + checkpoint path. SCLLMManager loads the model.
manager = ov.llm.SCLLMManager(
model_type="scgpt", # or geneformer / scfoundation / uce / cellplm
model_path="/path/to/checkpoints/scgpt",
device="auto", # "cpu" | "cuda" | "auto"
)
# 2a) Cell embedding — works for all 5 backends.
embeddings = manager.get_embeddings(adata)
adata.obsm["X_scgpt"] = embeddings # convention: X_<backend_short>
# 2b) Cell-type annotation — zero-shot (CellPLM) or via prior fine-tuning.
result = manager.annotate_cells(adata)
adata.obs["cell_type_scgpt"] = result["predictions"]
# 2c) Batch integration — uses the foundation latent as a batch-aware embedding.
manager.integrate(adata, batch_key="batch")
# adata.obsm["X_scgpt_integrated"] is populated.
# 2d) Optional fine-tune for annotation (when zero-shot accuracy isn't enough).
# train_adata must have obs["celltype"] ground-truth.
manager.fine_tune(train_adata, valid_adata, task="annotation")
result = manager.annotate_cells(adata) # now uses fine-tuned head
adata.write_h5ad("query.h5ad")
Storage conventions (for reviewers / graders)
After running the pipeline, the AnnData should carry:
obsm["X_<backend>"] — the per-cell embedding (≥16-D, typically 256-1280-D depending on backend).
uns["neighbors"] — kNN graph computed on X_<backend> (call sc.pp.neighbors(adata, use_rep="X_<backend>")).
obs["cell_type_<backend>"] (annotation runs only) — predicted labels with the backend identifier in the column name so multi-method comparisons stay unambiguous.
Discovery hooks
print(ov.utils.registry_lookup("scgpt")) — surfaces SCLLMManager + its task-specific methods.
print(ov.utils.registry_lookup("foundation model embedding")) — same.
print(ov.utils.registry_lookup("cell type annotation")) does not intentionally surface SCLLMManager; that query routes to the rule-based / reference-mapping annotators in single-cell-annotation. Use the FM-explicit query when you mean the transformer path.
References
- Tutorials (canonical examples):
Tutorials-llm/t_scgpt.ipynb, t_geneformer.ipynb, t_scfoundation.ipynb, t_uce.ipynb, t_cellplm.ipynb.
- API:
omicverse.llm.SCLLMManager and omicverse.llm.ModelFactory (low-level factory).
- Compatibility note (2026): the legacy
ov.fm.run API was removed; SCLLMManager is the only supported foundation-model entry.
Quick reference
See reference.md for the per-method signatures, return shapes, and caveats per backend.
1---2name: omicverse-single-cell-foundation-model3description: Cell embedding, cell-type annotation, batch integration, and (where supported) perturbation prediction with single-cell foundation models — scGPT, Geneformer, scFoundation, UCE, CellPLM. Driven by the unified `ov.llm.SCLLMManager` interface; one object handles model loading, inference, and (optional) fine-tuning.4---56# Single-cell foundation model — `ov.llm.SCLLMManager`78## When to use this skill910Pick this skill when the user wants a transformer-style **per-cell representation** that is structurally richer than PCA: e.g. cell embedding, zero-shot or fine-tuned cell-type annotation, batch integration on the foundation-model latent, or (model permitting) perturbation prediction. The five fully-supported backends are **scGPT**, **Geneformer**, **scFoundation**, **UCE**, **CellPLM**; pick by data type, hardware, and gene-ID convention.1112This skill **does not** cover marker-rule annotators (CellTypist / SCSA / gpt4celltype) or reference-mapping annotators (popV / scmap / SingleR). For those, prefer the `single-cell-annotation` skill — both can coexist; the foundation embedding is often used as the input space for downstream annotation/integration.1314## Backend selection cheatsheet1516| Model | Tasks supported | Species | Gene IDs | Min VRAM | CPU? | Strengths |17|---------------|------------------------------------------|------------------------|----------|----------|-------|------------------------------------|18| **scGPT** | embed, integrate, fine-tune→annotate | human, mouse | symbol | 8 GB | yes | General RNA, longest-running, multi-modal extensions |19| **Geneformer**| embed, integrate, fine-tune→annotate | human | ENSEMBL | 4 GB | **yes** | Ensembl-id pipelines, low-VRAM |20| **scFoundation** | embed, integrate | human | symbol | 16 GB | no | xTrimoGene architecture; perturbation work upstream |21| **UCE** | embed, integrate | 7 species (cross-species) | symbol | 16 GB | no | Zebrafish / macaque / pig / frog / lemur transfer |22| **CellPLM** | embed, integrate, annotate (zero-shot) | human | symbol | 8 GB | yes | Fastest inference; cell-centric pretraining |2324**Common pitfalls** the agent should avoid:2526- *Don't* pick scGPT for an `annotate` task without first calling `fine_tune(task='annotation')` — scGPT's pretrained weights only emit embeddings; annotation is the fine-tuned head.27- *Don't* feed Geneformer gene **symbols** — its tokenizer expects ENSEMBL IDs. Convert via `ov.utils.geneid_to_ensembl(...)` first.28- *Don't* attempt `predict_perturbation` on scGPT/Geneformer/UCE/CellPLM — that path is scFoundation- or domain-specific. If perturbation is required, prefer the `single-cell-perturbation` skill.2930## Canonical pipeline3132```python33import omicverse as ov34import scanpy as sc3536adata = sc.read_h5ad("query.h5ad")3738# 1) Pick a backend + checkpoint path. SCLLMManager loads the model.39manager = ov.llm.SCLLMManager(40 model_type="scgpt", # or geneformer / scfoundation / uce / cellplm41 model_path="/path/to/checkpoints/scgpt",42 device="auto", # "cpu" | "cuda" | "auto"43)4445# 2a) Cell embedding — works for all 5 backends.46embeddings = manager.get_embeddings(adata)47adata.obsm["X_scgpt"] = embeddings # convention: X_<backend_short>4849# 2b) Cell-type annotation — zero-shot (CellPLM) or via prior fine-tuning.50result = manager.annotate_cells(adata)51adata.obs["cell_type_scgpt"] = result["predictions"]5253# 2c) Batch integration — uses the foundation latent as a batch-aware embedding.54manager.integrate(adata, batch_key="batch")55# adata.obsm["X_scgpt_integrated"] is populated.5657# 2d) Optional fine-tune for annotation (when zero-shot accuracy isn't enough).58# train_adata must have obs["celltype"] ground-truth.59manager.fine_tune(train_adata, valid_adata, task="annotation")60result = manager.annotate_cells(adata) # now uses fine-tuned head6162adata.write_h5ad("query.h5ad")63```6465## Storage conventions (for reviewers / graders)6667After running the pipeline, the AnnData should carry:6869- `obsm["X_<backend>"]` — the per-cell embedding (≥16-D, typically 256-1280-D depending on backend).70- `uns["neighbors"]` — kNN graph computed on `X_<backend>` (call `sc.pp.neighbors(adata, use_rep="X_<backend>")`).71- `obs["cell_type_<backend>"]` (annotation runs only) — predicted labels with the backend identifier in the column name so multi-method comparisons stay unambiguous.7273## Discovery hooks7475- `print(ov.utils.registry_lookup("scgpt"))` — surfaces `SCLLMManager` + its task-specific methods.76- `print(ov.utils.registry_lookup("foundation model embedding"))` — same.77- `print(ov.utils.registry_lookup("cell type annotation"))` does **not** intentionally surface SCLLMManager; that query routes to the rule-based / reference-mapping annotators in `single-cell-annotation`. Use the FM-explicit query when you mean the transformer path.7879## References8081- Tutorials (canonical examples): `Tutorials-llm/t_scgpt.ipynb`, `t_geneformer.ipynb`, `t_scfoundation.ipynb`, `t_uce.ipynb`, `t_cellplm.ipynb`.82- API: `omicverse.llm.SCLLMManager` and `omicverse.llm.ModelFactory` (low-level factory).83- Compatibility note (2026): the legacy `ov.fm.run` API was removed; SCLLMManager is the only supported foundation-model entry.8485## Quick reference8687See `reference.md` for the per-method signatures, return shapes, and caveats per backend.