This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
Repo: https://github.com/zish-s/EZsearch
A sloth does not rush. It conserves its energy and lets the world come to it.
EZsearch is built the same way: two open models run slowly and locally on your laptop, so that you never have to spend time searching for the perfect image to paste into your docs again.
What I Built
Imagine you're finished with your report, and then you remember you need to paste photos!
It can be such a hectic task - google search and then try to find a good quality, not blurred, not watermarked, perfect picture describing what you want, then having to copy, go back to your document and paste.
I'm an avid lazy person, someone who chose to study comp sci because apparently all you need is a laptop and you can work while sitting anywhere.
Hence, to simplify this tedious process I built EZSearch.
This is how the popup looks like in action
- Select a sentence anywhere - Word, Google Docs, PowerPoint, OneNote, a browser.
- Press
Ctrl+Shift+X. A small panel appears next to the cursor with up to eight matching pictures. - Click one and it is pasted right in the document you were already typing in.
Ctrl+click opens the source of the picture. Right-click copies a finished attribution line.
The idea is simple, it was how I implemented the approach to come up with as accurate pics as possible!
Demo
A demonstration video showing exactly how you can use this build on your desktop:
Code
https://github.com/zish-s/EZsearch
-
ezsearch.py- the hotkey, selection capture, popup-close-before-capture, paste dispatch -
ezsearch_core.py- query ladder, Commons/Openverse clients, licence and artwork filters, de-duplication, CLIP scoring, on-disk cache -
ezsearch_ui.py- the popup: up to eight tiles,+ show more, match bars, credit copy -
ezsearch_focus.py- the Win32 focus capture and restore that makes Word obey -
tests/andbenchmark.py- 64 offline tests, and the 20-sentence x 2-model benchmark
MIT licensed. python -m pytest runs the suite; python ezsearch.py --search "..." runs headless.
How I Built It
This project was built using OpenCode
Two open models do the slow jobs in EZsearch, and both run on the laptop:
| Piece | Job | Licence |
|---|---|---|
| Llama 3.2 3B via Ollama | Turns the sentence into a short, photographable query | Llama 3.2 Community |
| CLIP ViT-B/32 via fastembed (ONNX) | Scores each candidate against the whole sentence | MIT |
| Wikimedia Commons + Openverse | Supply the pictures | CC / public domain, per file |
- Gemma 3 4B is a one-env-var swap and was benchmarked against it.
Around the models it is deliberately plain Python: Tkinter for the popup, pynput for the global hotkey, pywin32 (pythoncom) for the Word automation fallbacks, requests + Pillow for search and previews. Wikimedia Commons and Openverse answer with no API keys. The build itself was pair-programmed in OpenCode, an open-source agent harness, with DevRelay's DEV tools.
The architecture follows the privacy claim:
the sentence is read from the clipboard and handed to the local Ollama server, so it never leaves the machine. Only the short query and the image
downloads cross the network.
The pipeline:
sentence --> local LLM --> "lighthouse in stormy sea"
|
+------------+------------+
v v
Wikimedia Commons Openverse (queried in parallel, merged)
+------------+------------+
v
candidate pictures (24 of them)
|
local CLIP scores each one against the whole sentence
v
8 tiles in a panel next to your cursor
(a show-more page reveals the rest of the pool)
The accuracy work lives in ezsearch_core.py:
a precision-first query ladder, Commons category mining when filename search is thin, artwork filtering by Commons categories, three layers of
de-duplication, and a licence gate that keeps NC/ND/fair-use images out before you ever see them.
64 offline tests pin the behaviour; the 20-sentence x 2-model benchmark pins the numbers above.
The lazy payoff
I recently had to search up pictures to paste in a word document and get a print of it.
Like normal, I googled them. In the process of trying to find an image that wasn't blurry, didn't have a watermark, or did not copy/paste into a document took me a whole hour. Just to paste 7-8 images.
So I tried my build, and even though I tend to be skeptical with my choices, for a work that just needs to get done and doesn't perfectionism. This build was a major success! I was able to reduce my time to just 10 minutes, taking roughly 30-45 seconds to show suggested images.
It was unbelievably useful and I was very happy to not have to decide which image to pick among hundreds. The model picked out the best search terms and the search engine ranked the best matches!!
I have shown exactly how it works in practicality in the demo video linked above, do check it out :))
Here's how the machine functions:
- ~13 s for the first search of a new subject on this laptop, with no GPU and no API.
- ~1 s for the same subject again: the pictures and the CLIP vectors are cached on disk.
- Zero network round trips for the sentence itself. Only the 2-5 word query leaves the machine.
| Stage (median, cold cache) | llama3.2:3b | gemma3:4b |
|---|---|---|
| LLM query build | 3.5 s | 4.5 s |
| Image search | 1.9 s | 1.9 s |
| Download + CLIP scoring | 8.1 s | 5.3 s |
| Sentence to picture | 13.4 s | 13.3 s |
So you trade about thirteen seconds of local compute for a thirty-second context switch. The seconds are similar; what you get back is the paragraph you did not lose. Even A sloth could do it.
Why Does Open Innovation Matter?
Privacy. The sentence we are writing - the draft, the research note, the thing you not published yet - is read from the clipboard and handed to a local Ollama server.
It never leaves the machine. The only thing that crosses the network is the 2-5 word query, and the requests for the pictures themselves.
Cost. $0 per use. A closed vision API bills every single selection, which is exactly the kind of cost that makes people stop doing the thing at all.
Swappable. EZSEARCH_MODEL points at any model you have pulled. I benchmarked two:
| Model | Query build (median) | Top 1 | Top 3 |
|---|---|---|---|
| Llama 3.2 3B (default) | 3.5 s | 14/20 | 16/20 |
| Gemma 3 4B | 4.5 s | 15/20 | 15/20 |
Twenty sentences, ranked in the search engine's order. The two are within noise on quality, and Gemma takes about a second longer per query, so Llama stays the default. EZSEARCH_MODEL=gemma3:4b is a one-line change if you want the other trade.
Offline-capable. Query building and CLIP scoring run with no internet at all. Only the image fetch needs a connection. If I lose my network halfway through a paragraph, EZsearch still finds me the right picture from the cache; any new pictures need the connection back.
Choosing the most relevant model for most accuracy
CLIP helps find images by understanding what a sentence means, rather than just matching keywords.
To test how well it works, I used 20 sentences:
12 that directly name the subject (like a dog) and 8 that describe it without using its name (like “the four-legged animal barked at the man in the blue coat”).
For each sentence, we fetch images once and compare their original search-engine ranking with their ranking after CLIP reorders them based on the full sentence.
An image counts as a correct result only if it shows the right subject and is an actual photograph, not a painting or engraving.
The goal was to see whether CLIP can bring the most relevant photographs closer to the top, especially when the sentence doesn't contain the exact keywords the search engine would normally look for.
| Ranking (20 sentences, two models) | Top 1 | Top 3 |
|---|---|---|
| Search engine order (keywords only) | 29/40 (72%) | 31/40 (78%) |
| CLIP re-ranked | 24/40 (60%) | 31/40 (78%) |
The results were not what I expected. The search engine's original ranking performed better than CLIP at finding the correct image in the first position, with 72% accuracy compared to CLIP's 60%. Both achieved 78% accuracy in the top three results. This meant CLIP did not improve the overall ranking, even when tested on sentences that described subjects without using their exact names.
One limitation is that the test judged images partly by their titles, which naturally favours keyword-based search. A photograph might perfectly match a sentence even if its filename doesn't describe it accurately. However, CLIP also failed to outperform the search engine on the paraphrased sentences designed to test this advantage, so there was no clear evidence that re-ranking helped.
Based on these results, I changed the app to keep the search engine's original image order instead of reordering images using CLIP.
CLIP still scores each image to display match scores and warn users when no strong match is found. Re-ranking can also be enabled again for further testing.
The key learning for me was that a feature shouldn't be kept just because it sounds clever. Testing showed that CLIP's re-ranking wasn't improving results, so I changed the app rather than making users rely on a feature that performed worse.
Run it yourself
git clone https://github.com/zish-s/EZsearch.git
cd EZsearch
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
ollama pull llama3.2:3b
python ezsearch.py
First run downloads the CLIP weights (~600 MB, cached afterwards). After that it starts instantly
and ranks entirely offline.
python -m pytest # 64 offline tests
python ezsearch.py --doctor
python ezsearch.py --search "a sentence" # headless
Windows is the tested platform.
My Agent Session
EZsearch was built across one long OpenCode session with a DeepSeek V4.1 Flash agent: diagnosing
why Word refused the paste, adding the automation fallbacks, then chasing "accuracy" down the query
ladder into Commons' category space. The transcript below is that session curated to the milestones
- the rest was pytest runs and PowerShell.
Prize Categories
Best Use of Gemma (featured category). Gemma 3 4B is a first-class local model in EZsearch,
not a demo stub: EZSEARCH_MODEL=gemma3:4b swaps the query model behind the same Ollama call, and
the benchmark in this post was run head-to-head against the default Llama 3.2 3B on 20 sentences.
Gemma built queries in 4.5 s vs 3.5 s, won one more top-1 hit (15/20 vs 14/20) and one fewer top-3
(15/20 vs 16/20). Llama stays the default because it is a full second faster; every Gemma number in
this post came out of the app.
No other partner technology is used in this build - it is a local desktop app with no hosted
database, deployment platform, voice or browser tooling - so the other categories are not claimed.
Solo entry, published by @zishs.

Top comments (1)
Hy how many Hackathon participate u?
I don't know about dev. I earliest joined it and builded first project using ai can u give more info about dev? Help me🙂