<?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: Sandip Ghorai</title>
    <description>The latest articles on DEV Community by Sandip Ghorai (@sandip_ghorai_41d8afbbc81).</description>
    <link>https://dev.to/sandip_ghorai_41d8afbbc81</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%2F3872057%2Fbcc84ed4-6940-485b-956e-fe85cf7359a1.png</url>
      <title>DEV Community: Sandip Ghorai</title>
      <link>https://dev.to/sandip_ghorai_41d8afbbc81</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sandip_ghorai_41d8afbbc81"/>
    <language>en</language>
    <item>
      <title>My grandpa's recipes lived in WhatsApp voice memos, so I built him an offline AI cookbook</title>
      <dc:creator>Sandip Ghorai</dc:creator>
      <pubDate>Fri, 02 Oct 2026 05:59:03 +0000</pubDate>
      <link>https://dev.to/sandip_ghorai_41d8afbbc81/my-grandpas-recipes-lived-in-whatsapp-voice-memos-so-i-built-him-an-offline-ai-cookbook-3ci</link>
      <guid>https://dev.to/sandip_ghorai_41d8afbbc81/my-grandpas-recipes-lived-in-whatsapp-voice-memos-so-i-built-him-an-offline-ai-cookbook-3ci</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-2026"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Person I Built This For
&lt;/h2&gt;

&lt;p&gt;My thatha has been cooking sambar for about fifty years and has never once written a recipe down.&lt;/p&gt;

&lt;p&gt;What he does instead is send voice memos. Every few weeks one lands in the family group chat, four or five minutes long, usually recorded while he's standing over a pot. "Add a little hing. Not that much. A bit less. You'll know." Then someone replies with a thumbs up, the chat moves on, and the recipe sinks under forty photos of a cousin's baby.&lt;/p&gt;

&lt;p&gt;I've been scrolling back through that chat for a year looking for his sambar. This weekend I finally did something about it.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Thatha's Kitchen&lt;/strong&gt; takes one of his voice memos and turns it into a recipe card: title, ingredients, steps, and the little asides he's famous for ("don't rush the onions, they'll punish you").&lt;/p&gt;

&lt;p&gt;The part I care about most is that it doesn't guess. When he says "a handful of dal," the card says "a handful of dal" and adds a flag: &lt;em&gt;ask Thatha how big his hand is.&lt;/em&gt; Next time I'm at his place I can ask, and fix the card.&lt;/p&gt;

&lt;p&gt;It also exports everything to a printable PDF, because he will never open an app but he will happily read a paper cookbook.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code:&lt;/strong&gt; &lt;a href="https://github.com/your-username/thathas-kitchen" rel="noopener noreferrer"&gt;https://github.com/your-username/thathas-kitchen&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Everything is open source and runs locally on my laptop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;faster-whisper (large-v3, int8 on CPU)&lt;/strong&gt; for transcription. His memos switch between Tamil and English mid-sentence, so I let Whisper keep the original language instead of forcing English.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Qwen2.5 7B through Ollama&lt;/strong&gt; to pull the recipe out of the transcript as JSON.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlit&lt;/strong&gt; for a small page on top, and &lt;strong&gt;WeasyPrint&lt;/strong&gt; for the PDF.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The prompt does most of the work. I ask the model for ingredients, steps and tips, plus a fourth list called &lt;code&gt;unclear&lt;/code&gt; for anything vague or missing. My first version didn't have that list, and the model cheerfully invented "2 teaspoons of cumin" out of nowhere. For a dish my family has eaten for decades, that's a small betrayal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;faster_whisper&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;WhisperModel&lt;/span&gt;

&lt;span class="n"&gt;SYSTEM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You turn a transcript of an elderly cook talking into a recipe.
Return ONLY JSON with these keys:
title (string), ingredients (list of strings), steps (list of strings),
tips (list of strings), unclear (list of strings).
Rules:
- Use the speaker&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s own words for quantities (&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a handful&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a little&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;).
- NEVER invent a quantity, ingredient or step that was not said.
- If something is vague or missing, put a short question in `unclear`.
- Keep his personal asides in `tips`.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="n"&gt;whisper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WhisperModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;large-v3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;compute_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;int8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;transcribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;whisper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transcribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;initial_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sambar, rasam, kuzhambu, tamarind, hing, curry leaves, toor dal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&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="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;segments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;extract_recipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ollama&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;qwen2.5:7b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SYSTEM&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;transcript&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things that went sideways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whisper turned "kuzhambu" into something I can't print here. Giving it a vocabulary hint through &lt;code&gt;initial_prompt&lt;/code&gt; fixed most of it.&lt;/li&gt;
&lt;li&gt;The model kept "tidying up" his quantities into exact measurements. Adding the line "use the speaker's own words" stopped that.&lt;/li&gt;
&lt;li&gt;Long memos sometimes came back as broken JSON. Ollama's &lt;code&gt;format="json"&lt;/code&gt; mode fixed it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Open Source Mattered Here
&lt;/h2&gt;

&lt;p&gt;I want to be specific instead of just saying "privacy."&lt;/p&gt;

&lt;p&gt;These are recordings of my grandfather's voice. Some are the last ones where he's telling a story and cooking at the same time. I wasn't comfortable uploading them to a service I can't see inside of, so everything runs on my laptop and nothing leaves it.&lt;/p&gt;

&lt;p&gt;It also costs me nothing. There's no per-minute transcription bill and no API key to babysit, which matters when the project is a gift and not a startup.&lt;/p&gt;

&lt;p&gt;And I could swap models. I tried Llama 3.1 8B and Qwen2.5 7B on the same memo, and Qwen was better at keeping the &lt;code&gt;unclear&lt;/code&gt; list honest instead of filling gaps. I don't think I could have compared models like that, or pinned one, with a hosted API.&lt;/p&gt;

&lt;p&gt;To be fair, a big hosted model would probably have been more accurate on the rare Tamil words. I decided that wasn't worth giving up the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  What He Said
&lt;/h2&gt;

&lt;p&gt;I printed the first three recipes and gave him the pages on Sunday.&lt;/p&gt;

&lt;p&gt;He put his glasses on, held the pages at arm's length, and read the sambar one slowly. Then he said:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Who wrote this? It's exactly how I talk."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;He found one thing wrong, which was that I'd put the tamarind in too early, and he corrected it in pen on the page. Then he asked if I could do his rasam next.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;I want to add photos of the finished dishes, let my cousins record their own memos, and build a read-aloud mode so he can have a recipe played back to him.&lt;/p&gt;

&lt;p&gt;Thanks for reading. If someone in your family keeps their knowledge only in their head, go record them this weekend, even if you never build anything with it.--&amp;gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Turns my thatha's rambling voice memos into a printable family recipe book, 100% local with Whisper and Qwen. No cloud needed.</title>
      <dc:creator>Sandip Ghorai</dc:creator>
      <pubDate>Fri, 02 Oct 2026 05:57:01 +0000</pubDate>
      <link>https://dev.to/sandip_ghorai_41d8afbbc81/turns-my-thathas-rambling-voice-memos-into-a-printable-family-recipe-book-100-local-with-whisper-2i7e</link>
      <guid>https://dev.to/sandip_ghorai_41d8afbbc81/turns-my-thathas-rambling-voice-memos-into-a-printable-family-recipe-book-100-local-with-whisper-2i7e</guid>
      <description></description>
      <category>hf26challenge</category>
    </item>
  </channel>
</rss>
