All examples
Language models

A native language model research workflow

Fit byte BPE on training documents, build a decoder from scratch and assert training, causality, checkpoint continuation and seeded generation.

generative_research_workflow.aner
// Native from-scratch workflow and executable correctness checks.
// Small synthetic strings expose mechanisms; they are not a language-quality benchmark.
// Run from a fresh output directory using a runtime with aner.token and aner.gen.
import aner.token
import aner.gen
import aner.nn
import aner.dev
import aner.math

fn verify(label: String, condition: Bool) -> Unit {
    print("check_" + label)
    if !condition {
        let failure: Result<Bool, String> = Result.err(label)
        print(failure.unwrap())
    }
    print(condition)
}
fn trace(model: LanguageModel, training: TokenCorpus, validation: TokenCorpus) -> Unit {
    print("trace_step")
    print(model.steps())
    print("trace_training_loss")
    print(model.loss(training))
    print("trace_validation_loss")
    print(model.loss(validation))
}

nn.configure("cpu", "Float64", "preserve")

// Partition real research documents by subject, experiment or time before this step.
// Learn BPE only from training documents, retaining exact UTF-8 byte fallback.
let fitting_documents = List(
    "temperature α pressure β temperature α pressure β",
    "pressure β temperature α pressure β temperature α")
let fitting = token.corpus(token.byte_tokenizer(), fitting_documents, role: "training")
let bpe = token.bpe(fitting, vocabulary: 280, min_frequency: 2)
let symbols = "new scientific symbols α β 🔬"
verify("bpe_roundtrip", bpe.decode(bpe.encode(symbols, bos: true, eos: true), skip_special: true) == symbols)
bpe.save("research-bpe.anertoken")
print("bpe_vocabulary")
print(bpe.vocabulary())

// Fixed byte IDs make every point on the learning trace directly comparable.
let codec = token.byte_tokenizer()
let training = token.corpus(codec, List(
    "abababababababab", "babababababababa"), role: "training")
let validation = token.corpus(codec, List(
    "abababababababa", "bababababababab"), role: "validation")
let testing = token.corpus(codec, List(
    "ababababab", "babababab"), role: "test")
let initial = gen.decoder(codec, context: 24, width: 8,
    heads: 2, layers: 1, seed: 63, dropout: 0.0)
let initial_validation = initial.loss(validation)
print("uniform_loss")
print(math.log(259.0))
trace(initial, training, validation)
let step30 = initial.train(training, steps: 30, batch: 2, rate: 0.01, seed: 99,
    clip_norm: 1.0, warmup_steps: 0, weight_decay: 0.0)
trace(step30, training, validation)
let step60 = step30.resume(training, steps: 30)
trace(step60, training, validation)
step60.save("research-step60.anergen")
let loaded = gen.load("research-step60.anergen")
verify("checkpoint_roundtrip", loaded.fingerprint() == step60.fingerprint())
let step90 = loaded.resume(training, steps: 30)
trace(step90, training, validation)
let model = step90.resume(training, steps: 30)
trace(model, training, validation)
let direct = initial.train(training, steps: 120, batch: 2, rate: 0.01, seed: 99,
    clip_norm: 1.0, warmup_steps: 0, weight_decay: 0.0)
verify("exact_split_resume", model.fingerprint() == direct.fingerprint())
verify("training_improves", model.loss(training) < initial.loss(training))
verify("validation_improves", model.loss(validation) < initial_validation && model.loss(validation) < math.log(259.0))
print("test_loss")
print(model.loss(testing))

// Future-token changes cannot change earlier logits, across the full vocabulary.
let left = model.logits(List(256, 97, 98, 97), batch: 1, length: 4, training: false)
let right = model.logits(List(256, 97, 122, 122), batch: 1, length: 4, training: false)
var prefix_equal = true
var row = 0
while row < 2 {
    var column = 0
    while column < codec.vocabulary() {
        if nn.value(left, row, column) != nn.value(right, row, column) {
            prefix_equal = false
        }
        column = column + 1
    }
    row = row + 1
}
verify("causal_prefix", prefix_equal)
let prompt = codec.encode("ab", bos: true, eos: false)
let generated = model.generate(prompt, max_new_tokens: 8,
    temperature: 0.8, top_k: 20, top_p: 0.95, seed: 7)
let repeated = direct.generate(prompt, max_new_tokens: 8,
    temperature: 0.8, top_k: 20, top_p: 0.95, seed: 7)
var generation_equal = generated.len() == repeated.len()
var token_index = 0
while token_index < generated.len() && generation_equal {
    generation_equal = cast<Int64>(generated.get(token_index)) == cast<Int64>(repeated.get(token_index))
    token_index = token_index + 1
}
verify("seeded_generation", generation_equal)
print("continuation_hex")
print(codec.decode_bytes(generated, skip_special: true).hex())
model.save("research-trained.anergen")
codec.save("research-byte.anertoken")
dev.capture("From-scratch native decoder", model)

// A changed training corpus starts an explicit fine-tuning run.
let adaptation = token.corpus(codec, List(
    "abababab science", "babababa research"), role: "training")
let full = model.fine_tune(adaptation, steps: 4, batch: 2, rate: 0.001, seed: 101)
verify("full_fine_tune_steps", full.steps() == 4)
let selected = model.freeze(List("embedding.token", "embedding.position"))
verify("freezing_reduces_selection", selected.trainable_parameters().len() < model.trainable_parameters().len())
let adapted = model.lora(List("block.0.qkv", "block.0.attention.output"),
    rank: 2, alpha: 4.0, seed: 23)
let lora = adapted.fine_tune(adaptation, steps: 4, batch: 2, rate: 0.001, seed: 102)
verify("lora_training_steps", lora.steps() == 4)
lora.save("research-lora.anergen")
print("workflow_checks_passed")

Make it your experiment.

With a compatible development runtime installed, save this program as examples/generative_research_workflow.aner inside a folder for your experiment. Open a terminal in that folder, then check and run the program.

Terminal
aner check examples/generative_research_workflow.aner
aner run examples/generative_research_workflow.aner

The aner command must be on your PATH. Follow the installation guide if your terminal cannot find it.

Use a compatible current native Aner development runtime with aner.token, aner.gen and sequence primitives. CPU supports Float64 and Float32; native Metal/MPS sequence kernels require Float32 and a compatible build. CUDA sequence kernels are not implemented. Run checkpoint examples from a fresh working directory because existing artifacts are never replaced. These local synthetic examples require no model provider, credentials or network connection. The runtime and VS Code extension remain development software without public downloads.

Bundled datasets retain their own source attribution and license notices. Example outcomes are not comparative benchmarks or evidence of clinical validity.

Dataset sources & attribution
Install Aner