<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ishita Sharmaa</title>
    <description>The latest articles on DEV Community by Ishita Sharmaa (@zishs).</description>
    <link>https://dev.to/zishs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4153002%2F5933be1b-a28f-4074-9547-195a31cc3ebf.jpg</url>
      <title>DEV Community: Ishita Sharmaa</title>
      <link>https://dev.to/zishs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zishs"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Ishita Sharmaa</dc:creator>
      <pubDate>Sat, 24 Oct 2026 20:22:26 +0000</pubDate>
      <link>https://dev.to/zishs/-587a</link>
      <guid>https://dev.to/zishs/-587a</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/zishs/im-too-lazy-to-google-search-an-image-and-paste-it-back-in-word-so-i-built-ezsearch-3omh" class="crayons-story__hidden-navigation-link"&gt;I’m Too Lazy to Google Search an Image and Paste it Back in Word, So I Built EZSearch&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/zishs/im-too-lazy-to-google-search-an-image-and-paste-it-back-in-word-so-i-built-ezsearch-3omh" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady Submission 🦥&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/zishs" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4153002%2F5933be1b-a28f-4074-9547-195a31cc3ebf.jpg" alt="zishs profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/zishs" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Ishita Sharmaa
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Ishita Sharmaa
                
                
              
              &lt;div id="story-author-preview-content-4898724" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/zishs" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4153002%2F5933be1b-a28f-4074-9547-195a31cc3ebf.jpg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Ishita Sharmaa&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/zishs/im-too-lazy-to-google-search-an-image-and-paste-it-back-in-word-so-i-built-ezsearch-3omh" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/zishs/im-too-lazy-to-google-search-an-image-and-paste-it-back-in-word-so-i-built-ezsearch-3omh" id="article-link-4898724"&gt;
          I’m Too Lazy to Google Search an Image and Paste it Back in Word, So I Built EZSearch
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hf26challenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hf26challenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hacktoberfest"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hacktoberfest&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/zishs/im-too-lazy-to-google-search-an-image-and-paste-it-back-in-word-so-i-built-ezsearch-3omh" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/zishs/im-too-lazy-to-google-search-an-image-and-paste-it-back-in-word-so-i-built-ezsearch-3omh#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              1&lt;span class="hidden s:inline"&gt;&amp;nbsp;comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            8 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>productivity</category>
      <category>sideprojects</category>
      <category>tools</category>
    </item>
    <item>
      <title>I’m Too Lazy to Google Search an Image and Paste it Back in Word, So I Built EZSearch</title>
      <dc:creator>Ishita Sharmaa</dc:creator>
      <pubDate>Sat, 24 Oct 2026 20:21:05 +0000</pubDate>
      <link>https://dev.to/zishs/im-too-lazy-to-google-search-an-image-and-paste-it-back-in-word-so-i-built-ezsearch-3omh</link>
      <guid>https://dev.to/zishs/im-too-lazy-to-google-search-an-image-and-paste-it-back-in-word-so-i-built-ezsearch-3omh</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/zish-s/EZsearch" rel="noopener noreferrer"&gt;https://github.com/zish-s/EZsearch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A sloth does not rush. It conserves its energy and lets the world come to it. &lt;br&gt;
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. &lt;/p&gt;


