dev.to

My mom reads Bengali, not English. So I built her a reader that catches scams, on open-weight Gemma.

벵골어만 읽는 어머니를 위해 만든 사기 탐지 문서 리더

Chithi는 문서 사진을 읽어 벵골어를 포함한 인도 22개 공용 언어로 설명하고, 사기 메시지를 탐지하는 오픈 웨이트 Gemma 기반 앱입니다. 저자는 가정용 노트북에서 사진을 처리하고 규칙 기반 안전장치와 고정 경고 문구를 더해 개인정보 보호와 사기 대응을 함께 설계했습니다.

AI 요약

벵골어를 읽는 어머니와 조부모가 은행 안내문이나 사기 문자를 이해하려면 가족에게 사진을 보내 물어봐야 했습니다. 저자는 이 과정을 줄이려고 Chithi를 만들었습니다. 휴대전화로 종이나 화면을 촬영하면 문서 종류, 해야 할 일, 금액과 기한을 읽어주고 사기 가능성도 알려줍니다. 벵골어로 시작한 앱은 인도 헌법 부칙에 지정된 22개 언어와 영어를 지원합니다.

구성과 실행 방식

휴대전화의 카메라를 쓰는 PWA(Progressive Web App)가 집 안 Wi-Fi로 사진을 노트북에 보냅니다. 노트북에서는 Bun 서버가 Ollama를 거쳐 Gemma 3 4B 비전 모델을 실행합니다. 답변은 원문, 문서 종류, 두 줄 설명, 조치, 금액, 기한, 위험도(safe·caution·scam)를 담은 JSON으로 받습니다. Ollama의 JSON Schema 모드를 사용해 응답 형식을 고정합니다.

음성 합성은 휴대전화에 내장된 TTS(Text-to-Speech)를 사용하므로 오프라인에서도 작동합니다. 기기에 해당 언어 음성이 없으면 같은 문자 체계를 읽는 다른 언어 음성을 대신 씁니다. 마이틸리어는 힌디어 음성으로, 콘카니어는 마라티어 음성으로 읽습니다. 앱은 큰 글씨와 버튼을 사용하고, 우르두어·카슈미르어·신디어에는 오른쪽에서 왼쪽으로 쓰는 레이아웃을 적용합니다.

모델 오류를 안전장치로 다루기

저자는 4B 모델의 답을 그대로 사용자에게 보여주기보다 실패 사례를 찾아 제약을 추가했습니다. 가짜 SBI KYC 문자에서 모델은 사기라고 판정하고도 문자에 적힌 사기범의 전화번호로 연락하라고 안내했습니다. 이후 사기 판정이 나오면 모델이 조언을 만들지 못하게 했습니다. 대신 각 언어로 사람이 작성한 고정 문구를 보여주며 링크를 누르거나 번호로 전화하거나 OTP를 공유하지 말라고 안내합니다.

별도의 결정적 규칙 계층은 OTP·PIN 요구, KYC, 계정 차단, 복권·경품 문구, 단축 링크, APK 파일, AnyDesk 같은 원격 접속 앱을 검사합니다. 이 계층은 위험도를 높일 수만 있고 낮출 수는 없습니다. 약품 포장에 인쇄된 권장소비자가격(MRP)처럼 위험 신호가 아닌 숫자는 기록만 합니다. 다만 규칙은 Gemma가 옮긴 텍스트를 검사하므로, 모델이 흐릿한 사진의 OTP 문구를 놓치면 규칙도 이를 보지 못할 수 있습니다.

숫자도 설명 문장에 넣지 못하게 했습니다. 모델이 ₹1,182를 1,188로 잘못 읽어 소리 내어 읽은 사례가 있었기 때문입니다. 금액과 기한은 별도 필드에 원문 그대로 담고, 화면에서도 따로 표시합니다. 문자 체계가 섞이는 문제도 처리합니다. 벵골어 답변에 한글이 섞이거나 말라얄람어 답변에 루마니아어·러시아어 단어가 들어가면 허용된 문자 체계 밖의 문자를 제거하고, 심하게 어긋난 답변은 한 번 다시 요청합니다.

로컬 실행과 공개 데모

가족이 실제로 쓰는 버전은 8GB 메모리의 M3 MacBook에서 Gemma 3 4B를 실행합니다. 첫 요청은 모델을 불러오는 동안 거의 4분이 걸렸습니다. 워밍업 요청과 실제 요청의 컨텍스트 크기가 달라 모델이 두 번 적재되고 시간 초과가 난 문제도 있었습니다. 서버 시작 시 실제 요청과 같은 설정으로 모델을 미리 불러와 계속 유지한 뒤에는 사진 한 장 처리에 25~60초가 걸립니다.

공개 데모는 Vercel에서 같은 코드를 실행하지만 모델은 Google의 무료 Gemini API 티어에 있는 Gemma 4 26B를 사용합니다. 혼합 전문가(Mixture of Experts) 모델로, 활성 파라미터는 4B입니다. 처음에는 모델이 출력 토큰 1,500개 중 1,497개를 생각에 쓰고 JSON을 출력하지 않아 배포가 실패했습니다. 저자는 thinkingLevel을 minimal로 낮췄고 응답 시간은 40~55초에서 약 5초로 줄었습니다. 16개 언어에서 63회 실시간 시험을 했을 때 사기를 모두 잡고 금액과 기한도 모두 정확했다고 밝혔습니다. 말라얄람어·오디아어 답변은 개선됐고, 산탈리어는 올 치키(Ol Chiki) 문자로 출력됐습니다.

