A community health worker reads a blood-pressure measurement out loud. Whisper transcribes it as एक सौ दस बटा सत्तर — "one hundred ten over seventy," in words. The form I was filling needed 110/70.

That gap is the whole reason this library exists.

I've written about llmclean before — a tiny library that grew out of the same habit of copy-pasting the same cleanup pass across projects. This is its sibling, one layer down the stack. Where llmclean cleans up what a language model emits, hindi-normalize cleans up what a speech recogniser hears — specifically for Hindi.

It came out of Sakhi, an offline Hindi voice-to-form tool for ASHA workers (India's frontline community health workers). At the bottom of that pipeline, right before Whisper's transcript became "data we trust," I kept finding the same code: number words that never became digits, ५ and 5 treated as different characters, an ASCII | sitting where a danda । belonged, the same word encoded two different ways so search and dedup silently missed it.

Every Hindi speech project I touched had its own ad-hoc version. So I pulled the pass out, generalized it, and put it on PyPI.