&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Imagine you're finished with your report, and then you remember you need to paste photos! &lt;br&gt;
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. &lt;/p&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;Hence, to simplify this tedious process I built EZSearch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcdmo8ndhxu0bks13ofqn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcdmo8ndhxu0bks13ofqn.png" alt="The EZsearch popup" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is how the popup looks like in action&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select a sentence anywhere - Word, Google Docs, PowerPoint, OneNote, a browser. &lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Ctrl+Shift+X&lt;/code&gt;. A small panel appears next to the cursor with up to eight matching pictures. &lt;/li&gt;
&lt;li&gt;Click one and it is pasted right in the document you were already
typing in.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ctrl+click opens the source of the picture. Right-click copies a finished attribution line.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The idea is simple, it was how I implemented the approach to come up with as accurate pics as possible!&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;A demonstration video showing exactly how you can use this build on your desktop:&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/Y8zUiisqFh8" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/zish-s/EZsearch" rel="noopener noreferrer"&gt;https://github.com/zish-s/EZsearch&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ezsearch.py&lt;/code&gt; - the hotkey, selection capture, popup-close-before-capture, paste dispatch&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ezsearch_core.py&lt;/code&gt; - query ladder, Commons/Openverse clients, licence and artwork filters,
de-duplication, CLIP scoring, on-disk cache&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ezsearch_ui.py&lt;/code&gt; - the popup: up to eight tiles, &lt;code&gt;+ show more&lt;/code&gt;, match bars, credit copy&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ezsearch_focus.py&lt;/code&gt; - the Win32 focus capture and restore that makes Word obey&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tests/&lt;/code&gt; and &lt;code&gt;benchmark.py&lt;/code&gt; - 64 offline tests, and the 20-sentence x 2-model benchmark&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MIT licensed. &lt;code&gt;python -m pytest&lt;/code&gt; runs the suite; &lt;code&gt;python ezsearch.py --search "..."&lt;/code&gt; runs headless.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This project was built using OpenCode&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Two open models do the slow jobs in EZsearch, and both run on the laptop:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Piece&lt;/th&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;Licence&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Llama 3.2 3B&lt;/strong&gt; via &lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Turns the sentence into a short, photographable query&lt;/td&gt;
&lt;td&gt;Llama 3.2 Community&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;CLIP ViT-B/32&lt;/strong&gt; via fastembed (ONNX)&lt;/td&gt;
&lt;td&gt;Scores each candidate against the &lt;em&gt;whole sentence&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Wikimedia Commons + Openverse&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Supply the pictures&lt;/td&gt;
&lt;td&gt;CC / public domain, per file&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 3 4B&lt;/strong&gt; is a one-env-var swap and was benchmarked against it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Around the models it is deliberately plain Python: Tkinter for the popup, &lt;code&gt;pynput&lt;/code&gt; for the global hotkey, &lt;code&gt;pywin32&lt;/code&gt; (&lt;code&gt;pythoncom&lt;/code&gt;) for the Word automation fallbacks, &lt;code&gt;requests&lt;/code&gt; + &lt;code&gt;Pillow&lt;/code&gt; for search and previews. Wikimedia Commons and Openverse answer with no API keys. The build itself was pair-programmed in &lt;strong&gt;OpenCode&lt;/strong&gt;, an open-source agent harness, with DevRelay's DEV tools.&lt;/p&gt;

&lt;p&gt;The architecture follows the privacy claim: &lt;br&gt;
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&lt;br&gt;
downloads cross the network.&lt;/p&gt;

&lt;p&gt;The pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; sentence --&amp;gt; local LLM --&amp;gt; "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)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  The accuracy work lives in &lt;code&gt;ezsearch_core.py&lt;/code&gt;:
&lt;/h3&gt;

&lt;p&gt;a precision-first query ladder, Commons category mining when filename search is thin, artwork filtering by Commons categories, three layers of&lt;br&gt;
de-duplication, and a licence gate that keeps NC/ND/fair-use images out before you ever see them.&lt;br&gt;
64 offline tests pin the behaviour; the 20-sentence x 2-model benchmark pins the numbers above.&lt;/p&gt;


&lt;h2&gt;
  
  
  The lazy payoff
&lt;/h2&gt;

&lt;p&gt;I recently had to search up pictures to paste in a word document and get a print of it.&lt;br&gt;
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.&lt;/p&gt;

&lt;p&gt;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. &lt;br&gt;
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!!&lt;/p&gt;

&lt;p&gt;I have shown exactly how it works in practicality in the demo video linked above, do check it out :))&lt;/p&gt;
&lt;h3&gt;
  
  
  Here's how the machine functions:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;~13 s&lt;/strong&gt; for the first search of a new subject on this laptop, with no GPU and no API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;~1 s&lt;/strong&gt; for the same subject again: the pictures and the CLIP vectors are cached on disk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero&lt;/strong&gt; network round trips for the sentence itself. Only the 2-5 word query leaves the machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage (median, cold cache)&lt;/th&gt;
