Vietnamese documents, finally readable by your RAG stack.
viparse turns legacy Vietnamese files — TCVN3/VNI/VISCII fonts, scanned PDFs, old .doc/.xls — into clean Unicode NFC Markdown or JSON. One function call, ready for your vector DB.
B¸o c¸o tµi chÝnh quý II n¨m 2026 cña c«ng ty. ThÞ trêng ViÖt Nam ph¸t triÓn m¹nh.
Báo cáo tài chính quý II năm 2026 của công ty. Thị trường Việt Nam phát triển mạnh.
Your parser reads the file. It doesn't read Vietnamese.
Millions of Vietnamese documents were authored in pre-Unicode fonts — .VnTime, VNI, VISCII. Generic loaders like Unstructured or LlamaParse extract the bytes faithfully and hand your pipeline garbage: "Tiªu ®Ò" instead of "Tiêu đề". Embeddings built on garbled text retrieve nothing. viparse handles exactly that layer: detect the legacy encoding, convert to Unicode, enforce NFC — then get out of your way.
Three steps, one call.
Built for pipelines, not demos.
Two lines to clean text.
import viparse
docs = viparse.load("bao_cao_cu.doc") # list[Document], already NFC
docs = viparse.load("scan.pdf", ocr=True, output="markdown")Try it in your browser.
Paste garbled Vietnamese text, get clean Unicode back. It runs in the page — nothing is uploaded, and it works offline once loaded.
Measured on real broken files.
96 Vietnamese government documents from 2002–2009 — Word, Excel, RTF, PDF and PowerPoint — transcribed by hand and scored on diacritic accuracy. The corpus, the metric, the raw results and the command that regenerates them are public.
| Reading | Character | Diacritic | Syllable |
|---|---|---|---|
| No conversionbytes extracted faithfully | 0.787 | 0.019 | 0.225 |
| viparse 0.1.2796 documents, end-to-end | 0.982 | 0.986 | 0.985 |
The 0.019 row is the honest headline: text that looks 79% intact carries 1.9% of the Vietnamese. viparse's own row is a weaker claim than it looks — the transcripts and the conversion tables were derived from the same corpus, so it measures self-consistency as much as correctness. Both numbers, the method, every document and the command that regenerates them are published so the second one can be argued with.
And on ordinary Unicode documents
| Document | Order | Completeness | Headings |
|---|---|---|---|
| DOCX · XLSX · PPTX | 1.000 | 1.000 | 1.000 |
| PDF, one column | 1.000 | 1.000 | 0.000 |
| PDF, two columns | 0.600 | 1.000 | 0.000 |
Nothing is ever lost — completeness is 1.000 everywhere. Both failures are failures of arrangement, which is the harder kind to notice. A PDF has no headings, so every chunk from one carries an empty section; and a multi-column PDF is read across the page rather than down the columns. Recovering columns means layout analysis, which viparse does not do: use a layout-aware loader for those and pass its output through viparse.fix().