
scSidekick - AskSidekick(): the AI Documentation Assistant
21_ask_sidekick.RmdOverview
AskSidekick() is a small, self-contained help assistant
for scSidekick itself. Instead of digging through
?FunctionName or the vignette index, you can just ask:
library(scSidekick)
AskSidekick("Which function do I use to split a UMAP by two variables at once?")It answers four kinds of questions particularly well:
-
“How do I recreate this figure?” - point it at a
saved PDF or a screenshot with
image_pathand it reads off the plot type and axis/legend labels, matches the file’s own path against how scSidekick names its outputs, and proposes the call that likely made it. -
“Which column in my object is Age?” - pass your
seurat_objectand it reads the realmeta.datacolumn names (and any colors already saved byPrepObject()) instead of guessing from a generic naming convention. -
“How do I change these colors?” - grounded answers
about
PrepObject(),custom_colors,GetColors(), etc., pulled from the actual installed documentation rather than a fixed FAQ that can drift out of date. - “Which covariates should I adjust for?” - general how-to questions about any exported function, answered from that function’s real man page.
Every answer is grounded in your installed copy’s own documentation - man pages plus vignette sources - so it never quotes an argument name or default that doesn’t actually exist in the version you have installed.
Setup
AskSidekick() uses the ellmer package to talk to a
large language model. ellmer is a
Suggests-only dependency - scSidekick loads and works
normally without it - so install it once:
install.packages("ellmer")By default AskSidekick() talks to Google Gemini, which
has a genuinely free tier (no credit card required). Get a key at https://aistudio.google.com/apikey, then add one line to
~/.Renviron (usethis::edit_r_environ() opens
it for you) and restart R:
GEMINI_API_KEY=your_key_here
That’s the whole setup. No account tier to choose, no billing to configure.
1. A plain question
No Seurat object needed for a general “how do I…” question:
AskSidekick("How do I split a UMAP by donor and color by cell type in the same figure?")Use PlotDimPlots() with `group.by` for color and `split.by` for the panel split:
scSidekick::PlotDimPlots(seurat_object,
group.by = "cell_type",
split.by = "donor")
Each call is independent - AskSidekick() doesn’t
remember earlier questions in the same session. That’s deliberate:
Gemini’s free tier has a fairly tight per-minute token budget, and
re-sending a growing conversation history would burn through it in one
or two calls. Ask one self-contained question at a time.
2. Passing your own object: “which column is Age?”
Supply seurat_object and the assistant sees your actual
meta.data column names (and any colors already registered
via PrepObject()) instead of guessing from common naming
conventions:
AskSidekick("Which metadata column represents the donor's age?",
seurat_object = SeuratObj)Looking at SeuratObj's meta.data, "Age.at.Death" (numeric) is the column that
represents age:
scSidekick::PlotFeature(SeuratObj, features = "Age.at.Death",
group.by = "Diagnosis")
Notice the reply uses SeuratObj - your own variable’s
name - in the code snippet, not a generic placeholder like
seurat_obj.
3. Recreating a figure from an image
Point image_path at a saved PDF or a screenshot of a
figure someone sent you, and AskSidekick() reads off the
plot type, axis/legend labels, and the file’s own path (scSidekick’s
output folders and filenames are deterministic, not just cosmetic -
e.g. only RunSCssGSEA() creates a folder starting
"SC ssGSEA ") to identify the function that most likely
made it:
AskSidekick(image_path = "Figures/bmcite_celltype.l1_donor_GroupHeatmap.pdf",
seurat_object = SeuratObj)The filename matches GroupHeatmap()'s own naming convention (<object>_<group
.by>_<split.by>_GroupHeatmap.pdf). Based on the visible row/column labels:
scSidekick::GroupHeatmap(SeuratObj,
group.by = "celltype.l1",
column_split_by = "donor")
You can add your own question alongside the image if you want something more specific than “recreate this”:
AskSidekick("What are the top marker genes labeled on this heatmap?",
image_path = "Figures/markers_heatmap.pdf")
same_dataset: is this figure actually from this
object?
When you pass both image_path and
seurat_object, same_dataset tells the
assistant how confident to be about matching the figure’s grouping
variables to your object’s real columns:
-
same_dataset = TRUE- “this figure was made from this exact object.” The assistant is told an exact column match must exist for every grouping/coloring variable shown, and to search carefully among similar-but-not-identical columns (Clustervs.seurat_clustersvs.Assignment) rather than settling for the first plausible name. -
same_dataset = FALSE(or the defaultNA) - the figure may be from a different dataset, an earlier package version, or a collaborator’s file. The assistant gives its best estimate and says explicitly that it’s an estimate, rather than implying a confirmed match.
AskSidekick(image_path = "Figures/old_project_umap.pdf",
seurat_object = SeuratObj,
same_dataset = TRUE)Either way, after the model replies, AskSidekick()
independently double-checks anything that looks like a gene list
(c("Cd3e", "Cd8a", ...)) against
rownames(SeuratObj) and anything that looks like a metadata
column (group.by = "...", stat.by = "...",
etc.) against colnames(SeuratObj@meta.data) -
deterministically, not by asking the model to grade its own work. If
either check comes back thin (e.g. a species mismatch between Title-case
mouse genes and ALL-CAPS human genes), a “Heads up”
note is appended to the reply automatically, telling you exactly which
names didn’t match and the closest real alternatives.
4. The first call after install (or after an update)
The assistant’s documentation context - man pages plus vignette
sources - is built from your installed copy of
scSidekick and cached under
tools::R_user_dir("scSidekick", "cache"), keyed by package
version. The very first AskSidekick() call after installing
or updating the package rebuilds that cache automatically:
scSidekick: setting up AskSidekick() for the first time with this package
version (v1.2.0) - hang on, this can take a minute or two. It only happens
once; every call after this is instant.
scSidekick: ready (120 documentation chunks cached).
Every call after that reuses the cache silently - no bundled asset to ship with the package, and no manual “rebuild the docs” step on release day.
If you’re actively developing scSidekick itself (editing a man page or vignette without bumping the version number), force a rebuild directly:
5. Model fallback
Google Gemini’s free tier gives each model its own separate daily
quota (RPD), and the allowance varies a lot by model - “Flash Lite”
models typically get a much larger daily allowance than flagship Flash
models on the same account (check https://aistudio.google.com/rate-limit for yours).
AskSidekick() tries the models in models (a
“Flash Lite” model first, by default) and automatically moves to the
next one on a quota or server error, rather than making you wait out a
429:
scSidekick bot: gemini-3.5-flash-lite unavailable right now (RESOURCE_EXHAUSTED),
trying the next model...
scSidekick bot: answered using gemini-3.1-flash-lite (earlier model(s) were
over today's quota).
That fallback is always printed, never silent. Pass your own
models vector to reorder or restrict which models are
tried:
AskSidekick("...", models = c("gemini-2.5-flash"))Using a different provider entirely
AskSidekick() is built on ellmer, which is
provider-agnostic - Gemini’s free tier is simply a convenient default
that doesn’t require billing setup. There’s no built-in argument to swap
providers today, but because the whole assistant is under 700 lines in
R/ask_sidekick.R, pointing it at Anthropic, OpenAI, or a
local Ollama model instead is a matter of swapping the single
ellmer::chat_google_gemini(...) call for
ellmer::chat_anthropic(...),
ellmer::chat_openai(...), or
ellmer::chat_ollama(...) - see the ellmer
documentation for each provider’s exact arguments.
Parameter reference
| Parameter | Type | Default | Description |
|---|---|---|---|
question |
character | NULL |
What you want to ask. Optional when image_path is
supplied. |
seurat_object |
Seurat object | NULL |
Gives the assistant your real meta.data columns and any
PrepObject()-saved colors; also enables the post-reply
gene/column match checks. |
image_path |
character | NULL |
Path to a PNG/JPEG/PDF figure to read and reverse-engineer. |
same_dataset |
logical | NA |
TRUE = demand an exact metadata-column match (the
figure is confirmed to be from seurat_object);
FALSE/NA = best estimate, flagged as
such. |
models |
character vector | Flash Lite + flagship Flash mix | Gemini models to try in order; automatic fallback on quota/server errors. |
rebuild_context |
logical | FALSE |
Force a documentation-cache rebuild before asking. Rarely needed -
see RebuildSidekickContext(). |
See also
-
RebuildSidekickContext()- force a documentation-cache rebuild - Vignette 01: Getting Started -
PrepObject()is whatAskSidekick()reads columns and colors from when you pass aseurat_object - Vignette 12: Reporting & Utilities - the rest of scSidekick’s
reproducibility layer (
.legendsidecars,ExtractMethods(), the session logger)
Session info
## R version 4.3.1 (2023-06-16)
## Platform: aarch64-apple-darwin20 (64-bit)
## Running under: macOS 15.6
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: America/Chicago
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## loaded via a namespace (and not attached):
## [1] digest_0.6.37 desc_1.4.3 R6_2.6.1 fastmap_1.2.0
## [5] xfun_0.52 cachem_1.1.0 knitr_1.45 htmltools_0.5.8.1
## [9] rmarkdown_2.29 lifecycle_1.0.4 cli_3.6.5 sass_0.4.10
## [13] pkgdown_2.1.3 textshaping_0.3.7 jquerylib_0.1.4 systemfonts_1.3.2
## [17] compiler_4.3.1 rstudioapi_0.16.0 tools_4.3.1 ragg_1.4.0
## [21] bslib_0.9.0 evaluate_0.23 yaml_2.3.10 jsonlite_2.0.0
## [25] rlang_1.1.6 fs_1.6.6 htmlwidgets_1.6.4