edu-ganda-gemma-e2b-v5 (EXPERIMENTAL — current best)

Experimental research checkpoint — Crane AI Labs' current best Luganda primary-education assistant. A SLERP merge (alpha 0.5) of two Crane experimental Gemma-4-E2B checkpoints:

  • a065_polished_v2 — Luganda-vocabulary-repaired base (good Luganda content, weak instruction-following), and
  • ganda-e2b-v4 (edu-ganda-gemma-e2b-v4) — strong instruction-following (weaker Luganda content).

The merge combines V2's Luganda accuracy with v4's instruction-following, and beats V2, every finetuning attempt (GRPO/SFT), and every alternative merge we tried (including pre-QAT-v4 merges).

Good at (guard-free, vs the a065_polished_v2 base)

Metric v5 merge V2 base
Instruction-following (IF-adherence) 65.9% 40.9% (+25)
Judge task quality /10 4.6 3.76
Judge Luganda /10 7.84 7.52
Math (mn100) 72% 70.7%
Doom (repetition) lower than base

Bad at

  • FLORES lug→en translation — chrF about −3.3 vs base.
  • Guarded followed% caps around ~44% (n=25, a coarse judge metric).

Required serving settings (OPTIMAL — from a guard sweep)

  • repetition_penalty=1.0 (off) + no_repeat_ngram_size=4 → doom 0/0, math 68.3, IF 68.3. This is the recommended guard. The older 1.15 / 3 guard is over-tuned and costs roughly −7 pt math and −3 pt IF for no doom benefit here.
  • eos_token_id=[<eos>, <end_of_turn>].
  • Prepend <bos> (id 2) before the chat-templated prompt.

Base models

  • a065_polished_v2 (Crane experimental, Luganda-vocab-repaired)
  • ganda-e2b-v4 = CraneAILabs/edu-ganda-gemma-e2b-v4 (Crane experimental)

Experimental research checkpoint. Best-effort Luganda content; review before high-stakes use.

Usage

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

MODEL = "CraneAILabs/edu-ganda-gemma-e2b-v5"
tok = AutoTokenizer.from_pretrained(MODEL)
model = AutoModelForCausalLM.from_pretrained(MODEL, torch_dtype=torch.bfloat16, device_map="auto").eval()
eos_ids = [tok.eos_token_id] + tok.convert_tokens_to_ids(["<end_of_turn>"])

def chat(prompt, max_new_tokens=256):
    text = tok.apply_chat_template([{"role": "user", "content": prompt}],
                                   add_generation_prompt=True, tokenize=False)
    inputs = tok(text, return_tensors="pt").to(model.device)
    out = model.generate(**inputs, max_new_tokens=max_new_tokens, do_sample=False,
                         repetition_penalty=1.0, no_repeat_ngram_size=4,   # guard: prevents loops
                         eos_token_id=eos_ids, pad_token_id=tok.pad_token_id or tok.eos_token_id)
    return tok.decode(out[0, inputs.input_ids.shape[1]:], skip_special_tokens=True).strip()

print(chat("Nnyonnyola engeri y'okunaaba engalo mu Luganda."))

Recommended decoding: greedy with repetition_penalty=1.0, no_repeat_ngram_size=4 (best doom/math/instruction-following tradeoff from a guard sweep), eos_token_id=[<eos>, <end_of_turn>]. The n-gram guard is needed to prevent loops.

Downloads last month
827
Safetensors
Model size
6B params
Tensor type
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support