加载中…
加载中…
Inferno-Exp-1.5 is a 76.2M-parameter decoder-only base language model trained from scratch by AlgoDriveAI. It continues training Inferno-Exp-1.0 on an expanded corpus. It is a math-first model: its training emphasizes arithmetic and math word problems, and it is geared toward the AxiomicLabs small-language-model benchmarks used in SLM challenges, ArithMark 3.0 and ArithMark 2.0 (results below). Future versions will build on this math foundation with improvements aimed at broader language understanding and logical reasoning.
| Parameters | 76,163,200 |
| Layers × width | 14 × 640 |
| Attention | grouped-query, 8 query / 2 KV heads, head dim 80, full-head RoPE |
| Feed-forward | plain SwiGLU, inner width 1536 |
| Context | 2048 tokens |
| Tokenizer | Mistral-7B-v0.1 (padded to 32,064); `< |
| Embeddings | input and output tied |
| Training | Inferno-Exp-1.0 (AlgoDriveAI/SLM_v3, 2 epochs), then 75,000 more updates (~1.2B tokens) on an expanded SLM_v3 (3.89B tokens); AdamW, WSD-style schedule |
This is a base model (no instruction tuning). The model code ships in the repo, so load it with
trust_remote_code=True.
Same architecture and size as 1.0; more and broader training data.
| Benchmark | Inferno-Exp-1.0 | Inferno-Exp-1.5 | Change |
|---|---|---|---|
| ArithMark 3.0 (acc_norm) | 54.20% | 71.00% | +16.80 |
| ArithMark 2.0 (acc) | 67.32% | 67.00% | −0.32 (within noise) |
| HellaSwag | 27.46% | 27.85% | +0.39 |
| ARC-Easy | 40.24% | 43.39% | +3.15 |
| ARC-Challenge | 24.66% | 26.62% | +1.96 |
| PIQA | 56.58% | 58.49% | +1.91 |
| Open SLM Leaderboard Intelligence Index | 14.16 | 20.27 | +6.11 |
from transformers import AutoTokenizer, AutoModelForCausalLM
tok = AutoTokenizer.from_pretrained("AlgoDriveAI/Inferno-Exp-1.5")
model = AutoModelForCausalLM.from_pretrained("AlgoDriveAI/Inferno-Exp-1.5", trust_remote_code=True)
ids = tok("Once upon a time, a little fox", return_tensors="pt")
out = model.generate(**ids, max_new_tokens=80, do_sample=True, temperature=0.8, top_p=0.95)
print(tok.decode(out[0], skip_special_tokens=True))
The easiest way to play with the model is a small web app with a prompt box, sampling sliders, live streaming, and a Stop button:
*.gradio.live link it prints.If it stops and asks you to restart the session (it may need to switch Transformers to a compatible version), choose Runtime → Restart session and run the cell again.
Show the Gradio demo script (one Colab cell, ~200 lines)#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
INFERNO-EXP-1.5 — simple Gradio inference (loads like any Hub user, no pushing)
==============================================================================
Loads Inferno-Exp-1.5 with plain Transformers (AutoModelForCausalLM +
trust_remote_code=True) and serves a small Gradio app: open prompt box,
sampling controls, streaming output with a Stop button, token/speed readout.
Works with either source:
• the Hub repo: MODEL_SOURCE = "AlgoDriveAI/Inferno-Exp-1.5"
• the local export folder the push script builds (test before uploading):
MODEL_SOURCE = "/content/hf_export_inferno_exp_1_0"
Private repo? Add a Colab secret named HF_TOKEN (🔑 icon in the left sidebar, turn on
notebook access), set the env var HF_TOKEN, or paste a READ token into HF_TOKEN below.
It is a base model: it continues text, it does not chat. Write the start of the text
you want (e.g. a word problem followed by "Answer:").
Hardcoded constants, no argparse. Paste into one Colab cell and run; open the share link.
"""
# =============================================================================
# SETTINGS — edit these
# =============================================================================
MODEL_SOURCE = "AlgoDriveAI/Inferno-Exp-1.5" # Hub repo id (or a local folder with the same files)
HF_TOKEN = "" # only for private repos; "" → Colab secret / env var
MODEL_DISPLAY_NAME = "Inferno-Exp-1.5"
# Default slider values (all adjustable in the UI)
DEF_MAX_NEW_TOKENS = 256
DEF_TEMPERATURE = 0.8
DEF_TOP_K = 40
DEF_TOP_P = 0.95
DEF_REPETITION_PENALTY = 1.0
DEF_SEED = -1 # -1 = different every run
DTYPE = "auto" # "auto" (bf16 on newer GPUs, fp32 on CPU) / "float32" / "bfloat16" / "float16"
GRADIO_SHARE = True # public *.gradio.live link (needed in Colab)
GRADIO_PORT = 7860
INSTALL_DEPENDENCIES = True
# =============================================================================
# RUN (no edits needed below)
# =============================================================================
import os, sys, time, threading, subprocess
try:
import google.colab # noqa: F401
IN_COLAB = True
except ImportError:
IN_COLAB = False
if IN_COLAB and INSTALL_DEPENDENCIES:
import importlib.metadata as _md
def _version(name):
try:
return _md.version(name)
except _md.PackageNotFoundError:
return None
_before = _version("transformers")
subprocess.check_call([sys.executable, "-m", "pip", "install", "--quiet",
"transformers>=4.45,<5", "safetensors", "huggingface_hub>=0.25", "gradio"])
if _before != _version("transformers") and "transformers" in sys.modules:
raise SystemExit("Transformers was just changed to a compatible version, but the old one is still loaded. "
"Restart the session (Runtime → Restart session) and run this cell again.")
import torch
import gradio as gr
from transformers import (AutoModelForCausalLM, AutoTokenizer, StoppingCriteria, StoppingCriteriaList,
TextIteratorStreamer)
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
STOP_EVENT = threading.Event()
def get_token():
if HF_TOKEN.strip():
return HF_TOKEN.strip()
if IN_COLAB:
try:
from google.colab import userdata
value = userdata.get("HF_TOKEN")
if value:
return value
except Exception:
pass
return os.environ.get("HF_TOKEN") or None
def pick_dtype():
if DTYPE != "auto":
return {"float32": torch.float32, "bfloat16": torch.bfloat16, "float16": torch.float16}[DTYPE]
if DEVICE == "cuda":
return torch.bfloat16 if torch.cuda.get_device_capability()[0] >= 8 else torch.float16
return torch.float32
class StopOnEvent(StoppingCriteria):
"""Ends generate() as soon as the Stop button sets STOP_EVENT."""
def __call__(self, input_ids, scores, **kwargs):
return STOP_EVENT.is_set()
def load():
token = None if os.path.isdir(MODEL_SOURCE) else get_token()
dtype = pick_dtype()
tok = AutoTokenizer.from_pretrained(MODEL_SOURCE, token=token)
model = AutoModelForCausalLM.from_pretrained(MODEL_SOURCE, token=token, trust_remote_code=True,
torch_dtype=dtype).to(DEVICE).eval()
return model, tok, dtype
MODEL, TOK, MODEL_DTYPE = load()
CFG = MODEL.config
N_PARAMS = sum(p.numel() for p in MODEL.parameters())
CONTEXT = CFG.max_position_embeddings
print(f"Loaded {MODEL_SOURCE}: {N_PARAMS / 1e6:.1f}M params · {DEVICE} · {MODEL_DTYPE}")
def generate(prompt, max_new, temperature, top_k, top_p, rep_penalty, seed):
STOP_EVENT.clear()
if not prompt:
yield "", "Type a prompt first."
return
ids = TOK(prompt, return_tensors="pt", add_special_tokens=False).to(DEVICE)
room = CONTEXT - ids["input_ids"].shape[1]
if room <= 0:
yield prompt, f"Prompt is longer than the model's {CONTEXT}-token context; shorten it."
return
seed = int(seed)
if seed >= 0:
torch.manual_seed(seed)
greedy = temperature <= 0
sampling = {} if greedy else dict(temperature=float(temperature), top_k=int(top_k), top_p=float(top_p))
streamer = TextIteratorStreamer(TOK, skip_prompt=True, skip_special_tokens=True)
result = {}
def worker():
with torch.no_grad():
result["ids"] = MODEL.generate(
**ids, max_new_tokens=min(int(max_new), room), do_sample=not greedy,
repetition_penalty=float(rep_penalty), eos_token_id=TOK.eos_token_id, pad_token_id=TOK.pad_token_id,
use_cache=False, streamer=streamer, stopping_criteria=StoppingCriteriaList([StopOnEvent()]), **sampling)
started = time.time()
thread = threading.Thread(target=worker, daemon=True)
thread.start()
text = ""
for piece in streamer:
text += piece
yield prompt + text, f"generating… {time.time() - started:.1f}s"
thread.join()
new = result["ids"].shape[1] - ids["input_ids"].shape[1] if "ids" in result else 0
took = time.time() - started
status = "stopped" if STOP_EVENT.is_set() else "done"
yield prompt + text, (f"**{status}** · {new} tokens · {took:.1f}s · {new / max(took, 1e-6):.1f} tok/s · "
f"{'greedy' if greedy else f'T={temperature} · top-k {int(top_k)} · top-p {top_p}'} · seed {seed}")
def output_box():
kwargs = dict(label="Output (prompt + continuation)", lines=16, max_lines=30, interactive=False)
for extra in (dict(show_copy_button=True), dict(buttons=["copy"]), {}):
try:
return gr.Textbox(**kwargs, **extra)
except TypeError:
continue
def build_ui():
gr_major = int(gr.__version__.split(".")[0])
theme = gr.themes.Soft(primary_hue="indigo", secondary_hue="blue")
blocks_kwargs = {} if gr_major >= 6 else dict(theme=theme) # Gradio 6 moved theme to launch()
launch_kwargs = dict(theme=theme) if gr_major >= 6 else {}
with gr.Blocks(title=MODEL_DISPLAY_NAME, **blocks_kwargs) as demo:
gr.Markdown(f"# 🔥 {MODEL_DISPLAY_NAME}\n"
f"{N_PARAMS / 1e6:.1f}M-parameter math-first base model · `{CFG.num_hidden_layers}L × {CFG.hidden_size}d` · "
f"{CFG.num_attention_heads}Q/{CFG.num_key_value_heads}KV heads · context {CONTEXT} · "
f"continues text (not a chat model)")
with gr.Row():
with gr.Column(scale=3):
prompt = gr.Textbox(label="Prompt", lines=6, placeholder="Write the beginning of the text to continue…")
with gr.Row():
run = gr.Button("Generate", variant="primary")
stop = gr.Button("Stop", variant="stop")
output = output_box()
status = gr.Markdown("")
with gr.Column(scale=1):
max_new = gr.Slider(16, 1024, value=DEF_MAX_NEW_TOKENS, step=16, label="Max new tokens")
temperature = gr.Slider(0.0, 1.5, value=DEF_TEMPERATURE, step=0.05, label="Temperature (0 = greedy)")
top_k = gr.Slider(0, 200, value=DEF_TOP_K, step=1, label="Top-k (0 = off)")
top_p = gr.Slider(0.05, 1.0, value=DEF_TOP_P, step=0.01, label="Top-p")
rep = gr.Slider(1.0, 1.5, value=DEF_REPETITION_PENALTY, step=0.01, label="Repetition penalty")
seed = gr.Number(value=DEF_SEED, precision=0, label="Seed (-1 = random)")
with gr.Accordion("Model info", open=False):
gr.Markdown(f"- **Source:** `{MODEL_SOURCE}`\n- **Parameters:** `{N_PARAMS:,}`\n"
f"- **Device / dtype:** `{DEVICE}` / `{str(MODEL_DTYPE).replace('torch.', '')}`\n"
f"- **Vocab:** `{CFG.vocab_size:,}` · EOS `{TOK.eos_token}`")
inputs = [prompt, max_new, temperature, top_k, top_p, rep, seed]
run.click(generate, inputs=inputs, outputs=[output, status])
prompt.submit(generate, inputs=inputs, outputs=[output, status])
stop.click(lambda: STOP_EVENT.set(), queue=False)
return demo, launch_kwargs
if __name__ == "__main__":
demo, launch_kwargs = build_ui()
demo.queue().launch(share=GRADIO_SHARE, server_port=GRADIO_PORT, server_name="0.0.0.0", **launch_kwargs)
Tips: it is a base model, so write the beginning of the text you want rather than a question to a
chatbot, for example Sam had 47 marbles. His sister gave him 28 more. Now Sam has. Lower the
temperature (or set it to 0) for arithmetic; raise it for stories.
All scores are zero-shot on the checkpoint in this repo. The ArithMark benchmarks were scored with AxiomicLabs' official scripts, unmodified; the language benchmarks with the lm-evaluation-harness.
| Benchmark | Metric | Score | Standard error | Chance |
|---|---|---|---|---|
| ArithMark 3.0 (word problems) | acc_norm | 71.00% | ±1.43 | 25% |
| ArithMark 2.0 (integer arithmetic) | acc | 67.00% | ±0.94 | 25% |
| HellaSwag | acc_norm | 27.85% | ±0.45 | 25% |
| ARC-Easy | acc_norm | 43.39% | ±1.02 | 25% |
| ARC-Challenge | acc_norm | 26.62% | ±1.29 | 25% |
| PIQA | acc_norm | 58.49% | ±1.15 | 50% |
On the Open SLM Leaderboard's Intelligence Index formula these scores give 20.27.
Inferno-Exp-1.5 is math-first, and the scores show it: it is strong on arithmetic but modest on general commonsense and reading benchmarks, where its narrower training data gives it less to draw on. Upcoming versions keep the math foundation and broaden the training mix to lift these language and reasoning scores.
Scored with bencharithmark-3.py on
ArithMark 3.0 (1,000 four-choice
continuation word problems, grades 1–5) at commit 6f6e59dd: float32, batch size 32,
max context 1,024, no BOS token, length-normalized log-likelihood as the primary metric.
| Metric | Score |
|---|---|
| Length-normalized accuracy (acc_norm, primary) | 71.00% |
| Raw continuation accuracy | 71.20% |
| Standard error (acc_norm) | ±1.43 points |
| Random-choice baseline | 25.00% |
| Category | Items | Raw | acc_norm |
|---|---|---|---|
| Addition (grades 1–2) | 128 | 77.34% | 77.34% |
| Comparison | 44 | 88.64% | 90.91% |
| Comparison: difference | 48 | 62.50% | 62.50% |
| Data | 43 | 67.44% | 62.79% |
| Division | 54 | 83.33% | 85.19% |
| Fractions: counting | 50 | 44.00% | 44.00% |
| Geometry: area | 52 | 88.46% | 86.54% |
| Geometry: perimeter | 45 | 77.78% | 77.78% |
| Measurement | 76 | 86.84% | 86.84% |
| Money | 64 | 62.50% | 62.50% |
| Multiplication | 74 | 89.19% | 86.49% |
| Patterns | 53 | 45.28% | 45.28% |
| Subtraction (grades 1–2) | 117 | 76.92% | 76.92% |
| Time | 55 | 98.18% | 98.18% |
| Two-step add/subtract | 46 | 19.57% | 19.57% |
| Two-step addition | 19 | 42.11% | 42.11% |
| Two-step subtraction | 32 | 31.25% | 34.38% |
Scored with benchmark_arithmark-2.0.py on
ArithMark 2.0 (2,500 four-choice integer
arithmetic continuations such as (16 / 4) + 44 =) at commit 5bd986c7: the script's standard GPU
setting (bfloat16), batch size 16, max context 1,024, no BOS token, raw summed continuation
log-likelihood (the benchmark's only metric).
| Operators per expression | Items | Accuracy |
|---|---|---|
| 1 | 1,250 | 96.88% |
| 2 | 750 | 43.87% |
| 3 | 500 | 27.00% |
| Overall | 2,500 | 67.00% (1,675 / 2,500) |
Standard error ±0.94 points; random-choice baseline 25.00%.
Zero-shot, acc_norm, float32, batch size 16:
lm_eval --model hf \
--model_args "pretrained=AlgoDriveAI/Inferno-Exp-1.5,trust_remote_code=True,dtype=float32" \
--tasks hellaswag,arc_easy,arc_challenge,piqa --num_fewshot 0 --batch_size 16
| Task | Items | acc_norm |
|---|---|---|
| HellaSwag | 10,042 | 27.85% ± 0.45 |
| ARC-Easy | 2,376 | 43.39% ± 1.02 |
| ARC-Challenge | 1,172 | 26.62% ± 1.29 |
| PIQA | 1,838 | 58.49% ± 1.15 |
bos_token is set to <|endoftext|>, the document
boundary the model saw during training, for tools that prepend one.