&lt;th&gt;llama3.2:3b&lt;/th&gt;
&lt;th&gt;gemma3:4b&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LLM query build&lt;/td&gt;
&lt;td&gt;3.5 s&lt;/td&gt;
&lt;td&gt;4.5 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image search&lt;/td&gt;
&lt;td&gt;1.9 s&lt;/td&gt;
&lt;td&gt;1.9 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Download + CLIP scoring&lt;/td&gt;
&lt;td&gt;8.1 s&lt;/td&gt;
&lt;td&gt;5.3 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sentence to picture&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;13.4 s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;13.3 s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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. &lt;/p&gt;


&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Privacy.&lt;/strong&gt; 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. &lt;br&gt;
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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost.&lt;/strong&gt; $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. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Swappable.&lt;/strong&gt; &lt;code&gt;EZSEARCH_MODEL&lt;/code&gt; points at any model you have pulled. I benchmarked two:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Query build (median)&lt;/th&gt;
&lt;th&gt;Top 1&lt;/th&gt;
&lt;th&gt;Top 3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Llama 3.2 3B&lt;/strong&gt; (default)&lt;/td&gt;
&lt;td&gt;3.5 s&lt;/td&gt;
&lt;td&gt;14/20&lt;/td&gt;
&lt;td&gt;16/20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemma 3 4B&lt;/td&gt;
&lt;td&gt;4.5 s&lt;/td&gt;
&lt;td&gt;15/20&lt;/td&gt;
&lt;td&gt;15/20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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. &lt;code&gt;EZSEARCH_MODEL=gemma3:4b&lt;/code&gt; is a one-line change if you want the other trade.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Offline-capable.&lt;/strong&gt; 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.&lt;/p&gt;


&lt;h2&gt;
  
  
  Choosing the most relevant model for most accuracy
&lt;/h2&gt;

&lt;p&gt;CLIP helps find images by understanding what a sentence means, rather than just matching keywords. &lt;/p&gt;
&lt;h4&gt;
  
  
  To test how well it works, I used 20 sentences:
&lt;/h4&gt;

&lt;p&gt;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”). &lt;/p&gt;

