llmask() sends a
question to a language model and returns the answer. You bring the
model: a key for a provider you already use, a model on your own
machine, or a server of your own. Nothing is sent anywhere you did not
set up, and the package runs no model service of its own. This vignette
explains the routes, how the model is given the packages’ help, and what
the package will and will not do on the network.
MORIE_LLM_BASE_URL (with MORIE_LLM_API_KEY and
MORIE_LLM_MODEL), any OpenAI-compatible server (LM Studio,
vLLM, llama.cpp’s llama-server, a company gateway). Taken
when configured, not probed.llmprvd() lists them: OpenAI, Anthropic, Google Gemini,
OpenRouter, Groq, Together AI, Fireworks AI, DeepSeek, Mistral, xAI,
Cerebras, Perplexity, Hugging Face, OpenCode Zen, Cohere and NVIDIA.
Each reads its usual variable (OPENAI_API_KEY,
ANTHROPIC_API_KEY, GEMINI_API_KEY, …) or a key
saved with llmcfg(anthropic.key = ...); the model is
MORIE_<PROVIDER>_MODEL or
<provider>.model. Anthropic’s Messages API and
Gemini’s generateContent are spoken natively; the others
are OpenAI-compatible.OLLAMA_HOST (default
localhost:11434), on this machine or another, once its
server is running (ollama serve, the Ollama app, or the
system service its Linux installer sets up) and has a model
(ollama pull NAME), or Ollama’s own cloud API
(ollama.url = https://ollama.com with your
ollama.key); OLLAMA_HOST=off disables the
probe. Its first listed model is the default.route = "anthropic" (or
rmbl config set route anthropic) takes one route only.
llmprvd()[, c("id", "label", "key_env")]
#> id label key_env
#> 1 openai OpenAI OPENAI_API_KEY
#> 2 anthropic Anthropic ANTHROPIC_API_KEY
#> 3 gemini Google Gemini GEMINI_API_KEY
#> 4 openrouter OpenRouter OPENROUTER_API_KEY
#> 5 groq Groq GROQ_API_KEY
#> 6 together Together AI TOGETHER_API_KEY
#> 7 fireworks Fireworks AI FIREWORKS_API_KEY
#> 8 deepseek DeepSeek DEEPSEEK_API_KEY
#> 9 mistral Mistral MISTRAL_API_KEY
#> 10 xai xAI XAI_API_KEY
#> 11 cerebras Cerebras CEREBRAS_API_KEY
#> 12 perplexity Perplexity PERPLEXITY_API_KEY
#> 13 huggingface Hugging Face HF_TOKEN
#> 14 opencode OpenCode Zen OPENCODE_API_KEY
#> 15 cohere Cohere COHERE_API_KEY
#> 16 nvidia NVIDIA NIM NVIDIA_API_KEYllmstat() reports what is available from this machine.
With the local route off the call reaches no network:
old <- Sys.getenv("OLLAMA_HOST", unset = NA)
Sys.setenv(OLLAMA_HOST = "off")
llmstat()
#> route status
#> 1 own endpoint not set
#> 2 other providers no key
#> 3 local Ollama disabled
#> detail
#> 1 MORIE_LLM_BASE_URL (+ MORIE_LLM_API_KEY, MORIE_LLM_MODEL): any OpenAI-compatible server
#> 2 openai (OPENAI_API_KEY), anthropic (ANTHROPIC_API_KEY), gemini (GEMINI_API_KEY), openrouter (OPENROUTER_API_KEY), groq (GROQ_API_KEY), together (TOGETHER_API_KEY), fireworks (FIREWORKS_API_KEY), deepseek (DEEPSEEK_API_KEY), mistral (MISTRAL_API_KEY), xai (XAI_API_KEY), cerebras (CEREBRAS_API_KEY), perplexity (PERPLEXITY_API_KEY), huggingface (HF_TOKEN), opencode (OPENCODE_API_KEY), cohere (COHERE_API_KEY), nvidia (NVIDIA_API_KEY)
#> 3 OLLAMA_HOST=off
if (is.na(old)) Sys.unsetenv("OLLAMA_HOST") else Sys.setenv(OLLAMA_HOST = old)llmask("How do I estimate a weighted proportion with bootstrap replicate weights?")
llmask(paste(c("Summarise this table:", capture.output(print(head(mtcars)))),
collapse = "\n"),
syspro = "Answer in two sentences.", docs = FALSE)With docs = TRUE (the default) the model is told every
function of the MORIE packages installed here (rmoriebricklayer, and
rmoriedata and rmorie when present), read from their installed help, and
gets five tools it can call: search_docs (a search over
every help page), get_help, get_examples,
list_datasets and get_vignette. It reads the
pages it needs before it writes code. A model that does not take tools
gets the pages nearest the question in its prompt instead. The tools
only read help; nothing the model says is run.
How much of the help goes into the prompt follows what the model can take in:
minimax-m3:cloud reports a 512,000-token context) and a
remote server of your own get the whole index of functions, full help
pages and up to six rounds of lookups;OLLAMA_CONTEXT_LENGTH), so it gets the functions nearest
the question, shorter pages and fewer rounds; a server of your own on
this machine gets a middle size;MORIE_LLM_CONTEXT (tokens) says what your model takes,
whatever the route.Every size can still reach every function: search_docs
and get_help look up any page.
agentbndl() asks over the same routes, with the bundle
task added, and with no route it returns the setup hint
(rmbl bundle exits 1).
The data service’s addresses and its sign-in service are
not hard-coded in the package. They come from a
document at
https://rmorie.com/.well-known/morie-services.json, signed
with ML-DSA-44 under a key pinned in the package, so the endpoints can
change without a release while no one but the project can change them. A
copy ships with the package as the fallback and the floor:
What the verifier enforces, each with a test:
.json suffix finds its
.sig; MORIE_SERVICES_URL names a mirror.The 0.5.8 to 0.5.10 reviews closed every bypass of the transport and these rules now hold for every byte the package sends or receives:
10/8, 172.16/12,
192.168/16, fc00::/7, for an LM Studio or vLLM
box on your own network) over plain http, or a public https address.
Link-local addresses and host names over plain http are refused, and a
redirect from a remote origin into the loopback interface is
refused.Authorization, X-Api-Key and the rest stay
with the first origin.Bearer token and any
sk- key removed before it becomes an R condition.timeout (120 s), a conversation with
help-page lookups three times that, and Ctrl-C ends the wait at once
without sending the prompt again. An in-memory reply past 16 MiB is
dropped; the services document and JSON fetches cap at 1 MiB and 16
MiB.verification_uri is opened in a
browser only when it is a public https address.Signing in is for the curated tables at data.rmorie.com
only; it is never a language model.
dlogin(token = "<key issued at https://www.rmorie.com/access/>")
dlogin() # or: GitHub device flow / emailed code
dlogout() # forget the keyThe key is stored with mode 0600 in the user’s configuration
directory and never written anywhere else. rmbl doctor says
whether one is stored.
The same routes serve the CLI installed by
instcli():
rmoriebricklayer config setup # pick a provider, paste its key (saved privately), pick a model
rmoriebricklayer doctor # the routes, and the one ask takes
rmoriebricklayer models --route anthropic
rmoriebricklayer ask "what does cpsbndl() cover?"
rmoriebricklayer ask --route ollama --model gemma3:4b "how do I verify a capsule?"
rmoriebricklayer login --token # the data key: paste it when asked; it never sits in the shell historyWith a route set up, a question can name the package’s Indigenous data; the model answers with the functions to call (this needs a model, so it is not run here):
The routes above are drawn from the provider table
llmprvd(). The bars count the providers by the shape of
request each one takes; every OpenAI-compatible provider shares one
request builder.
pv <- llmprvd()
barplot(table(pv$api), col = blpal()[1], ylab = "providers", main = "Providers by request shape")