# CPU speech synthesis under a serverless bill

Kokoro-82M served on serverless CPUs, and the two changes to the serving path that take a bursty day's bill from $2.41 to $0.38.

Technical report arXiv:2610.00063v1 (https://arxiv.org/abs/2610.00063v1), 2026-09-04, 6 pages, cs.DC, cs.AI, cs.CL.
Authors: Pakorn Nathong, Kunat Pipatanakul. Affiliations: Paxa Labs.

Figures below are the report's own, measured on its own benchmarks. They are not specifications of any Paxa Labs API.

Wayu-Paxa-TTS-Edge, the open Thai voice from the lab's [first speech report](https://paxalabs.com/research/thai-tts-from-synthetic-speech), is an 82M model on the Kokoro backbone. A model that small runs on a CPU, and a serverless container that scales with traffic is a natural place to host it. This report measures what such a container bills for, with Kokoro-82M itself as the workload.

Two changes to the serving path carry the result. Bounding the CPU each request may use doubles sustained efficiency on OpenVINO, from 1.35 to 2.71 audio-seconds per CPU-second. Releasing what an idle instance holds cuts its billed memory from 12.1 GB to 1.33 GB, and a request arriving afterwards reaches first audio in 2.2 seconds. Over one day of bursty traffic the bill falls from $2.41 on PyTorch defaults to $0.38.

## What a warm instance bills for

An instance-billed platform meters a container for its whole lifetime. It charges CPU-seconds while the container computes and GB-seconds for as long as it holds memory, idle or busy. The meter includes the page cache, and model files the kernel keeps there stay billable until they are reclaimed.

The report prices every configuration at $30 per vCPU-month and $8 per GB-month, round figures of the same order as public list prices. Its conclusions compare configurations and do not depend on the exact rates. At those rates a PyTorch server that holds 8.7 GB while idle costs about $69 a month before it serves a request. Scaling to zero removes the charge, and the next request then waits 7.7 seconds for first audio.

## Sizing each request

The exported model synthesizes one utterance per call. Padding requests of different lengths without masking changes the audio, and the model has no token-by-token decoding loop for a server to batch across. Parallelism comes from running independent requests side by side.

ONNX Runtime and OpenVINO size each request's thread pool to the machine's physical cores by default. Concurrent requests then compete for the same CPUs. The report gives each request a bounded share. Its server runs eight inference streams with two threads each on a 32-vCPU container.

**Audio-seconds per CPU-second at four concurrent clients** (higher is better)

| Configuration | Value |
| --- | --- |
| OpenVINO defaults | 1.35 |
| + sized threads, four streams | 2.31 |
| + compile cache | 2.33 |
| + eight streams | 2.71 |
| + idle release | 2.71 |

Table 2 of the report, each row adding one change to the one above. The thread budget and the stream count carry the gain. The compile cache and the release leave efficiency unchanged.

Sizing trades the latency of a lone request for throughput under load. A short utterance with the machine to itself reaches first audio in 134 ms on OpenVINO defaults and in 493 ms once sized. At four clients the comparison reverses, and median first audio falls from 1.26 to 0.69 seconds. Throughput plateaus near 38 times realtime at eight clients, and requests past that point queue.

## A third state between warm and cold

Eight streams buy that efficiency with memory. The sized server holds 12.1 GB while warm, more than any baseline, and an instance-billed platform charges for it between bursts. Scaling to zero is the usual answer, and it costs a process cold start of 5.7 to 7.7 seconds on the next request.

The report adds a released state between the two. After 45 quiet seconds the server frees the compiled model and its request pool, returns unused allocator memory, and evicts the compile-cache files from the page cache. The process and the compile cache on disk stay. The next request rebuilds inference state from that cache, which skips the restart and the recompile.

**Memory an idle instance holds** (lower is better)

| Configuration | Value |
| --- | --- |
| OpenVINO defaults | 5250 MB |
| + sized threads, four streams | 8684 MB |
| + compile cache | 7490 MB |
| + eight streams | 12097 MB |
| + idle release | 1331 MB |

Table 2 of the report, read 600 seconds after the last response. The eight-stream row is read at 30 seconds, before any release.

A request that arrives after release reaches first audio in 2.2 seconds, within 2.1 to 2.3 across ten cycles. A process cold start of the same configuration takes 6.2 seconds.

## One day of bursty traffic

The report tests both changes on a synthetic day of two audio-hours, delivered in eight equal bursts across 24 hours. The container is never scaled to zero between bursts.

**One day of bursty traffic, billed in US dollars** (lower is better)

| Configuration | Value |
| --- | --- |
| PyTorch defaults | 2.41 |
| Request sizing alone | 3.24 |
| Request sizing with release | 0.38 |

Figure 1 of the report, at $30 per vCPU-month and $8 per GB-month. Each row is one server left running through the same day.

Request sizing alone makes the day more expensive. The sized server spends less CPU on each burst and then holds 12.1 GB until the next one, and the day costs $3.24 against $2.41 on PyTorch defaults. Idle memory was already 95% of the PyTorch bill. Release is what turns the efficiency gain into a lower bill, at $0.38.

## What the server scores

**Kokoro-82M served six ways on one 32-vCPU host**

| System | Efficiency ↑ | First audio ↓ | Idle memory ↓ | Cold start ↓ | Per audio-hour ↓ |
| --- | --- | --- | --- | --- | --- |
| PyTorch eager | 0.66 | 2.46 s | 8659 MB | 7.7 s | $0.0631 |
| ONNX Runtime default | 0.89 | 0.94 s | 3969 MB | 5.8 s | $0.0468 |
| ONNX Runtime sized | 1.36 | 2.36 s | 3958 MB | 5.7 s | $0.0306 |
| OpenVINO default | 1.35 | 1.26 s | 5250 MB | 6.9 s | $0.0309 |
| OpenVINO sized | 2.71 | 0.69 s | 12097 MB | 7.4 s | $0.0154 |
| OpenVINO sized, with release | 2.71 | 0.94 s | 1331 MB | 6.2 s | $0.0153 |

Table 1 of the report. Efficiency is audio-seconds per CPU-second and first audio is the median, both at four concurrent clients. Idle memory is read 600 seconds after the last response, and at 30 seconds for the sized row without release. Cold start runs from process start to first audio. Cost is the busy cost per audio-hour at the report's example rates.

Busy cost per audio-hour falls to $0.0153, 4.1 times below PyTorch defaults and 3.1 times below ONNX Runtime defaults. The complete system holds the least memory once idle and ties for the highest efficiency. It gives ground elsewhere. Median first audio at four clients is 0.94 seconds against 0.69 for the sized server without release, and ONNX Runtime starts a fresh process faster.

## Where the method stops

With both changes in place, the report looks for further gains and keeps none. Static-shape compilation shortens per-call time by 3.3%, inside the variation between repeated runs. Padding inputs to a fixed length fails the output check. A 36-token utterance padded to 128 tokens yields 3.1 times as much audio, because the model synthesizes the padding.

The study covers one model family, one runtime for the approach, two CPU architectures, and a synthetic trace. Quantization, SMT, and core pinning were left untested. The Thai student built on the same backbone was outside the study. On an AMD Zen 5 host the same design reaches 3.26 audio-seconds per CPU-second and releases to 1.13 GB. A second model, the 100M pocket-tts on its own PyTorch server, holds 1234 MB through a ten-minute idle window and has no released state.

## If you serve speech on CPUs

On the report's bursty day a small speech model costs far more idle than busy, and a faster server raises the bill when it holds more memory. The implementation is about 1,900 lines of Python on OpenVINO with no custom kernels, and it is open with the raw logs behind every figure.

This is research. It is not a product specification. Paxa Labs serves speech through its own [text to speech API](https://paxalabs.com/text-to-speech), which is a different model with its own published limits. The dollar figures price cloud compute at example rates and say nothing about what the API costs.

## Released artifacts

- paxalabs/cpu-tts-to-the-wall: https://github.com/paxalabs/cpu-tts-to-the-wall

# A Thai voice from fifteen seconds of speech

An 82M model small enough to run on the device, trained entirely on speech a larger model generated, and the benchmark that says what it still gets wrong.

Technical report arXiv:2609.03502v1 (https://arxiv.org/abs/2609.03502v1), 2026-09-03, 18 pages, cs.CL, cs.AI.
Authors: Kunat Pipatanakul, Potsawee Manakul, Warit Sirichotedumrong, Sittipong Sripaisarnmongkol, Pakorn Nathong, Phatrasek Jirabovonvisut. Affiliations: Wayu Research, Paxa Labs, Typhoon.

Figures below are the report's own, measured on its own benchmarks. They are not specifications of any Paxa Labs API.

A voice-cloning model can reproduce a speaker from a few seconds of audio, but it needs a large generative backbone and a GPU to do it. A compact fixed-voice system runs anywhere, and needs hours of studio recording from the speaker it imitates. This report takes a third route: use the cloning model as a data source, turn a fifteen-second reference into a synthetic corpus, and train an 82M student on that. The student never hears a real recording of the voice it speaks with.

The result, Wayu-Paxa-TTS-Edge, reads Thai and English on the device. It scores 68.2% on a held-out set of 1,531 sentences built around expressions Thai speech models get wrong. It places phrase breaks more accurately than the 600M teacher it learned from, at 82M parameters.

## One teacher, filtered, one student

Thai text is prepared and verbalized, a zero-shot teacher renders it against a frozen voice reference, a quality filter accepts or rejects each candidate, and what survives trains the student. The filter rejects 23.0% of what the teacher produces. Rejection is not the same as deletion. A rejected text is re-rendered, because dropping it would quietly remove the hardest sentences from the corpus.

**Twelve voices, none of them recorded**: Each one began as a written description that the teacher turned into a speaker. These are the references the synthetic corpus was built from.

- Teen girl, bright (female · teenager · high pitch): https://paxalabs.com/audio/research/voices/f_teen_bright.mp3
- Young woman, bright (female · young adult · high pitch): https://paxalabs.com/audio/research/voices/f_young_bright.mp3
- Young woman, clear (female · young adult · moderate pitch): https://paxalabs.com/audio/research/voices/f_young_clear.mp3
- Young woman, warm (female · young adult · low pitch): https://paxalabs.com/audio/research/voices/f_young_warm.mp3
- Middle-aged woman, clear (female · middle-aged · moderate pitch): https://paxalabs.com/audio/research/voices/f_mid_clear.mp3
- Middle-aged woman, warm (female · middle-aged · low pitch): https://paxalabs.com/audio/research/voices/f_mid_warm.mp3
- Elder woman, soft (female · elderly · moderate pitch): https://paxalabs.com/audio/research/voices/f_elderly_soft.mp3
- Elder woman, low (female · elderly · low pitch): https://paxalabs.com/audio/research/voices/f_elderly_low.mp3
- Teen boy, bright (male · teenager · high pitch): https://paxalabs.com/audio/research/voices/m_teen_bright.mp3
- Young man, clear (male · young adult · moderate pitch): https://paxalabs.com/audio/research/voices/m_young_clear.mp3
- Middle-aged man, warm (male · middle-aged · low pitch): https://paxalabs.com/audio/research/voices/m_mid_warm.mp3
- Elder man, deep (male · elderly · very low pitch): https://paxalabs.com/audio/research/voices/m_elderly_deep.mp3

## What character error rate hides

Word error rate needs word boundaries, and Thai does not mark them. Character error rate avoids that, and then hides the errors that matter: a 150-character sentence can mispronounce a brand name and still score around 1% CER, which reads as fine. A transcript can also be perfectly correct while the waveform pauses in the middle of a word.

So the report measures four things: correctness on a challenge set of local expressions, pause placement, speaker similarity, and speaking rate. The challenge set holds 1,531 sentences, each containing one target expression, scored by whether the transcript contains it.

| Challenge-set category | Items |
| --- | --- |
| Thai-English code-switching | 391 |
| Names | 310 |
| Rare words | 410 |
| Informal spelling | 210 |
| Long sentences | 210 |
| Total | 1,531 |

## What the student scores

**Wayu-Paxa-TTS-Edge against its teacher and a frontier API**

| System | Params | Keyword ↑ | Thai CER ↓ | Pause prec. ↑ | PPER ↓ |
| --- | --- | --- | --- | --- | --- |
| Wayu-Paxa-TTS-Edge | 82M | 68.2% | 3.7% | 91.4% | 6.7% |
| OmniVoice teacher | 600M | 72.8% | 4.6% | 89.9% | 17.6% |
| Gemini 3.1 Flash TTS | ≥405B | 79.8% | 3.3% | 96.4% | 13.8% |

Table 8 of the report. PPER is the pause-placement error rate. Keyword accuracy uses 1,531 items and Thai CER 500; pause metrics use 210 long sentences. The Gemini parameter count is a literature-derived lower bound. The vendor publishes no figure.

Compression costs the student difficult lexical realization and almost nothing else. It trails both larger systems on the challenge set, improves on the teacher's Thai CER, and produces the fewest pause errors of the three. Its rate of pauses inside a word is the lowest at 1.4%. Adding English took its English CER from 4.4% to 1.1% while leaving speaker similarity and the intra-word pause rate unchanged.

## What each step of the recipe bought

| Corpus construction | Hours | Keyword | CER | Pause prec. | PPER |
| --- | --- | --- | --- | --- | --- |
| Unfiltered baseline | 17.72 | 67.5% | 4.0% | 81.3% | 16.2% |
| + pause filtering | 17.63 | 69.6% | 3.5% | 88.4% | 14.3% |
| + bilingual frontend | 17.63 | 68.7% | 4.1% | 88.2% | 14.8% |
| + filtered scale-up | 40.58 | 67.2% | 3.9% | 85.4% | 11.9% |
| + resample rejected | 41.81 | 69.2% | 3.4% | 92.8% | 6.2% |

Scaling the corpus from 17.63 to 40.58 hours under the same filter improved the pause metrics and cost keyword accuracy. Repeated filtering thins out exactly the hard examples the challenge set asks about. Resampling the rejected texts recovers that coverage and produces the best configuration on every measure but one.

**Trained from scratch against pretrained initialization** (higher is better)

| Configuration | Value |
| --- | --- |
| Keyword accuracy, from scratch | 51.7% |
| Keyword accuracy, pretrained | 69.2% |
| Code-switch accuracy, from scratch | 22.8% |
| Code-switch accuracy, pretrained | 65.5% |

Table 6 of the report, on the Thai-only model. Reusing the pretrained backbone is worth 17.5 points of keyword accuracy overall and 42.7 on code-switching alone: the student inherits far more from its initialization than its size suggests.

## A dialect with no corpus

Most language varieties will never have a licensed corpus or a recording studio, which is why most of them have no speech technology at all. The same pipeline was pointed at Isan with one fifteen-second crop of Isan-accented speech: the teacher rendered about 1.5 hours from it, and the student was fine-tuned for four epochs. Nothing else was recorded.

**Fifteen seconds in, a dialect voice out**: The reference clip, then the fine-tuned 82M model reading text from the Thai Dialect Isan Speech Corpus.

- The reference (15 seconds of Isan-accented speech, from a public demo): https://paxalabs.com/audio/research/isan/ref_15s_donor.mp3
- The student, first sentence (82M model, four Isan-only epochs): https://paxalabs.com/audio/research/isan/00_student_ep12.mp3
- The student, second sentence (82M model, four Isan-only epochs): https://paxalabs.com/audio/research/isan/01_student_ep12.mp3

The adapted student sits at 0.842 cosine similarity to the reference against the teacher's 0.854, and reaches 5.5% Isan CER where the teacher reaches 6.6%. It pays for that in Central Thai, where CER rises from 3.4% to 5.1% and keyword accuracy falls from 69.2% to 65.8%. CER measures intelligibility and nothing more. Whether the result sounds natural to an Isan speaker is not something this evaluation can answer.

## Where the method stops

The student cannot learn what the teacher cannot say. Sampling the teacher 118 times and keeping any correct rendering lifts exact accuracy from 72.8% to 87.9%. That puts 15.1 points of the gap within reach of better sampling alone. The rest tracks the teacher's own training data. At 118 samples, keywords the teacher never saw are recovered 66% of the time, against 98% for keywords it saw between 100 and 10,000 times. What binds is coverage.

Both evaluation instruments lean on heuristics. Pause scoring composes Thai word segmentation with CTC forced alignment, and its accuracy is bounded by both; keyword scoring uses exact matching against accepted forms. The rates are most reliable as comparisons between systems measured with the same instrument.

## If you are building on Thai speech

The practical finding is that the expensive part of a Thai voice is not the model. It is the coverage of the data behind it, and text normalization and pronunciation handling sit outside the acoustic model, where 1.1 points of challenge-set accuracy were recovered with the weights frozen. Anyone shipping Thai speech can measure the same things: the evaluation framework and both benchmarks are open.

This is research. It is not a product specification. Paxa Labs serves Thai speech through its own [text to speech API](https://paxalabs.com/text-to-speech), which is a different model with a different roster and its own published limits.

## Released artifacts

- wayu-ai/wayu-paxa-tts-edge: https://huggingface.co/wayu-ai/wayu-paxa-tts-edge
- wayu-ai/thai-tts-keyword-bench: https://huggingface.co/datasets/wayu-ai/thai-tts-keyword-bench
- wayu-ai/thai-tts-pause-bench: https://huggingface.co/datasets/wayu-ai/thai-tts-pause-bench
- wayu-research/thai-tts-eval: https://github.com/wayu-research/thai-tts-eval
- wayu-research/wayu-tts-inference: https://github.com/wayu-research/wayu-tts-inference
- kunato/wayu-paxa-tts-demo: https://huggingface.co/spaces/kunato/wayu-paxa-tts-demo

# Thai OCR trained without a single real label

A 0.9B document model taught on 45,723 reconstructed pages, and the controlled experiments that say which part of a synthetic document actually transfers.

Technical report arXiv:2609.03595v1 (https://arxiv.org/abs/2609.03595v1), 2026-09-03, 20 pages, cs.CL, cs.AI, cs.CV.
Authors: Kunat Pipatanakul. Affiliations: Wayu Research, Paxa Labs.

Figures below are the report's own, measured on its own benchmarks. They are not specifications of any Paxa Labs API.

Synthetic training pages give you exact labels at any scale, which is the whole reason to use them for a language whose documents are plentiful and whose labels are not. What nobody had isolated is which part of a synthetic page does the work. Realism is not one property: it bundles the source domain, the page context, the typography, the spatial structure, and the shape of the glyphs. The usual advice is to add more of all of it.

This report separates those factors with a controlled reconstruction pipeline, then uses the answer to build Wayu-Paxa-OCR-Zero, a Thai document model trained without one OCR label from a real Thai page. It reads a typical printed page at 1.24% median character error, down from 6.64% for the checkpoint it was adapted from. At 0.9B parameters it beats a 7B Thai OCR model on all five evaluation sets.

## Reconstruct a real page, one property at a time

Every synthetic page starts as a real one. The pipeline takes a document with annotated text regions, keeps the region geometry and the reading order, and erases the original text pixels. It then fits the label back into the same region and renders it in either a sampled typeface or real handwriting glyphs. The label is exact by construction, because it is the text that was rendered.

**One reconstructed page**

- Out-of-domain synthetic: An annual-report page whose original text has been erased and replaced with Thai, keeping the original charts, rules, and column structure in place. (https://paxalabs.com/research/thai-ocr-from-synthetic-data/reconstructed-page.jpg)

Rendered by docaug from a public source page, as published with the report.

Because the geometry survives, each property can be varied on its own. Keep the source background or replace it with white. Keep the two-dimensional arrangement or stack the regions vertically. Sample the measured Thai typeface profile or collapse to a single face. Render glyphs from a font or redraw them from a bank of real ink.

## Which properties actually transfer

**Source properties, page-level training** (lower is better)

| Configuration | Value |
| --- | --- |
| Out-of-domain synthetic | 43.99% |
| Without non-text page context | 43.16% |
| Without typeface diversity | 49.86% |
| Without two-dimensional layout | 58.4% |

Table 2 of the report: median character error rate on the handwriting set, each row removing one more property. Removing the page's backgrounds, figures and rules changes nothing; removing typeface variety and then spatial structure degrades transfer step by step.

Non-text context is the property everyone reaches for first, and it moves the median by at most 1.62 points across three evaluation sets and two training settings. Typeface diversity is the first thing whose removal consistently costs something, and it costs it on handwriting. Removing it takes 6.70 and 9.48 points of median CER under page-level training, against 0.56 and 2.15 on printed pages. Flattening the layout costs more again.

Training granularity changes which dataset wins, and the reversal is sharp. A model that sees whole pages does best on in-domain reconstruction, at 1.82% median CER against 5.07% for out-of-domain. A model that sees individual cropped elements does the opposite, at 15.59% against 5.52%. The report does not explain the reversal, and says so.

## How close reconstruction gets to real supervision

**Reconstruction against real supervision, page-level training** (lower is better)

| Configuration | Value |
| --- | --- |
| Qwen3-VL-2B-Instruct, unadapted | 14.47% |
| Out-of-domain synthetic | 5.07% |
| In-domain synthetic | 1.82% |
| Real Thai printed pages | 1.31% |

Table 4 of the report: median character error rate on printed Thai. On a typical page, reconstruction lands 0.51 points off real supervision.

The median is the flattering statistic. Under character-weighted mean CER the same comparison reads 16.20% against 9.79%. Real supervision is still removing a tail of severe failures that reconstruction does not reach. On handwriting, reconstructed Thai print and real Thai print land within 0.13 points of each other, and both stay far behind training that includes real handwriting at 26.05%.

## The gap was handwriting, and real ink closed it

A handwriting typeface renders the same character the same way every time. Real handwriting does not, and that difference is visible before any number is quoted. The two plates below carry identical labels, layout, ink height and ink colour, and differ only in where the strokes came from.

**The same page, two sources of ink**

- Handwriting typefaces: A Thai page rendered in a handwriting font, where every occurrence of a character has an identical outline. (https://paxalabs.com/research/thai-ocr-from-synthetic-data/glyphs-typeface.jpg)
- Real glyph instances: The same Thai page redrawn from a bank of real handwritten characters, where each occurrence of a character has a different shape. (https://paxalabs.com/research/thai-ocr-from-synthetic-data/glyphs-real.jpg)

Table 5 of the report. Labels, layout, ink height and ink colour held fixed; only the source of the strokes differs.

Handwriting typefaces alone take page-level median CER on the handwriting set from 43.99% to 38.65%. Redrawing the same pages from real ink takes it to 37.91%, and the easier handwriting set from 34.84% to 30.66%. Because the two variants differ in nothing else, the remaining gain belongs to stroke variation. Real handwriting supervision still wins at 26.05%, and the glyph bank holds only 5,953 instances.

## What the model scores

The recipe that follows from all of this is 45,723 synthetic pages: a base set with both renderings of every handwriting page, a handwriting-focused set, and 2,190 reconstructed forms. Every page is generated from a public source document. No real Thai page is used as a source image and no label from one enters training.

**Wayu-Paxa-OCR-Zero against its base checkpoint and open Thai OCR**

| System | Heldout ↓ | Handwriting ↓ | ThaiOCRBench ↓ | SEA-DocBench ↓ |
| --- | --- | --- | --- | --- |
| PaddleOCR-VL-1.6 (0.9B) | 6.64% | 74.87% | 38.0% | 8.87% |
| Wayu-Paxa-OCR-Zero (0.9B) | 1.24% | 20.55% | 15.3% | 4.86% |
| Typhoon OCR (7B) | 2.54% | 43.60% | 30.6% | 9.22% |
| Typhoon OCR 1.5 (2B) | 0.21% | 19.36% | 6.2% | 5.81% |
| Gemini 3.7 Flash | 0.00% | 11.29% | 0.9% | 5.51% |

Table 7 of the report: median page character error rate, lower is better. Heldout and Handwriting are the report's own sets. ThaiOCRBench averages five audited reading tasks, and SEA-DocBench uses its 1,148-page clean Thai subset. Scores include layout-detection and reading-order errors.

Against the checkpoint it was adapted from, with the architecture held fixed, the recipe cuts median CER on every benchmark: 6.64% to 1.24% on printed pages and 74.87% to 20.55% on handwriting. Against independently trained systems the comparison is about competitiveness, and it is mixed on purpose. It beats the 7B Typhoon model everywhere, nearly matches the 2B model on handwriting, and wins SEA-DocBench. It stays behind on printed pages and ThaiOCRBench. Gemini 3.7 Flash is stronger on three of the four.

## Where the method stops

Synthetic supervision still trails real supervision on the severe failures that dominate a character-weighted mean, and it trails it further on handwriting. The value of matching the source domain depends on the training unit, and the reason is unresolved. A model trained only on reconstructions is less robust to document types, typefaces, and handwriting styles it never saw, which is a real limit for anyone pointing it at an unfamiliar form.

## If you are working with Thai documents

The useful conclusion is where to spend effort. More visual realism in the background of a synthetic page buys nothing measurable. More typefaces, real two-dimensional layout, and real handwritten strokes buy a great deal, and the training unit decides which corpus you want in the first place. The reconstruction pipeline and both model weights are open. The experiment can be repeated on another language with abundant documents and few labels.

This is research. It is not a product specification. Paxa Labs serves Thai documents through its own [OCR API](https://paxalabs.com/ocr), which is a different model with its own published limits.

## Released artifacts

- wayu-ai/wayu-paxa-ocr-zero: https://huggingface.co/wayu-ai/wayu-paxa-ocr-zero
- wayu-ai/wayu-paxa-ocr-zero-gguf: https://huggingface.co/wayu-ai/wayu-paxa-ocr-zero-gguf
- wayu-research/docaug: https://github.com/wayu-research/docaug
- wayu-research/wayu-ocr-inference: https://github.com/wayu-research/wayu-ocr-inference
- kunato/wayu-paxa-ocr-zero-demo: https://huggingface.co/spaces/kunato/wayu-paxa-ocr-zero-demo
