Reference

API documentation.

AI4BayesCode has two layers. You drive the package to turn a model description into a compiled sampler. The compiled sampler exposes a small stateful interface you call to run the chain and read it back. A third set of helpers sits between them, turning a sampler’s output into diagnostics and a DAG. The same names work from R and Python.


A worked example

The whole flow in R: set your key once, describe the model, compile, run, and read it back. Python is identical, with AI4BayesCode. in front of the package calls and m.method() on the sampler.

library(AI4BayesCode)

ai4bayescode_set_key("sk-ant-...")                     # your own LLM key here ("sk-ant-..." is a placeholder)
ai4bayescode_generate(                                 # writes ./generated/MyModel.cpp
  "y ~ N(X beta, sigma^2), beta ~ N(0, 10^2), sigma ~ HalfNormal(0, 1)",
  output_path = "./generated")
ai4bayescode_source("./generated/MyModel.cpp")         # compiles + loads MyModel
ai4bayescode_doc(MyModel)                              # what does the constructor want?

# keep_history = TRUE records every sweep, FALSE keeps only the latest draw
m <- new(MyModel, y, X, seed = 1L, keep_history = TRUE)
m$step(10000)                                          # run the sampler (treat early draws as burn-in)
hist <- m$get_history()                                # named list of matrices, one per parameter

ai4bayescode_diagnose(hist)                            # R-hat / ESS table + trace, ACF, density
ai4bayescode_plot_dag(m)                               # model DAG

# optional: warm-start from chosen values, then re-tune NUTS if the geometry shifts
m$set_current(list(sigma = 1.0, beta = b0))            # overwrite the current draw
m$readapt_NUTS(500)                                    # re-tune NUTS step size + mass matrix

# run several chains in parallel for cross-chain R-hat / ESS
runs <- ai4bayescode_run_chains(
  function(seed) new(MyModel, y, X, seed = seed, keep_history = TRUE),
  n_chains = 4, n_burn = 5000, n_keep = 5000)
ai4bayescode_rhat_summary(runs)                        # cross-chain R-hat and ESS
ai4bayescode_diagnose(runs$histories[[1]])             # full diagnostics on one chain

The package

These functions take you from a model description to a running sampler. Every R name carries the ai4bayescode_ prefix. The Python module mirrors them under AI4BayesCode..

ai4bayescode_set_key

Store your LLM provider key for the session. Providers are anthropic, openai, and google.

R       ai4bayescode_set_key(key, provider = "anthropic")
Python  AI4BayesCode.set_key(key, provider="anthropic")

ai4bayescode_key_status

Report which provider keys are set this session.

R       ai4bayescode_key_status()
Python  AI4BayesCode.key_status()

ai4bayescode_models

List the supported LLMs (name, provider, and effort levels) you can pass to ai4bayescode_generate.

R       ai4bayescode_models()
Python  AI4BayesCode.models()

ai4bayescode_generate

Parse and validate the model description, then write a sampler .cpp to output_path. A validate-then-repair loop (up to max_attempts) keeps going until the code compiles and passes the checks. Pass API_key here, or set it once with ai4bayescode_set_key.

R       ai4bayescode_generate(model_description, LLM = NULL, effort = NULL,
          backend = NULL, output_path = NULL, max_attempts = NULL, API_key = NULL)
Python  AI4BayesCode.generate(model_description, LLM=None, effort=None,
          backend=None, output_path=None, max_attempts=None, API_key=None)
model_description
Plain-language model spec (text, or a path to a .txt).
LLM, effort
Which model writes the sampler, and how hard it thinks. Left unset (NULL/None) they are asked interactively; see ai4bayescode_models().
backend
Target runtime: "R", "Python", or "both" — one dual-module .cpp usable from both (the default when unset). Asked interactively if unset.
output_path
Where the generated .cpp is written (default ./generated/).
max_attempts
Validate-then-repair budget (default 5). Asked interactively if unset.
API_key
Provider key for this call. Optional if you used ai4bayescode_set_key.

ai4bayescode_prompt

Build (and, interactively, confirm) the code-generation prompt without calling the LLM. Useful to inspect or hand-edit what ai4bayescode_generate would send.

R       ai4bayescode_prompt(model_description)
Python  AI4BayesCode.prompt(model_description)

ai4bayescode_source

Compile the generated .cpp against the bundled library and load it, with no paths to configure. After it returns, the sampler class is available: new(MyModel, ...) in R, mod.MyModel(...) in Python.

R       ai4bayescode_source("./generated/MyModel.cpp")
Python  AI4BayesCode.source("./generated/MyModel.cpp")

ai4bayescode_doc

Print a usage card for a compiled sampler: the constructor arguments with their types and defaults, the model description, and the available methods. It answers “what does the constructor want?”.

R       ai4bayescode_doc(MyModel)
Python  AI4BayesCode.doc(MyModel)

ai4bayescode_example

Compile and load a bundled example by name, a one-line way to see a working sampler.

R       ai4bayescode_example("GaussianLocationScale")
Python  AI4BayesCode.example("GaussianLocationScale")

The remaining helpers list and report: ai4bayescode_list_examples(), ai4bayescode_list_skills(), ai4bayescode_version(), and ai4bayescode_stream_check() to confirm streaming works with your key. Each is mirrored under AI4BayesCode. in Python.

Contributed blocks

The core blocks ship with the package. Community blocks live in the hub registry and install on demand, the same way R installs a package from CRAN. Once a block is installed, its header is on the compile path and its skill is available to the generator, so you can use it like a built-in one. The Python module mirrors each name under AI4BayesCode..

ai4bayescode_available_blocks

