AI4BayesCode

From natural language to validated, modular, stateful Bayesian samplers.

AI4BayesCode is an extensible, LLM-driven system that turns a natural-language Bayesian model description into a runnable, validated MCMC sampler. A modular design decomposes the model into sampling blocks, each mapped to a built-in component, so complex sampling algorithms aren’t reimplemented from scratch. Validation covers the model specification (before generation) and the sampler code (after). A recursively stateful paradigm composes blocks (even from different contributors) into larger MCMC procedures, usable from R, Python, or C++.


News


What it is

An LLM-driven system that builds complete MCMC samplers from a model specification.

You describe a Bayesian model in plain language. Instead of writing the MCMC code from scratch, AI4BayesCode assembles the sampler from tested, built-in components and validates it before you run it.

From a plain-language model to a runnable sampler.

Describe your model in words, with its likelihood and priors. AI4BayesCode parses the description, picks the right built-in samplers, and hands you compiled code you can run from R, Python, or C++. You write the model, it writes the sampler.

Stateful coding paradigm that composes blocks into larger samplers.

A recursively stateful coding paradigm is central to AI4BayesCode. Each block keeps its own state as the quantities around it change, so it keeps sampling inside a larger MCMC instead of starting over. This lets modular sampling components, even ones developed by different contributors, be composed coherently within larger MCMC procedures, and the same paradigm makes model development and exploration fast.

An extensible system, open to new models and contributors.

AI4BayesCode is built to be extended. New kinds of models can be supported quickly by adding a block, so the system keeps up with new methods. The block library is also open to contribution, so users can add their own blocks and grow the set of models the system can build.

Systematic validation, before and after.

Before writing any code, AI4BayesCode confirms it parsed the model you meant. After, it checks the sampler compiles, screens the code for silent bugs, and runs it on simulated data to confirm it recovers the right posterior, reporting R-hat, ESS, and posterior-predictive checks.


Examples

From description to runnable chain.

You write the model in natural language, with priors and likelihood. AI4BayesCode builds the sampler, validates it, compiles it to C++, and ships R and Python bindings. Below are two short prompts and the samplers they produce.

Natural-language prompt

Bayesian linear regression, y ~ N(Xbeta, sigma^2). Normal prior on beta, half-Normal on sigma.

Blocks selected

joint_nuts_block(beta, sigma)

Generated interface

library(AI4BayesCode)
ai4bayescode_generate(
  "linear regression, y ~ N(Xbeta, sigma^2), normal prior on beta, half-normal on sigma",
  classname = "BayesLinReg", output_path = "./generated")
ai4bayescode_source("./generated/BayesLinReg.cpp")

# run several chains and check convergence (the usual workflow)
run <- ai4bayescode_run_chains(
  function(s) new(BayesLinReg, y, X, seed = s, keep_history = TRUE),
  n_chains = 4, n_burn = 5000, n_keep = 5000)

ai4bayescode_rhat_summary(run)         # cross-chain R-hat and ESS
ai4bayescode_diagnose(run$histories[[1]])    # trace, ACF, density

# optional: stateful usage, drive a single chain yourself
m <- new(BayesLinReg, y, X, seed = 1L, keep_history = TRUE)
m$step(10000)
hist <- m$get_history()           # named list of matrices
cur  <- m$get_current()           # current draw

Natural-language prompt

Spike-and-slab regression, y ~ N(Xbeta, sigma^2). beta_j ~ Laplace(b*sigma) if gamma_j = 1, else 0. gamma_j ~ Bernoulli(pi). pi ~ Beta(1, 1), half-Normal priors on sigma and b.

Blocks selected

rjmcmc_block(beta, gamma)
joint_nuts_block(sigma, b)
beta_gibbs_block(pi)

Generated interface

library(AI4BayesCode)
ai4bayescode_generate(
  "spike and slab, y ~ N(Xbeta, sigma^2), beta_j ~ Laplace(b*sigma) if gamma_j=1 else 0, gamma_j ~ Bernoulli(pi), pi ~ Beta(1,1), sigma ~ HalfNormal(0,1), b ~ HalfNormal(0,1)",
  classname = "SpikeLaplace", output_path = "./generated")
ai4bayescode_source("./generated/SpikeLaplace.cpp")

# run several chains and check convergence (the usual workflow)
run <- ai4bayescode_run_chains(
  function(s) new(SpikeLaplace, y, X, seed = s, keep_history = TRUE),
  n_chains = 4, n_burn = 5000, n_keep = 5000)

ai4bayescode_rhat_summary(run)
inc <- colMeans(run$histories[[1]]$gamma)   # posterior inclusion probabilities

# optional: stateful usage, drive one chain with full control
m <- new(SpikeLaplace, y, X, seed = 1L, keep_history = TRUE)
m$set_current(list(sigma = 1.0))   # warm-start a parameter
m$step(2000); m$readapt_NUTS(500)    # warm up, then re-tune NUTS
m$step(10000)
ai4bayescode_diagnose(m$get_history())

Paper

Read the paper.

AI4BayesCode received a Paper Award at STAI-X 2026, and the full paper is available on arXiv.