Views
No views yet
Honesty first: this is a 150M hobby model, not a Phi/SmolLM competitor. It chats, follows simple instructions, and retrieves facts from very long inputs, but it has the factual ceiling you'd expect at this size (see Limitations). Compare it to other consumer-GPU hobby projects, not to lab models.
trust_remote_code=True:1import torch
2from transformers import AutoModelForCausalLM, AutoTokenizer
3
4repo = "Sakatepon/Brujula-150M-32K-chat"
5tok = AutoTokenizer.from_pretrained(repo, trust_remote_code=True)
6model = AutoModelForCausalLM.from_pretrained(
7 repo, trust_remote_code=True, dtype=torch.bfloat16
8).to("cuda").eval() # "xpu" for Intel Arc; "cpu" works too
9
10prompt = "User: Explain why the sky is blue in one paragraph.\nAssistant:"
11ids = tok(prompt, return_tensors="pt").input_ids.to(model.device)
12out = model.generate(
13 ids, max_new_tokens=256,
14 do_sample=True, temperature=0.8, top_p=0.95,
15 repetition_penalty=1.3, # important — see Limitations
16 use_cache=False, # this reference impl has no KV cache
17 pad_token_id=50256, eos_token_id=50256,
18)
19print(tok.decode(out[0], skip_special_tokens=True))User: <your message>
Assistant:<|endoftext|> (id 50256) to end a turn; generation stops there.1context = open("long_document.txt").read()
2prompt = f"{context}\n\nUser: According to the document, who founded the company?\nAssistant:"User:/Assistant: chat format and sampling.... IMPORTANT: the X is Y. Please remember it.)
and the query is a stem the model completes (Question: what is the X? Answer: the X is ).
Wrapping the whole haystack in User: ... Assistant: and asking conversationally is
out-of-distribution for the retrieval head — it reads as a chat and free-associates instead of
looking the fact up.do_sample=False). With the
chat defaults (temperature=0.8, top_p=0.95) the correct token is usually in the
distribution but you won't reliably draw it — sampling turns a hit into a coin-flip. Also drop
repetition_penalty here (it can push the model off the correct token) and keep
max_new_tokens small (~16) — you only need the fact echoed back.1import torch
2from transformers import AutoModelForCausalLM, AutoTokenizer
3
4repo = "Sakatepon/Brujula-150M-32K-chat"
5tok = AutoTokenizer.from_pretrained(repo, trust_remote_code=True)
6model = AutoModelForCausalLM.from_pretrained(
7 repo, trust_remote_code=True, dtype=torch.bfloat16
8).to("cuda").eval() # "xpu" for Intel Arc; "cpu" works too
9
10NOISE = " The weather report mentioned clear skies and a gentle breeze across the quiet valley that morning."
11
12def needle_test(label, secret, context_len=16384, depth=0.5):
13 """Plant `secret` ~`depth` of the way into a `context_len`-token haystack, then ask for it."""
14 nz = tok(NOISE, add_special_tokens=False).input_ids
15 fact = tok(f" IMPORTANT: the {label} is {secret}. Please remember it.", add_special_tokens=False).input_ids
16 q = tok(f" Question: what is the {label}? Answer: the {label} is", add_special_tokens=False).input_ids
17 budget = max(0, context_len - len(fact) - len(q) - 2)
18 fill = lambda n: (nz * (n // len(nz) + 1))[:n]
19 nb = int(budget * depth)
20 ids = torch.tensor([fill(nb) + fact + fill(budget - nb) + q], device=model.device)
21 out = model.generate(
22 ids, max_new_tokens=16,
23 do_sample=False, # GREEDY — retrieval is a lookup, not a creative task
24 use_cache=False, # no KV cache in this reference impl
25 pad_token_id=50256, eos_token_id=50256,
26 )
27 answer = tok.decode(out[0, ids.shape[1]:], skip_special_tokens=True)
28 print(f"[{label}] depth {depth:.0%} of {context_len:>6}: "
29 f"{'✓ FOUND' if secret in answer else '✗ miss'} -> {answer!r}")
30
31needle_test("vault code", "MELON-7714", context_len=16384, depth=0.10)
32needle_test("password", "river-galaxy-92", context_len=16384, depth=0.50)
33needle_test("room number", "B-4417", context_len=32768, depth=0.70)... Answer: and let it continue) — just decode greedily. The chat persona is for short turns;
the retrieval head wants a continuation.repetition_penalty ≈ 1.3. Without it, it loops. This single knob was the
biggest lever on chat quality in testing.yarn_aggr (NTK-by-parts ramp β=16 + attention temperature
mscale = 0.1·ln(32768/1024)+1), applied training-free, then answer-masked SFT at 16K
(loss only on completion tokens) on a passkey/needle retrieval set to restore retrieval at the
extended length.smol-smoltalk, mixed with retrieval windows so the 32K skill
survives the chat tuning.faro/Brújula stack) is a separate project — the modeling code
in this repo (modeling_brujula_v2.py, configuration_brujula_v2.py) is self-contained and
matches that trainer bit-for-bit (logits parity-checked < 1e-5 at build).