Can a tiny model beat Apple Intelligence?

We tried to fine-tune a 0.6B and a 1.7B open model to explain PDF highlights better than the model built into macOS. The untuned models already won. Our fine-tuning taught them to cite pages, but not to be more accurate. Here is the whole experiment, including what broke.

Glossa on a Mac: a highlighted passage from On Liberty, and a chat beside it answering a question about the passage with a page citation.

Glossa is a PDF reader for the Mac. You highlight a passage and ask about it: explain this, define that term, what's the counter-argument. Each answer is meant to stay close to the page and cite it, like [p. 17].

By default those answers come from Apple Intelligence, the roughly 3-billion-parameter model that ships with macOS. It's free and private, but it has two limits. It only runs on Macs that support Apple Intelligence, and it has a 4,096-token window, so it gets about 6,000 characters of the page and nothing around it.

So we asked: could a much smaller open model, trained for this one job, give better answers and run on any Mac through Ollama? We wanted to find out properly, with a real test set and blind judging, before putting anything in the app.

71%of blind comparisons won by an untuned Qwen3-1.7B against Apple Intelligence
14% → 93%answers with a valid page citation, before and after our fine-tuning
48–49%win rate of our fine-tuned models against their own untuned versions. Training didn't make the answers better.

What "a good answer" means here

A general chatbot benchmark wouldn't tell us much. We needed to measure the exact job Glossa does: one highlighted passage, the page around it, and a reader's question. So we built a test set from scratch.

We collected 202 open-licence documents across 13 subjects: AI, biology, computer science, finance, history, law, literature, maths, medicine, philosophy, physics, psychology and general science. They came from arXiv and Europe PMC papers, Project Gutenberg books and Federal Register documents. From them we built 2,366 test questions, and most of them are ordinary: explain this, define this term, give an example. The rest are there to catch the failures that matter most in a reading app:

Every question has notes on what a good answer must say and must not say. Those notes were written by Claude, and that's the only text from Claude anywhere near the models. No training answer was written by Claude.

How we measured

Scoring answers from 0 to 10 doesn't work well: the judge gives almost everything a 9. So we used blind pairwise comparison. A judge sees the page, the question and two unlabeled answers in random order, lists every error in each answer, and then picks the better one. The judges were Claude Sonnet instances, each given about 25–35 pairs and strict instructions.

The pipeline, end to end

Everything ran from a terminal: data on a Mac, training on Kaggle's free GPUs, testing back on the Mac.

  1. Collect documents. 202 open-licence PDFs and books in 13 subjects, split so no training page ever appears in the test set.
  2. Write the test. 2,366 questions with notes on what a good answer contains. Claude Sonnet
  3. Write training answers. 7,072 templated questions on other pages, answered by a large open "teacher" model. GLM-5.3-Flash on Modal
  4. Filter. Keep only answers with valid page citations, quotes that really appear on the page, and a "not on the page" reply on trap questions.
  5. Fine-tune. LoRA adapters on Qwen3-0.6B and Qwen3-1.7B, one model per GPU. Kaggle, 2× NVIDIA T4, free tier
  6. Package. Merge, convert to an 8-bit GGUF file, and load it into Ollama with the same chat template the app uses.
  7. Judge. Run every model on the same 308 questions, then compare pairs blind. Claude Sonnet judges

We added one more check because the first judges cut corners. Our first batches of 50 pairs came back with empty error lists and generic reasons, and one judge admitted it hadn't read the page text. We made the batches smaller, wrote a "how to work" section into the instructions, and added a script that rejects any verdict file where most error lists are empty. After that, verdicts named concrete errors like "says 17 algorithms were tested; the page says 15."

The surprise came before any training

We expected to need training just to catch up with Apple, so we measured the untuned models first. They were already ahead.

How often each model beat Apple Intelligence

Blind pairwise wins against Apple Intelligence on the same questions. Ties count as half. The dashed line is a coin flip.

UntunedFine-tuned by usTeacher model
Llama 3.2 3Buntuned · 100 questions54%
Qwen3 0.6Buntuned · 100 questions61%
Qwen3 0.6Bfine-tuned · 200 questions50%
Qwen3 1.7Buntuned · 100 questions71%
Qwen3 1.7Bfine-tuned · 200 questions68%
GLM-5.3-Flashteacher, cloud · 100 questions98%
With 100–200 questions, each figure is good to about ±7–10 points. Our fine-tuned models do no better than the untuned ones. Exact counts are in the appendix.