저자는 4B 모델에서 힌디어·벵골어·마라티어·텔루구어·타밀어·구자라트어·우르두어·칸나다어는 양호했지만 오디아어와 말라얄람어는 약했고, 산탈리어 문자는 쓰지 못했다고 설명합니다. 해당 언어에는 베타 표시와 가족에게 다시 확인하라는 경고를 붙였습니다. 집에서 처리하면 사진이 외부 서버로 나가지 않는 대신 느립니다. 저자는 가정용 노트북에서 약 30초, 호스팅 모델에서 약 5초가 걸리며, 문서를 한 번 읽는 용도라면 개인정보 보호를 택한다고 설명합니다.

dev.to 반응

  • @pranto_bala_ — 음성을 넣은 아이디어가 정말 좋습니다.
    • @codeswithroh — 정말 감사합니다. 음성 기능 없이 앱을 드렸을 때 어머니가 직접 읽어주는 음성이 있으면 훨씬 도움이 되겠다고 말씀하셨습니다.
  • @indiainfranotes — 벵골어에 집중한 점이 중요합니다. 사기 문구는 번역 품질만이 아니라 지역 표현에도 좌우되기 때문입니다. 다음 시험에서는 일반적인 가족 메시지와 고위험 요청의 오탐을 따로 측정하고, 어떤 표현 때문에 경고했는지 모델이 보여주면 좋겠습니다. 메시지 유형을 가로지르는 소규모 실사용 평가를 계획하고 있나요?
    • @codeswithroh — 네, 맞습니다. 다음 목표는 좋은 분류기를 구현하는 일이라 지금 하나를 학습하고 있습니다. TypeScript의 jev를 붙이는 방안도 생각 중이며 꽤 효율적일 것 같습니다.
  • @mrsaynothing — 이 용도에는 로컬 우선 방식이 맞습니다. 사기 문자는 은행 이름과 OTP 흐름을 담으니, 그 내용을 호스팅 API에 붙여넣는 것 자체가 개인정보 유출이 될 수 있습니다. Gemma 분류기는 코드가 섞인 메시지에서 얼마나 잘 작동하나요? 가족이 전달하는 메시지는 벵골어와 영어가 반반이고 URL은 로마자로 적혀 있습니다. 소형 모델이 흔들리는 지점인데, 이런 메시지도 잡는다면 어머니를 넘어 더 널리 쓸 수 있겠습니다.
    • @codeswithroh — 좋은 질문입니다. 가족이 실제로 전달하는 방식대로 쓴 새 메시지 네 개를 시험했습니다. 로마자 벵골어(Banglish) 사기 문구, 영어 표현과 bit.ly 링크를 섞은 벵골어 문자, 힌디어와 영어가 섞인 전기 차단 사기, 그리고 실제 요금 안내 메시지를 대조군으로 넣었습니다. 호스팅 데모의 Gemma 4 26B는 4개 중 4개를 맞혔습니다. 사기 세 건을 모두 표시했고 실제 안내문은 안전하다고 판정했습니다. 영어 키워드 규칙의 도움 없이 의미만으로 힌디어·영어 혼합 전기 사기를 잡았습니다. 가족용 노트북의 Gemma 3 4B는 사기 세 건 중 두 건을 잡았습니다. 벵골어 메시지는 모두 잡았지만 힌디어·영어 혼합 전기 차단 사기는 '사기'가 아니라 '주의'로 판정했습니다. 예상하신 흔들림입니다. 보조 규칙에도 빈틈이 드러났습니다. 규칙은 영어와 'blocked', 'ব্লক' 같은 현지 문자 표현만 알아서 'block hoye jabe', 'kaat diya jayega' 같은 로마자 표현은 놓쳤습니다. 다음 수정에서는 로마자 패턴을 규칙에 추가해 4B 모델 하나에만 탐지를 맡기지 않으려 합니다.
  • @kartik-nvjk — 사기 판정은 맞았지만 조언이 사기범의 헬프라인을 가리켰습니다. 판정만 확인하는 시험으로는 잡히지 않는 문제입니다. 규칙은 Gemma가 직접 옮긴 original_text를 읽으니, OTP 문구를 잘못 읽으면 규칙에 닿지 않습니다. 일반 OCR 결과도 규칙에 넣는 편이 좋겠습니다. 흐릿한 사진에서 original_text가 OTP나 KYC 문구를 얼마나 자주 빠뜨리나요?
    • @codeswithroh — 잘 짚으셨습니다. 규칙은 Gemma가 옮긴 텍스트만 보므로 OTP 문구를 잘못 읽으면 규칙이 작동하지 않습니다. 그런 일이 얼마나 자주 생기는지는 아직 측정하지 않았습니다. 시험한 흐릿한 사진에서는 Gemma가 일부 내용을 빠뜨리기보다 '너무 흐릿하니 더 가까이에서 다시 찍으라'고 거부하는 경우가 많았습니다. 다만 몇 차례 시험한 결과일 뿐 수치로 말할 수는 없습니다. Tesseract 같은 일반 OCR도 함께 실행해 규칙을 적용하는 게 맞습니다. 그러면 두 계층이 서로 독립적으로 실패합니다. 할 일 목록에 추가하겠습니다.

원문: dev.to / 번역·요약: Trawling