https://github.com/alii/babble
A Markov chain text generator for Gleam
https://github.com/alii/babble
chain markov
Last synced: 23 days ago
JSON representation
A Markov chain text generator for Gleam
- Host: GitHub
- URL: https://github.com/alii/babble
- Owner: alii
- License: mit
- Created: 2026-05-27T11:18:49.000Z (about 2 months ago)
- Default Branch: master
- Last Pushed: 2026-05-27T11:54:46.000Z (about 2 months ago)
- Last Synced: 2026-05-27T12:15:37.344Z (about 2 months ago)
- Topics: chain, markov
- Language: Gleam
- Homepage: https://hex.pm/packages/babble
- Size: 0 Bytes
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# babble
[](https://hex.pm/packages/babble)
[](https://hexdocs.pm/babble/)
A Markov chain text generator for Gleam.
```sh
gleam add babble
```
## Usage
```gleam
import gleam/io
import babble
pub fn main() {
let model =
babble.new(order: 2, tokenization: babble.Words)
|> babble.train("the cat sat on the mat.")
|> babble.train("the dog sat on the log.")
let assert Ok(sentence) = babble.generate(model, babble.weighted, max_tokens: 200)
io.println(sentence) // => the dog sat on the mat.
}
```
`train` is incremental, so you can keep one model and feed it text as it arrives.
`generate` returns `Error(EmptyModel)` until the model has learned something.
## Configuration
`new` takes two settings, fixed at construction:
- `order`: how many previous tokens to condition on. Higher is more coherent but
repeats the source more; lower is more random. 2 is a reasonable default.
- `tokenization`: `Words` or `Characters`. With `Characters`, `order` counts characters.
The length cap is a `generate` argument (`max_tokens:`), not a model setting.
## Sampling
`generate` takes a sampler: the function that chooses the next token from the
weighted candidates at each step. Two are built in:
- `babble.weighted`: picks at random, weighted by training frequency. Varies each call.
- `babble.most_likely`: always picks the most frequent successor. Deterministic.
A sampler is `fn(List(#(Step, Int))) -> Step`, where `Step` is `Continue(word)` or
`Stop` and the `Int` is the training count. Write your own for temperature, top-k,
blocklists, and so on:
```gleam
import gleam/int
import gleam/list
fn uniform(candidates: List(#(babble.Step, Int))) -> babble.Step {
case list.drop(candidates, int.random(list.length(candidates))) {
[#(step, _), ..] -> step
[] -> babble.Stop
}
}
```
Samplers are stateless, so use `most_likely` for reproducible output rather than
seeding randomness yourself.
## Generation
```gleam
babble.generate(model, babble.weighted, max_tokens: 200) // one sentence
babble.generate_paragraph(model, 3, babble.weighted, max_tokens: 200) // three sentences
babble.generate_starting_with(model, "pizza", babble.weighted, max_tokens: 200) // from a prefix
```
A sentence ends at `.`, `!`, or `?` (learned during training) or when it hits
`max_tokens`.
## Development
```sh
gleam test
gleam format
```