Anass Kartit
← Writing / / 7 min read / Updated

EmbeddingGemma 2 Review: 30/30 vs Mac Spotlight 5/30, Offline Photo Search

EmbeddingGemma 2 found the right file 30/30 times on a Mac, Spotlight 5/30. Plus offline face search by name: 114/121 found, 0 wrong. Free app and code.

embeddinggemma 2embeddinggemma 2 reviewmac spotlight alternativelocal ragoffline ai on macface recognition by namearcfacegemma 4 e4bphoto cleanup ailocal ai 2026
EmbeddingGemma 2 vs Mac Spotlight: 30/30 vs ?
Watch: EmbeddingGemma 2 vs Mac Spotlight: 30/30 vs ?

EmbeddingGemma 2, Google’s new free embedding model, found the right file 30 times out of 30 on my Mac in October 2026, offline, in about 34 ms per question. macOS Spotlight found 5. I used it to build the face-search computer from the movies: type a name and every photo of that person lights up. From 5 clicks on one photo, it found a fictional family 114 times out of 121, with 0 wrong names. This is the written companion to my 6-minute video, with every number, how it works, what broke, and the code.

Watch the video: EmbeddingGemma 2 vs Mac Spotlight: 30/30 vs ?. The app and every benchmark: github.com/AnassKartit/embeddinggemma2-photo-sweep.

Key facts (quick answer)

FactMeasured result
Right file first, 30 questions, 62 filesEmbeddingGemma 2 30/30, file names 12/30, Spotlight 5/30 (11/30 keywords only)
Search speed62 files indexed in 5.0 s, about 34 ms per question, offline
Answers from your files (Gemma 4 E4B)11/11, about 2 s each, 6.5 GB peak memory
Find anyone by name (ArcFace, 5 clicks on 1 photo)114/121 family appearances, 0 wrong names; 118/121 after 2 more clicks
Photo cleanup, no training29/29 family photos kept, 1 of 77 junk let through
Speed per photo (70 image tokens, Mac GPU)85 ms (556 ms at the default 280 tokens)
Electricity bills: find, read, add up12/12 bills exact; one-prompt total was wrong
Vector database needed?No: numpy, ChromaDB, sqlite-vec, pgvector all 29/30
Cost$0 on the Mac; the cloud comparison cost $0.19 for 948 calls

TL;DR

  • EmbeddingGemma 2 understood plain questions like “where’s my latest electricity bill?”: 30/30 vs Spotlight’s 5/30.
  • Gemma 4 E4B answered from the files it found: 11/11, about 2 s each, nothing left the Mac.
  • Name 5 faces in one photo and search by name: 114/121 found, 0 wrong names, 0 names on photos of other people.
  • “Max birthday” works too: the name filters first, then EmbeddingGemma 2 ranks the rest by meaning.
  • The 6 cloud decision models that can see images sorted junk well, but every photo is uploaded.
  • You do not need a vector database or LangChain for one person’s files.

How does EmbeddingGemma 2 compare to Mac Spotlight?

It found the right file first 30 times out of 30; Spotlight found it 5 times.

EmbeddingGemma 2 vs Mac Spotlight: right file first on 30 questions

The test folder is a fictional Downloads folder for one made-up person: 62 files, including three electricity bills from 2024, 2025 and 2026 with dull file names, a boarding pass, a lease, notes, installers, screenshots and receipts. I wrote the 30 questions and the right file for each before running anything.

SearchRight file first (of 30)Right file in top 5
EmbeddingGemma 2 (offline)3030
File-name search1215
macOS Spotlight, keywords only (mdfind)1112
macOS Spotlight, the question as typed56

Why the gap: Spotlight matches words. EmbeddingGemma 2 turns each file and each question into 768 numbers that describe meaning, so “latest electricity bill” lands next to ebill_download.pdf even though no word matches. For “latest”, the app re-sorts near ties by date.

Can it answer questions from my files?

Yes. This is RAG in plain words: EmbeddingGemma 2 finds the 3 best files, then a small model reads them and answers.

Model on the MacRight answersMedian timePeak memory
Gemma 4 E4B (mlx-community/gemma-4-E4B-it-qat-4bit)11/112.0 s6.5 GB
Qwen3 4B Instruct 2507 (4-bit)11/112.2 s3.0 GB
Qwen3.5 9B (4-bit)11/114.8 s5.9 GB

Example: “how much was my latest electricity bill?” gave “$131.44” with the file name ebill_download.pdf.

