<?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: Tanay</title>
    <description>The latest articles on DEV Community by Tanay (@tanay_singh_1005).</description>
    <link>https://dev.to/tanay_singh_1005</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%2F4158034%2F440d8d04-4878-4135-8bb5-798a615ff6a6.jpg</url>
      <title>DEV Community: Tanay</title>
      <link>https://dev.to/tanay_singh_1005</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tanay_singh_1005"/>
    <language>en</language>
    <item>
      <title>Order Taker: turning "kal subah 2 box brownies" into real orders with open AI</title>
      <dc:creator>Tanay</dc:creator>
      <pubDate>Sun, 04 Oct 2026 12:55:48 +0000</pubDate>
      <link>https://dev.to/tanay_singh_1005/order-taker-turning-kal-subah-2-box-brownies-into-real-orders-with-open-ai-5h5h</link>
      <guid>https://dev.to/tanay_singh_1005/order-taker-turning-kal-subah-2-box-brownies-into-real-orders-with-open-ai-5h5h</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;Picture the home baker down your street. They take every order on WhatsApp:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Priya:&lt;/strong&gt; Hi aunty! Can I get 1 kg chocolate truffle cake for Sunday evening? Eggless please 🙏&lt;br&gt;
&lt;strong&gt;Priya:&lt;/strong&gt; Write "Happy Birthday Arjun" on it&lt;br&gt;
&lt;strong&gt;Rahul Bhaiya:&lt;/strong&gt; 2 box brownies kal subah, address 14B Lakeview Apts&lt;br&gt;
&lt;strong&gt;Rahul Bhaiya:&lt;/strong&gt; sorry make it 3 boxes&lt;br&gt;
&lt;strong&gt;Meena:&lt;/strong&gt; Good night aunty 😊&lt;br&gt;
&lt;strong&gt;Sneha:&lt;/strong&gt; 12 cupcakes vanilla + 6 red velvet, Saturday 4pm pickup. My number 98450 12345&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's six messages in a mix of English and Hindi. There's an edit ("make it 3 boxes"), relative dates ("kal", "Sunday"), a pickup, and someone just saying good night. Multiply that by a busy festival week and orders get missed, quantities get mixed up, and customers keep messaging "aunty, is my cake ready?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Order Taker&lt;/strong&gt; is built for that person: someone who is great at baking, not at spreadsheets, and who runs the whole business from one WhatsApp chat.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The shop owner&lt;/strong&gt; pastes (or uploads) the WhatsApp chat. A small team of AI helpers reads it, and a friendly &lt;em&gt;"What's happening"&lt;/em&gt; box explains each step in plain English as it goes. Each order shows up as a card to &lt;strong&gt;Accept, Edit or Discard&lt;/strong&gt;, with anything odd flagged: &lt;em&gt;"Delivery or pickup? No address was given."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Accepted orders move along with one big thumb-sized button: &lt;strong&gt;Received → Confirmed → Preparing → Ready → Delivered.&lt;/strong&gt; There's a per-day &lt;strong&gt;prep list&lt;/strong&gt; ("3 boxes brownies, 2 kg chocolate cake") and a CSV export.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customers&lt;/strong&gt; log in from their phone with their number and a PIN that the shop sends them on WhatsApp. They see a progress bar for their order, and they can &lt;strong&gt;change or cancel it in the app&lt;/strong&gt;. Before the shop confirms an order, changes apply straight away. After that, they go to the shop owner as a request to approve, shown old → new.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole thing runs &lt;strong&gt;on the shop owner's laptop&lt;/strong&gt;. Customers' phones reach it over the same Wi‑Fi.&lt;/p&gt;

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


&lt;div class="ltag__huggingface"&gt;
  &lt;iframe src="https://midking1234-order-taker.hf.space" title="Hugging Face Space" width="100%" height="600"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;