List the contributed blocks you can install from the hub registry, like available.packages().

R       ai4bayescode_available_blocks()
Python  AI4BayesCode.available_blocks()

ai4bayescode_install_block

Install a contributed block into your library, like install.packages(). It downloads a reviewed bundle from the hub registry into a fixed per-user library at ~/.AI4BayesCode/blocks_download/, shared across R, Python, and C++, and adds the block, with any vendored dependencies, to the compile path, so the next ai4bayescode_source or ai4bayescode_generate can use it. The registry is curated and pre-validated, so installing is a download and version check, not a compile.

R       ai4bayescode_install_block("nngp_gaussian_gibbs_block")
Python  AI4BayesCode.install_block("nngp_gaussian_gibbs_block")
name
The block name, as listed by ai4bayescode_available_blocks().
force
Reinstall even if it is already present. Off by default.
quiet
Skip the progress messages and the install summary. Off by default.

ai4bayescode_installed_blocks

List the contributed blocks already installed in your library, like installed.packages().

R       ai4bayescode_installed_blocks()
Python  AI4BayesCode.installed_blocks()

ai4bayescode_remove_block

Remove an installed contributed block, like remove.packages(). The library folder itself is ai4bayescode_blocks_path().

R       ai4bayescode_remove_block("nngp_gaussian_gibbs_block")
Python  AI4BayesCode.remove_block("nngp_gaussian_gibbs_block")

The generated sampler

Once ai4bayescode_source (or ai4bayescode_example) has loaded a sampler class, build it with your data and drive it through a small stateful interface. Every block, every composite, and the top-level sampler expose the same methods. In R they are m$method(). In Python, m.method(). Each signature below is the general form.

constructor

Build the sampler with your data. The arguments depend on the model, so run ai4bayescode_doc(MyModel) to see them. seed fixes the RNG. keep_history = TRUE records every draw, otherwise only the latest is kept.

R       m <- new(MyModel, y, X, seed = 1L, keep_history = TRUE)
Python  m = mod.MyModel(y, X, seed=1, keep_history=True)

step

Run n sweeps in one call, advancing the chain. n defaults to 1, so m$step() advances a single sweep. Every sweep is recorded when keep_history = TRUE, so there is no separate unrecorded burn-in. Treat the early draws as burn-in when you analyze.

R       m$step(n = 1)
Python  m.step(n=1)

get_current

The current draw as a named list (R) or dict (Python), keyed by parameter. Does not advance the chain.

R       m$get_current()
Python  m.get_current()

set_current

Overwrite current values from a named list, to warm-start from a previous run or a chosen starting point. Keys are parameter names (and, for some blocks, the data they condition on).

R       m$set_current(list(sigma = 1.0, beta = b0))
Python  m.set_current({"sigma": 1.0, "beta": b0})

get_history

All stored draws as a named list of matrices, each (n_draws × dim). Feed it straight to ai4bayescode_diagnose().

R       m$get_history()
Python  m.get_history()

predict_at

Posterior-predictive draws at new inputs, using the recorded chain. Pass the new data as a named list (column-major flattened where the constructor took a matrix). If you do not supply all of the inputs, it still returns a partial prediction of the intermediate quantities it can reach. Returns a named list and does not mutate state.

R       m$predict_at(list(X = X_new))
Python  m.predict_at({"X": X_new})

get_dag

The model’s dependency graph as data (a named list of edges). ai4bayescode_plot_dag() reads this to draw the figure.

R       m$get_dag()
Python  m.get_dag()

readapt_NUTS

Re-tune the NUTS step size and mass matrix for n iterations without advancing the chain. With reset = FALSE (the default) it continues adapting from the current state. With reset = TRUE it reinitializes dual-averaging and adapts from scratch. Continuing is what you want for online learning, where new data arrives and you keep refining. Resetting is for when the target geometry has changed and the old tuning no longer fits. The optional max_tree_depth caps the tree-doubling depth per iteration; -1 (the default) uses the block's configured depth. NUTS-family blocks only, others are skipped.

R       m$readapt_NUTS(n, reset = FALSE, max_tree_depth = -1)
Python  m.readapt_NUTS(n, reset=False, max_tree_depth=-1)

Diagnostics & DAG

These helpers sit between the two layers: they take what a sampler produces, its history and its structure, and turn it into convergence diagnostics and figures. They ship with the package, so a generated runner calls the same functions by name.

ai4bayescode_diagnose

From get_history(): a summary table (R-hat, bulk / tail ESS) plus a trace, autocorrelation, and density plot. The one call to sanity-check a run.

R       ai4bayescode_diagnose(hist)
Python  AI4BayesCode.diagnose(hist)

ai4bayescode_plot_dag

Draw the model as a plate DAG straight from the sampler, reading its get_dag() under the hood. Leave out_path empty to show it, or pass a path to write a PNG.

R       ai4bayescode_plot_dag(m, out_path = NULL)
Python  AI4BayesCode.plot_dag(m)

ai4bayescode_run_chains

Run several independent chains in parallel and collect them, for cross-chain R-hat and ESS. The first argument is a function that builds a fresh sampler from a seed. Convergence companion: ai4bayescode_rhat_summary() in R, AI4BayesCode.rhat_summary() in Python (or the lower-level rhat(), ess_bulk(), and ess_tail()).

R       ai4bayescode_run_chains(function(seed) new(MyModel, y, X, seed = seed, keep_history = TRUE),
                                n_chains = 4, n_burn = 5000, n_keep = 5000)
Python  AI4BayesCode.run_chains(lambda s: mod.MyModel(y, X, seed=s, keep_history=True),
                                seeds=range(4), n_burn=5000, n_keep=5000)