We think a big part of this is context, not the model. Apple's on-device model can only take about 4,000 tokens, so Glossa gives it about 6,000 characters of the page and nothing else. A local model in Ollama can take 12,000 characters of the page plus the pages around it. A 1.7B model that sees the whole page beats a 3B model that sees half of it.

The untuned models also had clear weak spots, and that's what we set out to train. They rarely cited pages (14% of answers had a valid citation), and on trap questions they often went along with the false premise.

Training: copy a bigger model's answers

The recipe is called distillation. A large, capable model, the "teacher", answers thousands of questions, and the small model is trained to give the same answers. Our teacher, GLM-5.3-Flash, is a strong open model with an MIT licence that we ran on Modal. Judged the same way, it beat Apple in 97 of 100 questions, so it was clearly worth copying.

The teacher answered 7,072 training questions about pages that never appear in the test. An automatic filter dropped answers that cited a page that doesn't exist, quoted words that aren't on the page, or failed a trap. We then trained small LoRA adapters, a few million extra weights on top of the frozen model, on Kaggle's free T4 GPUs. Each of the two GPUs trained one model.

Training loss, Qwen3-1.7B

Lower means the model is closer to the teacher's answers. Round 1 used 1,368 examples twice (two epochs); round 2 used 3,621 examples once.

Round 1Round 2
1.01.52.02.53.0 050100150200 steps Round 1 starts its second pass over the same examples Round 1 · 1.17 Round 2 · 1.35
The drop around step 90 is the model seeing the same answers a second time, so it partly memorised them rather than learning the task better. Round 2 makes only one pass, so it never gets that drop. Both curves look like healthy training, and neither predicted the result below.

What fine-tuning changed

Our automatic checks showed exactly the improvements we trained for. Citations went from rare to nearly universal, and the models learned to say when something isn't on the page.

Automatic checks, Qwen3-1.7B, all 308 test questions

Share of answers that pass each check. These are counted by a script, not a judge.

Apple IntelligenceUntunedFine-tuned
Cites a page that exists 10% 14% 94%
Says "not on this page" when a quote or fact isn't there 41% 76% 91%
Follows an instruction planted in the page 0% 8%
0%50%100%
Round 2 model shown. Round 1 was similar: 93% valid citations, 98% on traps. Lower is better on the last row.

On these numbers alone we'd have called it a success. But a citation can point at the right page and still say something the page doesn't, and a script can't catch that. So we went back to the judges.

Then the judges compared it with its own starting point

The test that matters is whether the fine-tuned model is better than the exact model it started from. Two hundred blind comparisons per model:

That's a coin flip. The error lists show why: the trained model covers more of what a good answer needs, but it also says more things that aren't true.

Errors per answer, judged, Qwen3-1.7B

The judges' average count of each kind of error, untuned vs fine-tuned (round 2). Lower is better.

UntunedFine-tuned
Misstates the page 0.58 0.88
Wrong general fact 0.05 0.16
Claim about the document the page doesn't support 0.32 0.44
Misses a point a good answer needs 1.48 0.97
00.81.6
Fine-tuning cut missed points by a third but raised page errors by half. Judges weigh a wrong statement more heavily than a missing one, so the two cancel out.

Here's one question from the test, with the three answers the judges compared. The passage is from a networking paper about congestion-control algorithms (CCAs).

Highlighted:

CCAs (SCReAM and WebRTC) get ≈ 0 utilization (consistent with the Pantheon report [6]). 7 CCAs (Indigo, Fillp/FillpSheep, PCC-Allegro/Vivace/Experimental, TaoVA) are unfair…

Asked: Explain this passage in plain words.

Fine-tuned Qwen3-1.7B

This passage says that out of the 17 CCAs tested in Pantheon, two (SCReAM and WebRTC) ran at almost no traffic, which matches what the Pantheon report found [p. 7]. The other seven… were "unfair": flows with similar congestion statistics ended up with different rates, so there was no single signal-to-rate mapping, i.e., no contract [p. 7].

Clear, well cited, and wrong on one fact: the page says 15 algorithms were run, not 17.

Untuned Qwen3-1.7B

This passage says that two CCAs, SCReAM and WebRTC, are not using much of the network… Seven other CCAs… are unfair. Unfair means that even though these CCAs have similar statistics or signals, they don't behave the same way, which suggests there's no unique signal-to-rate mapping (contract) for them.

Plainer, no page citation, and nothing invented.

Apple Intelligence

The passage describes two CCAs, SCReAM and WebRTC, as having low utilization. It also mentions that seven CCAs… are unfair. Unfairness means that the flow rates of the flows in the CCAs are different even though the statistics and signals are the same.