&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;An image counts as a correct result only if it shows the right subject and is an actual photograph, not a painting or engraving. &lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ranking (20 sentences, two models)&lt;/th&gt;
&lt;th&gt;Top 1&lt;/th&gt;
&lt;th&gt;Top 3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Search engine order (keywords only)&lt;/td&gt;
&lt;td&gt;29/40 (72%)&lt;/td&gt;
&lt;td&gt;31/40 (78%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLIP re-ranked&lt;/td&gt;
&lt;td&gt;24/40 (60%)&lt;/td&gt;
&lt;td&gt;31/40 (78%)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One limitation&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Based on these results, I changed the app to keep the search engine's original image order instead of reordering images using CLIP.&lt;/strong&gt; &lt;br&gt;
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. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;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.&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Run it yourself
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/zish-s/EZsearch.git
&lt;span class="nb"&gt;cd &lt;/span&gt;EZsearch
python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
.venv&lt;span class="se"&gt;\S&lt;/span&gt;cripts&lt;span class="se"&gt;\a&lt;/span&gt;ctivate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
ollama pull llama3.2:3b
python ezsearch.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;First run downloads the CLIP weights (~600 MB, cached afterwards). After that it starts instantly&lt;br&gt;
and ranks entirely offline.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; pytest        &lt;span class="c"&gt;# 64 offline tests&lt;/span&gt;
python ezsearch.py &lt;span class="nt"&gt;--doctor&lt;/span&gt;
python ezsearch.py &lt;span class="nt"&gt;--search&lt;/span&gt; &lt;span class="s2"&gt;"a sentence"&lt;/span&gt;   &lt;span class="c"&gt;# headless&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Windows is the tested platform. &lt;/p&gt;


&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;EZsearch was built across one long OpenCode session with a DeepSeek V4.1 Flash agent: diagnosing&lt;br&gt;
why Word refused the paste, adding the automation fallbacks, then chasing "accuracy" down the query&lt;br&gt;
ladder into Commons' category space. The transcript below is that session curated to the milestones&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the rest was pytest runs and PowerShell.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag-agent-session"&gt;
  &lt;div class="agent-session-header"&gt;
    
    &lt;span class="agent-session-tool-icon-badge" title="OpenCode"&gt;
&lt;/span&gt;
    &lt;span class="agent-session-title"&gt;EZsearch: making a Windows paste-back hotkey find accurate pictures (curated milestones)&lt;/span&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-scroll"&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;EZsearch (my Windows hotkey that pastes openly licensed pictures from Commons/Openverse into the document): make it actually shippable. The picture sometimes never lands in Word, the pasted image eats my selected sentence, and the popup only ever shows one result. Also give me more variety in the grid.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;Two independent Word problems, both caused by synthetic input being ignorable. (1) Focus: Office keeps the caret in a child control, so SetForegroundWindow is not enough. Capture the focused child with GetGUIThreadInfo before the popup appears and restore it with AttachThreadInput + SetFocus on the child, detaching in finally. (2) COM: a synthetic Ctrl+C is as ignorable as a synthetic Ctrl+V, so both halves get an automation path through Word itself - read ActiveWindow.Selection, collapse it to its end (which is why the picture appends after the sentence instead of eating it), and paste with Selection.Paste(). COM must be initialised per thread with pythoncom.CoInitialize. Also moved the default hotkey off Ctrl+Alt+F, which is Word's Insert Footnote accelerator, to Ctrl+Shift+X.&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-pytest"&gt;pytest&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;python -m pytest&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;python -m pytest&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;62 passed&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;This is what it's supposed to show - Chandigarh roundabouts. The grid should feel topical for "The roundabouts in chandigarh", not generic roundabouts from anywhere.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Commons has zero file hits for "roundabout chandigarh" and no matching categories by name; the topical reservoir is category space ("Road bridges in Chandigarh", "National highways in Chandigarh"). Rewrote resolve_query to be precision-first: the query as given and the de-filler variant lead the grid; Commons category mining fills a thin pool; the closest broader phrasing tops the pool up behind the topical head so Show more still has pages. Openverse got a longer timeout, one retry and a one-minute cooldown instead of ten. Same sentence: 1 candidate before, 24 after.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-probechandigarhpy"&gt;probe_chandigarh.py&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;headless pipeline on 'The roundabouts in chandigarh'&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;headless pipeline on 'The roundabouts in chandigarh'&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;resolved 'roundabout chandigarh' candidates=24 (Wikimedia Commons 15, Openverse 9)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;The current working level is good. Refine the README and the DevPost draft, and leave space under a Demo heading for screenshots.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Synced both documents with the working app: Ctrl+Shift+X and the Insert Footnote story, up to eight tiles plus show more, sentence-survives-paste, the precision-first ladder and category mining, the Word automation fallbacks, 64 offline tests, the Openverse timeout knob. Added a Demo section with three placeholders in README, DevPost.md and the staged DEV draft 4898724.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Write another new dev post draft, from your understanding of the project, for the Week 3 submission.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Created a second, differently-shaped draft: "EZsearch: slow on purpose, steady on your sentence". Argument-first, with three decisions I would defend in review (reranking cut on measurement, the licence gate, the Win32 edges where the demo never looks) and a compressed field-notes bug log. Saved locally as DevPost-alt.md and staged on DEV as draft 4911997.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;The idea is simple, it was how I implemented the approach to come up with as accurate pics as possible. Justify this sentence with a few pointers. Very few.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Four pointers: precision-first query ladder; filter before scoring (artwork categories, work-key and 64-bit hash de-duplication); licence gate before display; measured instead of assumed (search order beat CLIP reranking 29/40 vs 24/40 on top-1, so reranking was cut). Accuracy came from the pool, not from a bigger model.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Give me content for the DEV post headings: Prize Categories, My Agent Session, Code, How I Built It.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Prepared the four submission sections and saved this curated session so it can be embedded with the agent_session Liquid tag.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-footer"&gt;
    &lt;span class="agent-session-meta"&gt;
        12 of 12 messages
    &lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;






&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Best Use of Gemma&lt;/strong&gt; (featured category). Gemma 3 4B is a first-class local model in EZsearch,&lt;br&gt;
not a demo stub: &lt;code&gt;EZSEARCH_MODEL=gemma3:4b&lt;/code&gt; swaps the query model behind the same Ollama call, and&lt;br&gt;
the benchmark in this post was run head-to-head against the default Llama 3.2 3B on 20 sentences.&lt;br&gt;
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&lt;br&gt;
(15/20 vs 16/20). Llama stays the default because it is a full second faster; every Gemma number in&lt;br&gt;
this post came out of the app.&lt;/p&gt;

&lt;p&gt;No other partner technology is used in this build - it is a local desktop app with no hosted&lt;br&gt;
database, deployment platform, voice or browser tooling - so the other categories are not claimed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Solo entry, published by &lt;a href="https://dev.to/zishs"&gt;@zishs&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hf26challenge</category>
      <category>hacktoberfest</category>
      <category>opensource</category>
      <category>devchallenge</category>
    </item>
    <item>
      <title>I built an agent that files your cyber complaints for you, on the sites that are helpful and you weren't aware of</title>
      <dc:creator>Ishita Sharmaa</dc:creator>
      <pubDate>Tue, 20 Oct 2026 18:29:53 +0000</pubDate>
      <link>https://dev.to/zishs/i-built-an-agent-that-files-your-cyber-complaints-for-you-on-the-sites-that-are-helpful-and-you-1860</link>
      <guid>https://dev.to/zishs/i-built-an-agent-that-files-your-cyber-complaints-for-you-on-the-sites-that-are-helpful-and-you-1860</guid>
      <description>&lt;p&gt;This idea was inspired by one of my favourite comedian's recent show, no matter how much comedy there was that incident shouldn't happen to anyone, and it shouldn't become less of a concern just because the gender is different. &lt;/p&gt;

&lt;p&gt;Victims are often overwhelmed and nobody tells them where to look for help. What we get instead is a search engine, a pile of government pages with elongated filling of forms, and the knowledge that you should probably post screenshots somewhere. Then you give up, because it is 11pm and you are scared, exhausted and feel lost.&lt;/p&gt;

&lt;p&gt;Hence I wanted to build a site which could help people remain aware and have control over their identity online through my website - ReclaimYourNet. &lt;br&gt;
It aims to primarily protect people, especially women from cyber bullying and harassment by providing them a one single website which understands what their specific problem is and tells them which relevant sites (universal, country specific, state specific) they can use to register complaints or take down morphed pics. &lt;/p&gt;

&lt;p&gt;The triage runs local, nothing is stored when you close the tab - preserving the identity of the user. The local model works out what kind of harm it is and how urgent it is based on which it gives out its recommendations and recommended sites; a TinyFish web agent then goes to the live web, finds the official portal for every route — including the police station with jurisdiction over your own city — reads the real form as it exists today, and fills it in. You review every value through a monitor on our website and approve it to be submitted, the agent then returns a reference number, and an agent keeps checking whether the content actually came down. it keeps watch and notifies you if it actually came down or has resurfaced. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;One description of what happened. Every report you need to file, on the right portal, with the right evidence, and with proof that you filed it.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Live: &lt;strong&gt;&lt;a href="https://reclaim-your-net.vercel.app" rel="noopener noreferrer"&gt;https://reclaim-your-net.vercel.app&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Github Repo: &lt;strong&gt;&lt;a href="https://github.com/zish-s/TinyFish-a-thon" rel="noopener noreferrer"&gt;https://github.com/zish-s/TinyFish-a-thon&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;You type/dictate your problem or select from an existing one if you're unsure where to start:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/0JgVRl_4avU" rel="noopener noreferrer"&gt;Check out the demonstration video to understand how the site works!&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Someone made a fake Instagram account using my photo and my college ID and is asking my friends to send me 500 rupees as a gift. They also posted my phone number on the page."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Here is a demonstration video to understand the project better&lt;/em&gt;&lt;br&gt;
  &lt;iframe src="https://www.youtube.com/embed/N0wLqMg0-Yc" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;How it proceeds:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You describe it once.&lt;/strong&gt; Typed, or dictated from the mic, in your own words. A small local model works out what kind of harm it is and how urgent it is ("This one is time-critical", and why). Typed text never leaves the site itself; if you dictate, it is your browser's own speech recognizer doing the listening, and only the finished words reach the model. Your personal details stay masked until you reveal them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It asks for the facts once, not six times.&lt;/strong&gt; Your particulars, the date, the place, the account used: collected at intake, shown back to you in one editable place, and reused for every form it files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It plans the routes.&lt;/strong&gt; The case page opens with "Here is where this needs to be reported": the places to start with, plus more you can arm afterwards, grouped into Remove it from the platform · Create a legal record · Stop the money · Take it down before it spreads · Shrink the blast radius. Each route shows the reason it applies and its clock ("Money can usually only be frozen if reported within 24 hours of the transaction"), and a "Still missing" panel names every gap with one action to close it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It finds the live portals.&lt;/strong&gt; A TinyFish Search run, per country, at the moment you file. Not a hard-coded list: results are scored for officialness, runner-up pages show as "Also found live", and if nothing trustworthy turns up the route honestly says "no page found - Look again" rather than guessing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It reads the real form.&lt;/strong&gt; Press "Read the form" and a TinyFish web Agent opens the actual page and returns the fields it has today - labels, required flags, dropdown options, the evidence it wants - through a validated JSON schema. Forms change; the agent follows them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It pre-fills and tells you exactly what it did.&lt;/strong&gt; A banner on the route says "Filled 2 of 3 - 1 still needs you", with the missing field named. Anything genuinely yours sits in the route as "needs your input" until you supply it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;You watch, you approve, it files.&lt;/strong&gt; "What the agent did" shows the agent's own browser, live, plus a plain-language log of every step. "Fill it" always stops before Submit; "Fill &amp;amp; submit" is a separate, deliberate press. Once filed, the route flips to filed and the reference number sits on it as a chip.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It proves it.&lt;/strong&gt; Every page read, every reference and every filed value goes into a SHA-256 hash chain (each item printing its own hash and the previous one), attachments become annexures you can withdraw, and "Download case file (PDF)" builds the printable record you sign and hand to a police station, a bank or a court.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;It follows up.&lt;/strong&gt; Press "Start watching" and a TinyFish Monitor re-checks the reported URL on a schedule, telling you whether the content actually came down - or quietly came back.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The part I am actually proud of
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Nothing about the world is hard-coded.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The obvious implementation is a JSON file of "Instagram reports go here, cybercrime.gov.in is here, here is the form schema". It is also wrong within a month, because portals move, forms change, and the details differ per country.&lt;/p&gt;

&lt;p&gt;So the channel catalogue in the code is only a &lt;em&gt;fallback&lt;/em&gt;. The real work is done by a web agent that goes and looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// apps/api/src/pipeline/orchestrator.ts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;goal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You are helping a victim file a report. Read a real reporting form exactly.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;`Start page: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;targetUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1. Open the page. Follow any link to the reporting / complaint / abuse form.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2. If you hit a login wall, do NOT log in. Set has_form to false.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3. For EVERY field record: label, name, required, kind, and for a dropdown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;   the visible option values.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4. Record the report categories and any evidence the form asks for.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5. Do NOT type into the form. Do NOT submit anything.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;targetUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;goal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;outputSchema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ARCHAEOLOGY_SCHEMA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// TinyFish validates the schema first&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when you approve, the &lt;em&gt;same&lt;/em&gt; agent types the values and submits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;submitGoal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The form is now filled. Click the final Submit button exactly once.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;`Current page: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;targetUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Read the confirmation text and capture any reference number or case id.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The best part for the demo is that TinyFish hands back a &lt;strong&gt;live stream of the agent's own browser&lt;/strong&gt;. I embed that &lt;code&gt;streaming_url&lt;/code&gt; in the app, so you literally watch the agent open the portal, find the right form, and type into it. It is the difference between "an AI did something" and "I can see exactly what it did".&lt;/p&gt;

&lt;h3&gt;
  
  
  Jurisdiction is not a detail
&lt;/h3&gt;

&lt;p&gt;A FIR can only be registered by the police station with jurisdiction over where you live. If you type "Gurugram", the agent finds &lt;code&gt;gurgaon.haryanapolice.gov.in/cyber-crime&lt;/code&gt; - the district's own page - instead of a generic national portal. A hard-coded list can never do that, and it is the difference between a useful pointer and a dead end.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part I am not proud of (yet)
&lt;/h2&gt;

&lt;p&gt;The first version of the classifier was a Naive Bayes model, and it was &lt;strong&gt;fundamentally wrong for multi-label problems&lt;/strong&gt;. A generative model has to treat every token as evidence against every class it does not own, so "a fake account using my photo asking for money" produced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;financial_fraud  p=0.024   &amp;lt;- technically the top label
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix was to move to a discriminative model - one-vs-rest logistic regression - and to stop pretending that a 223-example hand-labelled corpus can be pushed much further. The honest numbers, from a reproducible 5-fold cross-validation (&lt;code&gt;npm run eval&lt;/code&gt;):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Macro F1&lt;/td&gt;
&lt;td&gt;0.62&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Macro precision&lt;/td&gt;
&lt;td&gt;0.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Macro recall&lt;/td&gt;
&lt;td&gt;0.83&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Top-1 label correct&lt;/td&gt;
&lt;td&gt;89.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I tuned it to over-predict, on purpose. In this domain a &lt;strong&gt;missed label means a missed reporting route&lt;/strong&gt;, and an extra channel costs a victim 20 seconds while a missing one can cost them their money.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decisions and learning I came across while working on this:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A missing reporting route is worse than a useless one.&lt;/strong&gt; The single most valuable screen is not the list of things to do, it is the list of things you have &lt;em&gt;not&lt;/em&gt; covered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Pre-emptive" beats "reactive".&lt;/strong&gt; Take It Down, StopNCII, Takedown and RemoveHer let you register a photo &lt;em&gt;before&lt;/em&gt; it is misused and have it pulled down later - including AI-morphed copies. Almost nobody knows these exist. ReclaimYourNet surfaces them at the moment they are useful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split "fill" from "submit".&lt;/strong&gt; Two approvals instead of one, and the agent never gets to decide on its own what gets sent in a victim's name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make the model say no.&lt;/strong&gt; The agent fills everything it can and only leaves a genuinely required field empty. That gap is shown to the user, not hidden. The blank field in the UI is a feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A serverless platform forgets between requests.&lt;/strong&gt; My first deployment returned 404 for every case. The fix was to stop treating the server as stateful: the client carries the case, and each agent run is one request that stays open and streams its events back on the same connection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never store what someone told you.&lt;/strong&gt; There is no account and no database. A report lives in the memory of the app and dies with the tab. The only copy that outlives the session is the PDF you download yourself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure the credits.&lt;/strong&gt; TinyFish Search and Fetch are free within the daily allowance; the Agent is $0.016/step; a Monitor is $0.005/run. A full report costs about $0.30-0.60 (Rs 25-50), which is what makes a Rs 499/month Pro tier work.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Live: &lt;strong&gt;&lt;a href="https://reclaim-your-net.vercel.app" rel="noopener noreferrer"&gt;https://reclaim-your-net.vercel.app&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Or run it yourself:&lt;/p&gt;

&lt;p&gt;github: &lt;strong&gt;&lt;a href="https://github.com/zish-s/TinyFish-a-thon" rel="noopener noreferrer"&gt;https://github.com/zish-s/TinyFish-a-thon&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install
cp&lt;/span&gt; .env.example .env      &lt;span class="c"&gt;# add TINYFISH_API_KEY&lt;/span&gt;
npx cloudflared tunnel &lt;span class="nt"&gt;--url&lt;/span&gt; http://localhost:4000   &lt;span class="c"&gt;# so the cloud browser can reach you&lt;/span&gt;
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The demo forms are clones of the real ones, so the agent can be driven end-to-end without touching a live platform. The repo has the architecture, the evaluation script, the pitch deck and a timed demo script.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would build next
&lt;/h2&gt;

&lt;p&gt;Authenticated filing (a TinyFish browser profile + vault so the agent files on logged-in platforms as &lt;em&gt;you&lt;/em&gt;), and a public channel graph so every case makes the next one's routing better.&lt;/p&gt;




</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>showdev</category>
      <category>development</category>
    </item>
  </channel>
</rss>
