This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle
제가 만든 것 (What I Built)
푸네(Pune)의 동네 키라나 상점들은 저녁 내내 다음과 같은 WhatsApp 메시지를 받습니다:
bhaiya 2 kilo atta, 1 amul butter chhota, 6 ande, ek maggi, aur paneer bhi
상점 주인은 이 메시지를 읽고, 손으로 '파르치(parchi)'라는 종이 영수증을 작성하고, 가격표를 찾아보고, 계산기로 합계를 내고, 답장을 타이핑하여 자신의 UPI ID를 보냅니다. 그러자 다음 메시지가 도착하는데, 이번에는 마라티어입니다. 이것은 하루에 수십 번 하는 작은 일이지만, 실수할 때마다 그것은 그의 돈이거나 짜증 난 고객을 만드는 일이 됩니다.
Parchi는 이 작업을 상점의 자체 노트북에서 약 1초 만에 처리합니다:
- WhatsApp 메시지를 붙여넣거나 (또는 '채팅 내보내기(Export chat)' 파일을 열고 아무 메시지나 클릭합니다).
- Gemma 4가 힌글리시(Hinglish), 마라티어, 힌디어 또는 영어를 읽고 품목, 수량 및 크기 단어를 추출합니다.
- **순수 코드(Plain code)**는 각 품목을 상점의 자체 가격 목록과 일치시키고, 단위를 변환하며, 실시간 계산서(live bill)를 만듭니다.
- 상점 주인은 색상 코드가 지정된 목록을 확인합니다: 녹색은 일치했고, 노란색은 빠르게 살펴봐야 할 것 (매기(Maggi)는 어떤 크기?), 빨간색은 가격표에 없거나 품절입니다. 한 줄을 수정하는 것은 검색 가능한 선택기입니다:
누가 비용을 지불할까요: 오늘날 WhatsApp으로 주문을 받는 키라나 상점(kirana stores), 유제품 판매점(dairies), 도시락 및 식사 서비스(tiffin and mess services), 그리고 소규모 유통업체들입니다. 월별 소액의 수수료(예: ₹199)는 일주일 동안 잘못된 청구서 한 장의 비용보다 적으며, 주문 건당 발생하는 수수료가 없습니다.
데모 (Demo)
로컬에서 실행해 보세요 (설계상 카운터탑 앱이므로 호스팅되는 데모는 없습니다. 상점 Wi-Fi를 사용하는 휴대폰으로도 열 수 있습니다):
ollama pull gemma4:e4b
git clone https://github.com/YashAdake/parchi.git ; cd parchi
python -m venv .venv ; .\.venv\Scripts\Activate.ps1
...
코드 (Code)
Parchi
WhatsApp 주문 → 상점 자체 노트북에서 동네 키라나 상점을 위한 청구서.
고객이 _
- Ollama를 통한 Gemma 4 (
gemma4:e4b) 사용: 이 시스템은 메시지를 읽습니다. 요청은 Ollama의 구조화된 출력(structured output)과 JSON 스키마를 사용하므로, 답변은 항상 줄마다 {raw, item, qty, unit, size} 형식으로 나옵니다. 프롬프트는 고객이 실제로 사용하는 숫자 단어(dedh = 1.5, aadha/अर्धा = 0.5, paav kilo = 0.25 kg, darjan = 12)와 크기 단어(chhota/bada/लहान/मोठा)를 포함하며, 세 가지 짧은 예시 중 하나는 "감사합니다, 돈 보냈어요(thank you, paisa bhej diya)"이며 이는 반드시 *주문 아님(not an order)*으로 처리되어야 합니다. 사고 과정(Thinking)은 비활성화되어 있고, 온도는 0입니다. JSON이 사용할 수 없을 경우 한 번 재시도한 후 추측하는 대신 상점 주인에게 알립니다. 페이지가 열릴 때 모델을 예열하므로 첫 주문도 빠릅니다.
- 매처는 일반 Python으로 구현되었습니다. 먼저 정확한 별칭 매칭(ande → Eggs, kanda → Onion, दूध → Milk)을 수행하고, 그 다음으로는 양사 모두에서 수량 단어를 제거한 후
rapidfuzz를 사용합니다. 이 단어 제거 과정이 중요했습니다. 이전에는 "1 kg kaju katli"가 둘 다 "1 l"-과 유사한 텍스트를 포함하기 때문에 "Fortune Sunflower Oil 1 L"와 모호하게 매칭되는 문제가 있었습니다. 이제 유닛 테스트(unit test)가 이를 방지합니다.
- 포장 수학 계산: "1 litre doodh"는 1 L 포장을 선택하고, "2 litre"는 1 L 포장 두 개로 처리하며, "500 gm poha"는 0.5 kg으로 변환됩니다. 수량이 온전한 포장이 아닐 경우("paav kilo jeera" = 250 g, 100 g 단위 판매) 해당 줄은 노란색으로 바뀌고 두 가지 원터치 선택지(2 × 100 g = 200 g 또는 3 × 100 g = 300 g)가 제공됩니다. 이는 상점 주인만이 결정해야 할 사항이기 때문입니다.
- 금액 처리는
Decimal을 사용하며, 가격은 오직 가격 목록(price list)에서만 가져옵니다 (API는 요청에 포함된 모든 가격을 무시합니다). 총 금액은 루피 단위로 반올림되며, 이 반올림 값은 영수증과 답변에 표시됩니다. 화면의 실시간 계산 청구서는 브라우저가 아닌 서버에서 편집할 때마다 재계산되며, 일단 청구가 저장되면 항목들이 잠겨서 화면이 저장된 주문 내용과 다르게 표시될 수 없습니다.
- 재학습 없이 시각적으로 학습합니다: 상점 주인이 "2 nimbu"를 한 번 수정하면, 고객의 단어와 모델의 해석 모두가 기억되며, 가격 목록에서 해당 제품에 고객 단어로 나타납니다. 잘못된 수정은 삭제(delete) 한 번으로 되돌릴 수 있습니다.
UPI QR은 qrcode 라이브러리로 생성된 표준 upi://pay?pa=…&am=… 링크입니다. 결제 API도 없고 게이트웨이 수수료도 없습니다.
- FastAPI + SQLite + 인터넷 폰트나 CDN이 없는 단일 HTML 페이지로 구성되어 있어 전체 시스템이 오프라인에서 작동합니다. 다크 모드와 휴대폰 레이아웃도 기본으로 제공됩니다.
실제로 작동할까요?
scripts/eval.py는 제 RTX 5060 노트북에서 실제 모델과 매처(matcher)를 통해 Hinglish, Marathi, Hindi, 영어로 20개의 주문(34개 품목 라인)을 실행했습니다:
- 도움 없이 34개 품목 라인 모두 정확하게 처리되었으며 (올바른 제품과 올바른 수량), "감사합니다" 메시지도 올바르게 무시되었습니다.
- 주문당 1초 미만 (실행 간 중앙값 0.6~0.7초).
이 수치가 무엇을 의미하는지 명확히 하자면: 저는 Parchi를 구축하면서 26개 품목의 샘플 가격표를 기준으로 그 20개의 메시지를 작성했기 때문에, 이는 블라인드 테스트가 아니며 실제 고객들은 놓치는 표현들을 발견할 것입니다. 바로 그렇기 때문에 모든 라인은 청구서가 존재하기 전에 상점 주인에게 보여지며, 모델은 돈과 관련하여 결코 신뢰되지 않습니다. 41개의 단위 테스트(unit tests)는 매처, 계산된 청구서 금액, 가격 목록 및 UPI 유효성 검사, WhatsApp 내보내기 파서, 그리고 API를 다룹니다.
알려진 한계점: GST 세금 계산서가 아닌 주문 청구서를 작성합니다. 메시지 하나씩 청구하며, 현재는 텍스트 전용입니다.
오픈 이노베이션이 왜 중요할까요?
키라나 상점(kirana shop)의 경우, 폐쇄형 API는 사업을 세 가지 방식으로 망가뜨릴 것입니다.
- 고객 명단 자체가 상점입니다. 모든 주문에는 가구의 이름, 전화번호, 그리고 매주 구매하는 품목이 담겨 있습니다. 카운터 노트북에 오픈 웨이트(open-weight) 모델을 사용하면 이 정보가 누구의 서버로도 전송되지 않습니다.
- 마진이 매우 작습니다. 키라나 상점의 주문은 종종 수백 루피에 불과합니다. 하루에 수십 건의 소량 주문마다 API 호출당 비용을 지불하는 것은 도구가 청구할 수 있는 모든 수익을 잠식해 버립니다. 로컬 환경에서는 일회성 다운로드 이후 주문을 읽는 데 아무런 비용이 들지 않습니다.
- 인터넷 연결이 불안정합니다. Parchi는 모델을 다운로드한 후에는 연결이 필요하지 않습니다.
그리고 모델이 단순히 설정값(PARCHI_MODEL)이기 때문에, 상점은 특정 모델에 종속되지 않습니다. 더 나은 소규모 오픈 모델이 출시되면, ollama pull 한 번이면 됩니다. Gemma 4는 오디오 입력도 처리할 수 있어 다음 단계가 명확해집니다: 고객의 음성 메모에서 직접 청구하는 것입니다.
수상 부문 (Prize Categories)
- Gemma 활용 최우수: Gemma 4 (
gemma4:e4b)는 로컬에서 실행되며, Hinglish, Marathi 및 Hindi 주문에 대한 모든 언어 이해를 JSON 스키마로 제한하여 수행합니다.