&lt;p&gt;The app is deliberately &lt;strong&gt;not&lt;/strong&gt; hosted anywhere: customer names, phone numbers and home addresses never leave the laptop. To try it yourself, follow the 3-step setup in the README with &lt;code&gt;samples/sample_chat.txt&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update: from one laptop to a fully deployed app&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Keeping it on the laptop was a choice for this first version, not a limit of the design. The same code can become a normal hosted web app that customers open from anywhere, not just on the shop's Wi‑Fi:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The web app&lt;/strong&gt; is a standard FastAPI service. Every machine-specific setting is already an env var (&lt;code&gt;ORDER_DB&lt;/code&gt;, &lt;code&gt;ORDER_PORT&lt;/code&gt;, &lt;code&gt;ORDER_PUBLIC_URL&lt;/code&gt;, &lt;code&gt;OLLAMA_URL&lt;/code&gt;), so it can run on Render, Fly.io or a small VPS behind HTTPS with secure-only cookies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The data&lt;/strong&gt; moves from one SQLite file to a managed Postgres database. The numbered migrations are plain SQL, so they carry over.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The AI stays open.&lt;/strong&gt; &lt;code&gt;OLLAMA_URL&lt;/code&gt; can point to an open-weight model on a GPU server you control, or even back to the shop's own laptop through a private tunnel. Then the model still runs on the owner's machine, while customers get a public link.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next steps after that:&lt;/strong&gt; WhatsApp Business webhooks so orders arrive automatically instead of being pasted, an SMS or WhatsApp one-time code instead of a shop-issued PIN, and one install serving many home businesses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trade-off is honest: once it's hosted, customer data lives on a server instead of only on the laptop. That's why the project's specs treat it as a deliberate change to its "local-first" rule. The owner should choose it on purpose, not have it happen by accident.&lt;/p&gt;
&lt;/blockquote&gt;

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


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Tanay3484" rel="noopener noreferrer"&gt;
        Tanay3484
      &lt;/a&gt; / &lt;a href="https://github.com/Tanay3484/order-taker" rel="noopener noreferrer"&gt;
        order-taker
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Turn messy WhatsApp orders into a clean order board for home bakers, with local multi-agent AI (Ollama) so customer data never leaves the laptop.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tbody&gt;
  &lt;tr&gt;
    &lt;th&gt;title&lt;/th&gt;
    &lt;td&gt;Order Taker&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;emoji&lt;/th&gt;
    &lt;td&gt;🧁&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;colorFrom&lt;/th&gt;
    &lt;td&gt;pink&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;colorTo&lt;/th&gt;
    &lt;td&gt;yellow&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;sdk&lt;/th&gt;
    &lt;td&gt;docker&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;app_port&lt;/th&gt;
    &lt;td&gt;7860&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;pinned&lt;/th&gt;
    &lt;td&gt;false&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;license&lt;/th&gt;
    &lt;td&gt;mit&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;short_description&lt;/th&gt;
    &lt;td&gt;Local AI agents turn WhatsApp orders into a bakery board&lt;/td&gt;
  &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Order Taker 🧁&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Turns messy WhatsApp order messages into clean orders for a small home business. The shop owner pastes the chat, a team of small AI helpers reads it, and customers can log in from their phones to see where their order is.&lt;/p&gt;
&lt;p&gt;Everything runs on the shop owner's laptop with an open-weight model via &lt;a href="https://ollama.com" rel="nofollow noopener noreferrer"&gt;Ollama&lt;/a&gt;, so customer names, numbers and addresses never leave the machine.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What it does&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shop owner&lt;/strong&gt; (admin): paste or upload the WhatsApp chat. Watch a plain-English "What's happening" feed while it's read. Check, edit and accept each order, then move it along: Received → Confirmed → Preparing → Ready → Delivered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customers&lt;/strong&gt;: log in with their phone number and a PIN the shop sends…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Tanay3484/order-taker" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


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