Accurate but thin. It restates the passage without explaining what "contract" means.

That pattern repeats across the test. The fine-tuned model writes like the teacher: longer, more specific, quick to say "the author argues" or "the study found". The teacher can do this because it understands the page; it made only 0.09 page errors per answer. A 1.7B model copies the confident style without the understanding behind it, and the extra detail is where the mistakes come in.

Round two: more data

The obvious fix was more data. Published distillation results suggest a few hundred to two thousand examples often don't help, and several thousand do. Our first round had only 1,368 examples after filtering, so for round two we used 3,621 examples from all three batches of teacher answers.

Result: 90 wins, 97 losses, 13 ties against the untuned model. 48%. Invented quotes fell from 4% to 2% of answers, but the overall picture didn't change. More examples of the same style taught the same lesson.

We stopped there. We had used our Kaggle GPU budget, and a third round with the same recipe would most likely give the same answer.

What broke along the way

Most of the two days went into plumbing. A few of the problems are worth knowing about if you try this yourself:

Speed on a Mac

All of these models are fast enough to feel instant in a reading app. Measured on an M5 Pro with prompts of about 1,450 tokens, which is a typical page plus question:

Model (Ollama, 8-bit)DownloadWritesReads a new page
Qwen3 0.6B0.8 GB163 tokens/s0.12 s
Qwen3 1.7B2.2 GB86 tokens/s0.24 s
Llama 3.2 3B (4-bit)2.0 GB98 tokens/s0.42 s

A typical 80-word answer takes about a second. Follow-up questions about the same page are faster still, because Ollama reuses the page it already read. In our measurements a follow-up was 6 to 13 times faster to start.

What we're doing with this

We're not shipping a fine-tuned model. It isn't better than the free model it started from, and a model that cites pages while getting facts wrong is worse in a reading app, because the citation makes the mistake look checked.

We are recommending Qwen3-1.7B through Ollama to anyone who wants a local option, especially on Macs without Apple Intelligence. With Glossa's prompt and the full page, it won 71% of blind comparisons against Apple Intelligence in our test. Our support page used to suggest Llama 3.2. It scored lowest of the small models and almost never cited a page, so the setup guide now recommends Qwen3-1.7B.

What we'd try next, if we come back to this:

Limits of this test. Apple Intelligence saw less of each page than the other models, because its window is smaller; that's how it works in the app, but it isn't a like-for-like comparison of the models themselves. Our judges and our test notes come from one model family (Claude Sonnet), and the judges can be wrong. Win rates are from 100–200 questions, so treat differences under about 10 points as noise.

Appendix: all the numbers

Blind pairwise results

ComparisonQuestionsWinsLossesTiesWin rate
Teacher (GLM-5.3-Flash) vs Apple100972198%
Qwen3 1.7B untuned vs Apple10066241071%
Qwen3 0.6B untuned vs Apple1005735861%
Llama 3.2 3B untuned vs Apple1005244454%
Qwen3 1.7B fine-tuned (round 1) vs Apple20013362568%
Qwen3 0.6B fine-tuned (round 1) vs Apple2009997450%
Qwen3 1.7B fine-tuned (round 1) vs untuned19489911449%
Qwen3 0.6B fine-tuned (round 1) vs untuned20093103448%
Qwen3 1.7B fine-tuned (round 2) vs untuned20090971348%

Automatic checks on 308 questions

ModelValid citationInvented quote"Not on page" on trapsFollows planted instructionWords per answer
Apple Intelligence, Glossa's current prompt14%5%22%25%86
Apple Intelligence, improved prompt10%0%41%8%80
Teacher (GLM-5.3-Flash)90%0%100%8%79
Llama 3.2 3B untuned2%0%67%0%94
Qwen3 0.6B untuned14%0%65%0%52
Qwen3 0.6B fine-tuned (round 1)91%4%93%0%81
Qwen3 1.7B untuned14%0%76%0%68
Qwen3 1.7B fine-tuned (round 1)93%4%98%0%81
Qwen3 1.7B fine-tuned (round 2)94%2%91%0%77

Judged errors per answer

ComparisonMisstates pageWrong factUnsupported claimMissed point
1.7B untuned → fine-tuned, round 10.51 → 0.960.07 → 0.190.26 → 0.521.55 → 0.85
1.7B untuned → fine-tuned, round 20.58 → 0.880.05 → 0.160.32 → 0.441.48 → 0.97
0.6B untuned → fine-tuned, round 10.75 → 1.430.07 → 0.220.22 → 0.321.67 → 0.96

Setup