For totals, do not let the model add. With all 12 monthly bills in one prompt, Gemma 4 E4B said $1,477.17, which is wrong. When it read one bill at a time into JSON and plain Python added them, all 12 totals were exact and so was the year ($1,741.64).

How does “find anyone by name” work?

You click 5 faces in one photo and type their names; the app then names every face it is sure about.

Find anyone by name: the whole family search with 114 of 121 found

  1. YuNet (OpenCV) finds every face and 5 points on it (eyes, nose, mouth corners).
  2. ArcFace R50 turns each aligned face into 512 numbers. Two photos of the same person land close together, across ages and angles.
  3. A face gets a name when it is at least 0.4 similar to the faces you named, and each name is used once per photo.
  4. Search: type “Lily”, “Max birthday” or “whole family”. Names filter first, then EmbeddingGemma 2 ranks the rest.

Search Lily: 19 photos, each with MATCH FOUND and a score

Measured on 112 WhatsApp-style files with a fictional family of 5 in 29 photos (121 face appearances):

SettingFoundWrong namesNames on other people’s photos
ArcFace, 0.4, 5 clicks on 1 photo114/12100
+ 2 more clicks (Lily and Emma in a pool photo)118/121 (108/111 on photos it never learned from)00
ArcFace, looser 0.3121/1210strangers named in 7 photos
SFace (the free-for-commercial model)115/121 on the benchmark

The looser setting finds everyone but starts naming strangers, so the app stays at 0.4 and asks you for one more click instead.

For your own library, agent/people.py groups every face it finds, lets you name groups, cross out the faces that are not that person, hide groups you don’t care about, and then shows the faces it is least sure about. Learning is examples, not retraining: every click is stored and used on the next search. Fingerprints and names stay in a folder on your Mac.

Can it clean the junk off a phone?

Yes, on a test phone with 158 photos squeezed like WhatsApp (1600 px, JPEG quality 70).

The photo cleanup app running on a Mac

CheckResult
Family photos kept, no training29/29
Junk let through, no training1 of 77
Speed at Google’s phone setting (70 image tokens)85 ms per photo
One family photo + YuNet/SFace, strict setting97.4% of the family found, 0.8% of other families kept
You tag 20 photos, then it decides junk or keep96.9% (tag 40: 97.8%)
Best cloud decision models (Perplexity Decider, Mercury Decide)158/158, but every photo is uploaded

The app never deletes anything: Sweep moves files into _Sweep/<pile>/ and Undo puts them back.

Do I need a vector database or LangChain?

No, not for one person’s files.

StoreRight file first (30)At 50,000 vectorsTrue top 10 found
numpy, in memory (what the app uses)296 ms100%
ChromaDB 1.5.92911 ms92%
sqlite-vec 0.1.62995 ms100%
Postgres 17 + pgvector, HNSW index2922 ms64% at default settings

Chunking is 3 lines of Python: 700-character pieces, 100 characters overlapping, each piece starting with the file name. The full search is about 80 lines. LangChain, LangGraph or ADK would add dependencies and change nothing here. They start to make sense for multi-step agents, like “find every passport photo and move it”.

If the library grows, the next step is saving the index in SQLite so a restart only embeds new files. Past a million pieces, sqlite-vec or LanceDB. For a multi-user cloud version, Postgres + pgvector, with the index tuned and measured first.

What broke?

  • Other families kept as family. EmbeddingGemma 2 alone knows a photo is a family photo, not whose family, so other families’ photos went into the family pile. Two small face models fixed it.
  • Looser face matching names strangers. 0.3 found 121/121 but named strangers in 7 photos.
  • One-prompt totals. The model added 12 bills wrong; code adds them right.
  • Licence. ArcFace weights are non-commercial. YuNet (MIT) and SFace (Apache 2.0) are the commercial-safe pair.

My take

The surprise is how little you need. One free embedding model, one small reading model and 80 lines of Python beat the search built into every Mac, and nothing leaves the laptop. The face search is the part people ask about, and it works because it asks you for 5 clicks instead of guessing. Start with plain numpy and a folder; add a database when the numbers tell you to.

Sources

Independent review by Anass Kartit. Not affiliated with Google.

Newsletter

Get the next post and game in your inbox

One email when I publish something new: measured write-ups on AI, local models and cloud, plus games like NEON RUN.

Your email is never shown or shared. What is stored and how to leave