Picking an icon for a to-do is a hard machine-learning problem. Someone types “call the dentist” and expects a phone, a tooth or a calendar, in any language. The usual answer is to send the note to a hosted general-purpose LLM.
We gave an agent on the Divergent Labs harness a brief for a model we called Iconic, with the following constraints: fit under 6 MB, run fast on an iPhone-class chip, and support all 24 official EU languages.
The agent tested two training-free approaches, generated and filtered 451,062 labelled examples, ran twelve architecture experiments and exported a 4.26 MB Core ML model. It reached 0.802 hit@3: the right icon appeared among its first three suggestions 80.2% of the time.
Iconic loads when you scroll here.
There are three ways to get from a note to an icon: match the words, match the meaning, or train on examples. The agent started with the cheapest first: let's try to match the text against the tags phosphor ships with?
Match the words
BM25, the keyword ranker behind most search boxes, scores a document by the rare words it shares with the query. The agent tested it on MASSIVE, short voice-assistant requests translated into 16 of our 24 languages. It puts the right icon in the top three for 53% of English notes and 2% of Finnish ones. The tags exist only in English, so “soita hammaslääkärille” (“call the dentist”) shared no token with any tag and scores zero.
Words don't cross languages. Does meaning?
Match the meaning
A static embedding is a lookup table with one vector per token, trained so similar meanings tend to land close together in any language.
The agent used potion-multilingual-128M. Averaging a note's vectors failed: “wake me up at five am” gives five filler words the same weight as “wake”, and alarm never surfaced. Scoring each content word separately against short phrases improved the score.
Unicode's CLDR has human-written emoji keywords in all 24 languages, so the agent matched each family to an emoji twin and inherited real translations. The pairing score is how close a family name sits to an emoji keyword in the table. shovel scores 0.618 against , which is right, and replit-logo scores 0.622 against 🧑💻, which is wrong. A 0.62 can mean either, so no cutoff separates a true twin from a false one. A judge model reads the pair and decides.
With no training, this reaches 50% hit@3. The table knows what words mean but has no idea which icons people use in to-dos, so half the time the right icon misses. Fixing that takes a labelled dataset in 24 languages, which the agent could not find on Hugging Face. So where do we get this data?
Create the data
The agent generated the dataset. An LLM wrote 778,074 unique phrases. Two judges from a different model family read each phrase next to shuffled candidate families and picked one by the log-probability of a single letter (the model's score for that letter coming next). A phrase survived when both picked its family, and we ended up with 451,062 labelled texts.
Our agent knew a model grading its own writing shares the blind spots that produced it, which is why the judges come from another family entirely.
The agent tried multiple models, its first choice of judge was a mistake. It watched the judges' performance and picked those that ran the fastest.
How do you train on 451,062 phrases and still fit under 6 MB?
Train small
The agent figured out we needed to strip some components, so Iconic lacks attention. A transformer lets every token look at every other one, which is how it tells a river bank from a savings bank. A to-do is six words, and “call” means the same next to “dentist” as apart. Reading a note costs table lookups, two averages and one matrix multiply, and Iconic reaches 0.81 hit@3.
Another failed experiment had to do with size: our lexical table alone came to 33 MB at 4 bits per parameter. The agent swept four table shapes and three dropout rates inside 6 MB, and the result surprised us. At the same size, more rows lose.
All 12 runs
| Rows × dims | Dropout | Size | hit@3 |
|---|
Our working hypothesis, untested, is that 16 dimensions can't separate 863 families. Compiled to Core ML with 4-bit weights, Iconic is 4.26 MB. On the same 3,000 test notes it scores 0.802 hit@3, against 0.807 for the uncompressed model. It fits. Is it good enough?
What we're still working on
Not yet. Each of the 16 languages we can test has a hit@3 floor: 0.90 for English, French, German and Dutch, 0.82 for the rest. The model and eval are overfit for texts that look like todo's right now. If you need another use-case, the model may have to be retrained with this data.
Why now
Open-weights models can now write and judge short phrases in 24 languages well enough to train on, so the bottleneck is running the loop: experimenting and scoring what ships.
With the Divergent Labs harness, agents get access to large GPU clusters. In this case they were used to generate and judge hundreds of thousands of examples, sweep model configurations and export what ships.
You set the benchmark; the agent runs the loop, reports where it fell short, and adjusts its experiment.
Iconic is what it produced here.
We're opening early access for teams who want to bring down their compute costs and train their own models.