Agentic multi-modal transcriptomics pipeline powered by LangGraph
Project description
Biocabinet
An agentic transcriptomics analysis platform built on LangGraph. It orchestrates FastQC → trimming → alignment → quantification → normalisation → differential expression → GNN-based PPI enrichment, with an optional RAG layer that grounds LLM summaries in KEGG and Reactome pathway knowledge.
The pipeline is agentic at the decision points, not just the prose: an LLM (with deterministic guardrails) decides whether a sample passes FastQC, what Trimmomatic steps to apply, what experiment type an input directory contains, and — in the spatial pipeline — whether suspicious clusters are a real cell type or an imaging batch effect. Every LLM decision is validated against hard metrics and falls back to rule-based logic if the model is unavailable or unreliable.
Architecture
Orchestrator (LangGraph)
│
├── Bulk RNA-seq sub-pipeline
│ ├── FastQC → Trimmomatic → STAR → featureCounts
│ ├── Normalisation (TPM / FPKM / RPKM)
│ ├── Differential Expression (PyDESeq2)
│ └── Summarise ← RAG-augmented (Phase 4a)
│
├── scRNA-seq sub-pipeline
│ ├── Load (h5ad / 10x / pbmc3k)
│ ├── QC → Filter → Normalise → PCA
│ ├── Cluster (Leiden / UMAP)
│ └── Marker genes → Summarise ← RAG-augmented
│
├── Spatial (imaging) sub-pipeline (in development — Vizgen/MERSCOPE)
│ ├── Load (squidpy Vizgen cell tables)
│ ├── QC (blank-FDR, per-cell counts/volume, FOV outliers)
│ ├── Cluster (PCA → Leiden)
│ └── FOV-bias check ← agentic (metrics + LLM + Harmony correct/re-cluster loop)
│
├── Enrichment sub-pipeline (auto-chained after bulk)
│ ├── Load PPI graph (STRING / SHS27k)
│ ├── GNN training (GIN, BFS split)
│ ├── Evaluation (test1/2/3 buckets)
│ └── Inference → Summarise ← RAG-augmented
│
└── RAG Q&A session (Phase 4b — interactive, after final report)
└── Retriever → LLM synthesis → Citations
Graph diagrams (Mermaid + PNG) live in docs/.
Installation
git clone https://github.com/ishitajain9717/biocabinet.git
cd biocabinet
python -m venv .venv && source .venv/bin/activate
# Option A: editable install (recommended — registers the `rnaseq-agent` CLI)
pip install -e ".[llm]"
# Option B: plain requirements files
pip install -r requirements.txt -r requirements-llm.txt
Python dependencies (all modalities)
Installed via pip install -e ".[llm]" from pyproject.toml. These are imported in code — no separate binary on PATH.
| Package | Used by | Role |
|---|---|---|
langgraph, langchain-core |
Orchestrator, all graphs | Agent workflow + state |
pandas, numpy, scipy |
Bulk, scRNA, enrichment | Tables and numerics |
pydeseq2 |
Bulk | Differential expression (DESeq2) |
scanpy |
scRNA, Spatial | Load h5ad/10x, QC, normalize, PCA, cluster, markers |
squidpy |
Spatial | Read MERSCOPE/Vizgen cell tables into AnnData |
harmonypy |
Spatial | FOV batch correction in the bias-check loop |
python-dotenv |
All | Auto-load LLM config from .env |
torch, torch-geometric |
Enrichment | GNN training and inference |
transformers |
Enrichment, RAG | BioBERT pathway text embeddings |
fair-esm |
Enrichment | ESM-2 protein sequence embeddings |
mygene |
Bulk (DEG → enrichment) | ENSG → ENSP mapping |
requests, tenacity |
Enrichment (pathway build) | KEGG / Reactome / WikiPathways APIs |
langchain-openai, langchain-ollama |
Summarise, RAG (optional) | LLM summaries and Q&A |
scRNA clustering (Leiden / UMAP) runs inside Scanpy. If Leiden fails at runtime, install graph backends:
pip install leidenalg python-igraph
Requirements by modality
Bulk RNA-seq
Workflow: FASTQ → FastQC → agentic QC gate → agentic trim gate (LLM picks Trimmomatic steps from the FastQC report) → STAR → featureCounts → TPM/FPKM/RPKM → PyDESeq2 → summarise (+ RAG).
The QC gate lets the agent drop a failing sample and continue with the rest of the batch rather than aborting the run; the trim gate generates sample-specific Trimmomatic arguments, validated against the FastQC metrics before execution.
| Type | Requirement | Notes |
|---|---|---|
CLI on PATH |
FastQC | QC |
| STAR | Alignment | |
| featureCounts (Subread) | Gene counts | |
| Trimmomatic | Adapter/quality trim | |
java |
Runs Trimmomatic | |
Python (pip) |
pydeseq2, pandas, mygene |
DEG + pair export for enrichment |
| Reference data | STAR genome index + GTF | Not in git |
| Input | Paired FASTQ + sample sheet | |
| Optional | LLM env vars | RAG-augmented summary |
scRNA-seq
Workflow: Load (h5ad / 10x / pbmc3k) → QC metrics → filter → normalize → HVG → PCA → neighbors → Leiden → UMAP → marker genes → summarise (+ RAG).
| Type | Requirement | Notes |
|---|---|---|
CLI on PATH |
(none) | Entire pipeline is Scanpy in Python |
Python (pip) |
scanpy, numpy, scipy, pandas |
Core analysis |
leidenalg, python-igraph |
Leiden clustering | |
| Input | .h5ad, 10x folder, or pbmc3k |
|
| Optional | data/pbmc3k_raw.h5ad |
Cached demo data |
| Optional | LLM + RAG index | Marker-gene pathway context in summary |
Spatial transcriptomics (imaging-based)
Status: in active development. The v1 scope targets imaging-based platforms — MERSCOPE / Vizgen — starting from the post-segmentation cell tables (segmentation is the user's responsibility). The node-level building blocks are implemented and tested; final assembly into the orchestrated LangGraph (scripts/spatial/graph.py) is still in progress, so the orchestrator currently routes spatial inputs to a stub.
Planned workflow: Load (squidpy Vizgen reader) → QC (blank-FDR, per-cell counts/genes/volume, FOV outliers) → normalize → cluster (PCA → Leiden) → FOV-bias check → annotation (CeLLama-style, reimplemented in Python) → summarise (+ RAG).
| Type | Requirement | Notes |
|---|---|---|
CLI on PATH |
(none) | Entire pipeline is Python |
Python (pip) |
squidpy, scanpy, harmonypy |
Read tables, QC/cluster, batch correction |
leidenalg, python-igraph |
Leiden clustering | |
| Input | *_cell_by_gene.csv + *_cell_metadata.csv |
MERSCOPE per-region exports |
| Optional | LLM env vars | Agentic FOV-bias adjudication |
The FOV-bias check is the spatial pipeline's flagship agentic step. Imaging-based data is captured tile-by-tile (each tile = a field of view, FOV), and per-FOV imaging differences can split one real cell type into several clusters. The node:
- Computes deterministic evidence — iLISI (do expression-neighbors mix across FOVs?), Cramér's V (is cluster identity explained by FOV?), and the fraction of cells in FOV-pure clusters.
- Hands that evidence to an LLM, which returns
BATCH_EFFECT/BIOLOGY/UNCERTAINplus an action — with guardrails that override the model in both directions (never silently keep an obvious artifact, never over-correct clean biology) and a rule-based fallback. - If a batch effect is confirmed, runs Harmony correction on the FOV label, re-clusters, and re-verifies that the split actually collapsed before accepting the result.
Enrichment (GNN-PPI)
Workflow: Load PPI graph + ESM-2 + pathway embeddings → train GIN (BFS split) → bucketed eval → inference on DEG pairs. Auto-chained after a successful bulk run from the orchestrator.
| Type | Requirement | Notes |
|---|---|---|
CLI on PATH |
(none) | Training and inference are PyTorch |
Python (pip) |
torch, torch-geometric, transformers, fair-esm |
Model + embeddings |
| Reference data | data/ppi_SHS27k.tsv, data/esm2_embeddings_SHS27k.pt, data/pathway/06_pathway_embeddings_combined.pt |
SHS27k benchmark |
| Upstream | Bulk DEG deg_pairs.tsv |
Optional |
| Optional | GPU (device=cuda / mps) |
Faster training |
Pathway embedding build (one-time, before merge):
python -m scripts.enrichment.pathway_embed
python -m scripts.enrichment.reactome_embed
python -m scripts.enrichment.wikipathways_embed
python -m scripts.enrichment.merge_pathway_embeddings
python -m scripts.enrichment.precompute_esm
RAG (pathway Q&A)
Workflow: Build index once → retriever (BioBERT cosine search) → answerer (LLM + citations) → augment pipeline summaries (4a) → optional interactive chat after orchestrator (4b).
| Type | Requirement | Notes |
|---|---|---|
CLI on PATH |
(none) | Search and embed in Python |
Python (pip) |
transformers, torch |
BioBERT at index build and query time |
langchain-openai or langchain-ollama |
Prose answers | |
| Reference data | KEGG + Reactome text under data/pathway/ |
Source for build_index |
| Generated | data/rag/docs.jsonl, embeddings.npy, gene_to_doc_ids.json |
Local library |
python -m scripts.rag.build_index # once, after pathway data exists
python -m scripts.rag.retriever "cell cycle CDK4" # smoke-test retrieval
python -m scripts.rag.graph # interactive Q&A
Bulk runs can set pathway interests at config time (e.g. cell cycle, apoptosis); matching DEGs are always included in RAG gene selection before the top-60% rule.
Orchestrator
| Type | Requirement | Notes |
|---|---|---|
Python (pip) |
All of the above for chosen modality | Lazy-imports child graphs |
| Persistence | pipeline_runs.sqlite |
LangGraph SqliteSaver; created on first run |
| LLM | OLLAMA_MODEL or OPENAI_API_KEY |
Final report + RAG chat; optional |
The orchestrator auto-detects the modality from the input path (FASTQ/sample-sheet → bulk, 10x/h5ad → scRNA, Vizgen CSVs or spatial-coordinate h5ad → spatial) via scripts/common/data_detect.py, shows the evidence, and asks for confirmation rather than presenting a blind menu. A confirmed bulk_rnaseq run chains bulk → enrichment (if bulk succeeds) → final report → optional RAG Q&A; scrna runs scRNA only, then report and optional RAG.
Data setup
See data/README.md for instructions on downloading the required reference files, PPI graph, and pre-computed embeddings.
Running
Full orchestrated pipeline
python -m scripts.orchestrator
# resume a previous run
python -m scripts.orchestrator --thread-id orchestrator_20260520_094200
Individual sub-pipelines
# Bulk RNA-seq
python -m scripts.bulk_rnaseq.graph
# scRNA-seq
python -m scripts.scrna.graph
# Enrichment (GNN-PPI)
python -m scripts.enrichment.graph
# Build RAG index (run once)
python -m scripts.rag.build_index
# Interactive RAG Q&A
python -m scripts.rag.graph
LLM configuration
The pipeline uses an LLM for plain-English summaries and RAG-grounded answers. Configure via environment variables — no API keys in code:
# Option A: local Ollama (free, offline)
export OLLAMA_MODEL=llama3
# Option B: OpenAI
export OPENAI_API_KEY=sk-...
export OPENAI_MODEL=gpt-4o-mini # optional, default is gpt-4o-mini
These can also be placed in a .env file at the repo root — it is auto-loaded via python-dotenv. If neither provider is set, all summarise nodes and every agentic gate (FastQC, trimming, data-type detection, FOV-bias) fall back to deterministic rule-based logic.
Project layout
scripts/
├── orchestrator.py top-level LangGraph orchestrator
├── bulk_rnaseq/ bulk RNA-seq sub-pipeline
│ ├── config.py PreprocessingConfig dataclass + CLI prompts
│ ├── nodes.py core bioinformatics functions
│ ├── graph_nodes.py LangGraph wrapper nodes
│ ├── graph_state.py PipelineState TypedDict
│ └── graph.py graph builder
├── scrna/ scRNA-seq sub-pipeline (same structure)
├── spatial/ spatial (imaging / Vizgen) sub-pipeline — in development
│ ├── config.py SpatialConfig (Vizgen CSVs + QC thresholds)
│ ├── nodes.py load_vizgen, spatial_qc, clustering, fov_bias_check
│ ├── graph_nodes.py LLM FOV-bias adjudication + guardrails
│ └── graph.py graph builder (assembly in progress)
├── enrichment/ GNN-PPI enrichment sub-pipeline
│ ├── pathway_embed.py KEGG pathway embeddings (BioBERT)
│ ├── reactome_embed.py Reactome pathway embeddings
│ ├── wikipathways_embed.py WikiPathways embeddings
│ ├── merge_pathway_embeddings.py multi-source merge + dedup
│ ├── precompute_esm.py ESM-2 protein sequence embeddings
│ ├── gnn_data.py PPI graph + feature assembly
│ ├── gnn_model.py GIN model definition
│ ├── gnn_train.py training loop (BFS split)
│ ├── gnn_test.py bucketed evaluation (test1/2/3)
│ └── inference.py predict interactions for novel pairs
├── rag/ RAG layer
│ ├── build_index.py Phase 1 — build pathway document library
│ ├── retriever.py Phase 2 — cosine similarity search
│ ├── answerer.py Phase 3 — LLM synthesis with citations
│ ├── augment.py Phase 4a — auto-augment pipeline summaries
│ ├── graph_state.py Phase 4b — RagChatState
│ ├── artifact_reader.py scan a run dir for STAR/featureCounts/FastQC/DEG/GNN artifacts
│ ├── graph_nodes.py Phase 4b — chat loop nodes (+ LLM data-type inference)
│ └── graph.py Phase 4b — interactive Q&A graph
└── common/
├── node_result.py NodeResult dataclass (shared across pipelines)
└── data_detect.py auto-detect modality (bulk / scRNA / spatial) from a path
Checkpointing and resumption
All pipeline state is persisted to pipeline_runs.sqlite via LangGraph's SqliteSaver.
If a run is interrupted, resume it by passing the printed --thread-id.
Child pipelines (bulk, enrichment) share the same checkpointer as the orchestrator, so partial child runs are also resumable.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file biocabinet-0.1.0.tar.gz.
File metadata
- Download URL: biocabinet-0.1.0.tar.gz
- Upload date:
- Size: 146.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a14651103f885effe7b26fa2081d22688cc9329adbf947c258a2ad2b1375c5dd
|
|
| MD5 |
baea9fa0313bece2266a20bb4e9fd39e
|
|
| BLAKE2b-256 |
6348eb59667b79d1a8c801a49799427313961937a14cb7867e446a615b434d8b
|
File details
Details for the file biocabinet-0.1.0-py3-none-any.whl.
File metadata
- Download URL: biocabinet-0.1.0-py3-none-any.whl
- Upload date:
- Size: 168.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1471ea9084ffe0045507c1096e4bc4530bd7d1dee7c0e1e7da37748ca74126b4
|
|
| MD5 |
449d1e53009eb976542289fffc03901d
|
|
| BLAKE2b-256 |
2f032584b2d155d7444a0bbc6b1d00e5768c9d1838eeb6396da4b7abc607f64c
|