Text Generation
MLX
Safetensors
English
code
cobol
gnucobol
sml
tiny-model
from-scratch
research
negative-result
Instructions to use SMLBuilder/cobol-jeeves-sml with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use SMLBuilder/cobol-jeeves-sml with MLX:
# Make sure mlx-lm is installed # pip install --upgrade mlx-lm # if on a CUDA device, also pip install mlx[cuda] # Generate text with mlx-lm from mlx_lm import load, generate model, tokenizer = load("SMLBuilder/cobol-jeeves-sml") prompt = "Once upon a time in" text = generate(model, tokenizer, prompt=prompt, verbose=True) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- MLX LM
How to use SMLBuilder/cobol-jeeves-sml with MLX LM:
Generate or start a chat session
# Install MLX LM uv tool install mlx-lm # Generate some text mlx_lm.generate --model "SMLBuilder/cobol-jeeves-sml" --prompt "Once upon a time"
- Atomic Chat
| """COBOL-aware word/symbol tokenizer for the COBOL SML. | |
| Same spirit as TinkyBrain's word-level tokenizer (the vocab IS the boundary), | |
| but COBOL-shaped: | |
| * case PRESERVED (COBOL identifiers matter; keywords are case-insensitive but | |
| the corpus is uppercase, so preserving keeps the vocab tight) | |
| * hyphenated names stay whole (PROGRAM-ID, L-TAB, END-PERFORM) | |
| * string literals "..." / '...' are single tokens | |
| * numbers are single tokens | |
| * every structural symbol ( ) . , : ; etc. is its own token | |
| * <nl> encodes line structure so free-format COBOL round-trips | |
| Free-format is the target dialect: strip fixed-format indentation, compile with | |
| `cobc -free -c`. Proven equivalent to the fixed-format source (see de-risk test). | |
| The detokenizer re-applies COBOL spacing (no space around parens / before . , ) | |
| so `PIC S9(5)`, `L-TAB(WS-I)`, `RESULT.` reconstruct exactly. | |
| """ | |
| import json | |
| import re | |
| from collections import Counter | |
| # Special tokens (mirror TinkyBrain ids so muscle memory carries over) | |
| PAD, BOS, EOS, SEP, UNK, NL = 0, 1, 2, 3, 4, 5 | |
| SPECIAL = {"<pad>": PAD, "<bos>": BOS, "<eos>": EOS, "<sep>": SEP, "<unk>": UNK, "<nl>": NL} | |
| # One token per: string literal | hyphenated word/keyword | number | single symbol | |
| _TOKEN_RE = re.compile(r""" | |
| "[^"]*" # double-quoted literal | |
| | '[^']*' # single-quoted literal | |
| | [A-Za-z][A-Za-z0-9-]* # identifier / keyword (hyphens kept) | |
| | [0-9]+ # integer | |
| | [^\sA-Za-z0-9] # any single structural symbol | |
| """, re.VERBOSE) | |
| # Detokenizer spacing rules | |
| _NO_SPACE_BEFORE = {".", ",", ")", "(", ";", ":"} | |
| _NO_SPACE_AFTER = {"("} | |
| def tokenize_cobol(src: str): | |
| """COBOL source -> flat token list with <nl> between lines (indentation dropped).""" | |
| out = [] | |
| for i, line in enumerate(src.splitlines()): | |
| if i > 0: | |
| out.append("<nl>") | |
| out.extend(_TOKEN_RE.findall(line.strip())) | |
| return out | |
| def detokenize_cobol(tokens) -> str: | |
| """Token list -> free-format COBOL source (re-applies COBOL spacing).""" | |
| parts, prev = [], None | |
| for t in tokens: | |
| if t == "<nl>": | |
| parts.append("\n") | |
| prev = None | |
| continue | |
| if prev is None or prev == "\n": | |
| parts.append(t) | |
| elif prev in _NO_SPACE_AFTER or t in _NO_SPACE_BEFORE: | |
| parts.append(t) | |
| else: | |
| parts.append(" " + t) | |
| prev = t | |
| return "".join(parts) | |
| class CobolTokenizer: | |
| def __init__(self, vocab_size=4096): | |
| self.vocab_size = vocab_size | |
| self.word2idx = dict(SPECIAL) | |
| self.idx2word = {v: k for k, v in SPECIAL.items()} | |
| self.fitted = False | |
| def fit(self, texts): | |
| counts = Counter() | |
| for t in texts: | |
| counts.update(tok for tok in _TOKEN_RE.findall(t) if tok) # NL handled separately | |
| for word, _ in counts.most_common(self.vocab_size - len(SPECIAL)): | |
| if len(self.word2idx) >= self.vocab_size: | |
| break | |
| if word not in self.word2idx: | |
| self.word2idx[word] = len(self.word2idx) | |
| self.idx2word[len(self.idx2word)] = word | |
| self.fitted = True | |
| print(f"CobolTokenizer: {len(self.word2idx)} tokens (from {len(counts)} unique)") | |
| def encode(self, text: str): | |
| return [self.word2idx.get("<nl>", NL) if t == "<nl>" else self.word2idx.get(t, UNK) | |
| for t in tokenize_cobol(text)] | |
| def encode_tokens(self, tokens): | |
| return [self.word2idx.get(t, UNK) for t in tokens] | |
| def decode(self, ids): | |
| toks = [self.idx2word.get(i, "<unk>") for i in ids if i not in (PAD, BOS, EOS, SEP)] | |
| return detokenize_cobol(toks) | |
| def save(self, path): | |
| json.dump(self.word2idx, open(path, "w")) | |
| def load(cls, path): | |
| w2i = json.load(open(path)) | |
| t = cls(vocab_size=len(w2i)) | |
| t.word2idx = {k: int(v) for k, v in w2i.items()} | |
| t.idx2word = {int(v): k for k, v in w2i.items()} | |
| t.fitted = True | |
| return t | |