&lt;p&gt;&lt;strong&gt;Open-weight model, running locally:&lt;/strong&gt; &lt;code&gt;qwen2.5:7b&lt;/code&gt; through &lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt;, on an ordinary laptop with a 4 GB GTX 1650. Every model call uses Ollama's structured output with a JSON schema, and the result is validated with Pydantic before anything is stored.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-agent intake, without a framework.&lt;/strong&gt; The flow is a fixed pipeline, so plain &lt;code&gt;asyncio&lt;/code&gt; was enough (about 150 lines), and it let me attach a progress message to every step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pasted chat ─▶ Master (plain code): split by person, skip messages already read,
                spot pure "good night / thank you" without any AI
                  │  one track per person, all at the same time
                  ├─▶ [Sorter, small model*] ─▶ [Extractor, 7B] ─▶ [Checker, plain code] ─▶ draft card
                  └─▶ …
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Master&lt;/strong&gt; splits the chat by sender and skips messages it has already handled, so you can paste the &lt;em&gt;whole&lt;/em&gt; chat every evening and only new messages get read.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extractor&lt;/strong&gt; (one per person) sees only that person's messages and their &lt;em&gt;open orders&lt;/em&gt;. That's how "sorry make it 3 boxes" becomes a change to the existing order instead of a duplicate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Checker&lt;/strong&gt; is just rules: missing date, missing address/pickup, missing phone, duplicates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The AI proposes, a human decides.&lt;/strong&gt; Nothing becomes a real order until the shop owner taps Accept.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The most interesting lesson: let code do what code is good at.&lt;/strong&gt; On the first real run, the 7B model read Priya's "Sunday" as a &lt;strong&gt;Thursday&lt;/strong&gt; and Sneha's "Saturday" as a &lt;strong&gt;Wednesday&lt;/strong&gt;. Small models are bad at calendar arithmetic. So now the model only &lt;em&gt;copies&lt;/em&gt; what the customer wrote ("Sunday", "kal", "5th Oct"), and a small lookup table in Python turns it into a date, counted from when the message was sent. Same with phone numbers: a regex finds "My number 98450 12345" every time; the model didn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Honest numbers&lt;/strong&gt; on my laptop (the model only partly fits on the GPU, so Ollama runs one request at a time):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Old (one big call)&lt;/th&gt;
&lt;th&gt;Multi-agent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First order ready to check&lt;/td&gt;
&lt;td&gt;~41 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~20 s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Whole chat done&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~41 s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~55 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dates, phone, chit-chat correct on the sample&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So on modest hardware the win is &lt;em&gt;time to first order&lt;/em&gt; and &lt;em&gt;correctness&lt;/em&gt;, not total time. On a machine with more VRAM and &lt;code&gt;OLLAMA_NUM_PARALLEL&lt;/code&gt; set, the per-person tracks really do run side by side. The repo includes &lt;code&gt;scripts/bench_intake.py&lt;/code&gt; so anyone can measure their own machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No "Processing…" spinner.&lt;/strong&gt; A spinner that sits there for a minute makes non-technical users think the app is broken. Instead, the progress box narrates every step: &lt;em&gt;"Meena is just chatting. Nothing to order."&lt;/em&gt;, &lt;em&gt;"Still working on Priya's messages, nearly there…"&lt;/em&gt;, &lt;em&gt;"All done in 53 seconds: 3 things to check, 1 just chatting."&lt;/em&gt; These messages come from fixed templates, never from raw model output. A test fails the build if any of them contains words like "JSON", "API", "token" or "Ollama".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spec Driven Development.&lt;/strong&gt; Before writing code, I wrote a short constitution (local-first, plain English, AI proposes / human decides, mobile-first) and five feature specs with numbered acceptance criteria. Every one of the 154 tests names the criterion it covers (&lt;code&gt;INT-21&lt;/code&gt;, &lt;code&gt;TRK-23&lt;/code&gt;…). When the real model proved a spec wrong (the dates!), I updated the spec first and then the code. It's all in &lt;a href="https://github.com/Tanay3484/order-taker/tree/main/specs" rel="noopener noreferrer"&gt;&lt;code&gt;specs/&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Stack: FastAPI, SQLite, Jinja2, a little vanilla JS, Server-Sent Events for the live feed. No CDNs, no external calls.&lt;/p&gt;

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

&lt;p&gt;For this user, a closed API wasn't really an option:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy:&lt;/strong&gt; these chats are full of customers' phone numbers and home addresses. With an open-weight model running locally, &lt;strong&gt;none of it leaves the laptop&lt;/strong&gt;. There's no third-party processor and nothing to explain to customers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; a home bakery might get 40 messages a day. Any per-token bill is real money for a tiny business. Local inference costs nothing per message.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It works when the internet doesn't:&lt;/strong&gt; the app and the model run on the laptop, and phones only need the home Wi‑Fi.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control:&lt;/strong&gt; I could look at exactly where the model failed (weekday maths, optional JSON fields) and design around it. When I needed every field filled in, I tightened the JSON schema sent to Ollama. Swapping to another model is one env var (&lt;code&gt;ORDER_MODEL=llama3.2&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And because the app is MIT-licensed, any other home business can run it, and any developer can add their language's words for "tomorrow".&lt;/p&gt;

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

&lt;p&gt;I built this pair-programming with &lt;strong&gt;Claude Code&lt;/strong&gt; as my coding agent, using a spec-first workflow: we agreed the constitution and specs together, then it implemented feature by feature against them and ran the real model to check its own work.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
  </channel>
</rss>
