How to use from the
Use from the
Transformers library
# Gated model: Login with a HF token with gated access permission
hf auth login
# Use a pipeline as a high-level helper
from transformers import pipeline

pipe = pipeline("image-text-to-text", model="botnick/Netra-2B")
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"},
            {"type": "text", "text": "What animal is on the candy?"}
        ]
    },
]
pipe(text=messages)
# pip install -U transformers accelerate
# Load model directly
from transformers import AutoProcessor, AutoModelForMultimodalLM

processor = AutoProcessor.from_pretrained("botnick/Netra-2B")
model = AutoModelForMultimodalLM.from_pretrained("botnick/Netra-2B", device_map="auto")
messages = [
    {
        "role": "user",
        "content": [
            {"type": "image", "url": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/p-blog/candy.JPG"},
            {"type": "text", "text": "What animal is on the candy?"}
        ]
    },
]
inputs = processor.apply_chat_template(
	messages,
	add_generation_prompt=True,
	tokenize=True,
	return_dict=True,
	return_tensors="pt",
).to(model.device)

outputs = model.generate(**inputs, max_new_tokens=256)
print(processor.decode(outputs[0][inputs["input_ids"].shape[-1]:]))
Quick Links

You need to agree to share your Hugging Face information to access this model

This repository is publicly accessible, but you have to accept the conditions to access its files and content.

Log in or Sign Up to review the conditions and access this model content.

Netra · เนตร logo, an eye whose lower lid is a line of text. Reads Thai accounting documents — text and key fields, in a 2B model. v0.3, 2B, Thai / English, Apache-2.0. Beside it, one synthetic tax invoice: printed ใบกำกับภาษี becomes "doc_type": "tax_invoice", 29 ก.ย. 2570 becomes "date": "2027-09-29", 0-7552-78249-83-1 becomes "tax_id": "0755278249831", 4,183.70 becomes "total": 4183.7

Netra-2B v0.3

Status: released — v0.3 (November 2026), replacing v0.2 (2026-10-26). v0.3 is training round 24: the v0.2 adapter (round 13) trained for one more epoch with receipt-printer slips added, including 1,433 synthetic fuel-station slips. Use it with the loop guard; ThaiOCRBench was scored with the guard on. Against v0.2, v0.3 has a lower character error rate on all three ThaiOCRBench page tasks, ties v0.2 on all seven hold-out sets, and its trust gate still accepts no wrong answer on the synthetic test sets. It does not beat v0.2 or v0.1 on every measure; see Release gate. v0.1 and v0.2 remain in this repository's commit history. The trust gate checks every field, cross-reads two independent OCR passes, and checks every party name against a character-level reader (Trust gate).

Netra (เนตร) reads Thai business and accounting documents. Give it a photo or scan of a page and it returns the text as Markdown, or the accounting fields as one JSON object. It is built for developers who process Thai tax invoices, receipts, transfer slips, 50 ทวิ withholding-tax certificates and billing notes. Netra is a 2B vision-language model, fine-tuned from typhoon-ai/typhoon-ocr1.5-2b, and released under Apache-2.0.

Highlights

  • ThaiOCRBench, with the loop guard: lower character error rate than the base on all three page tasks, now with clear margins: Document parsing 0.183 vs 0.218, Full-page OCR 0.337 vs 0.359, Table parsing 0.285 vs 0.308. v0.2: 0.217 / 0.343 / 0.302 (ThaiOCRBench).
  • Hold-out sets: 5 wins, 2 ties and no loss against the base on 802 rows never used to choose a model, and a tie with v0.2 on all seven sets (hold-out).
  • Trust gate: 0 wrong answers accepted on three synthetic test sets (387 documents) and on a real fuel-station receipt photo; it accepts 31 of the 387 (4–10% per set) and sends the rest to a person (Trust gate).
  • Held-out private real-world test sets (not released): on one set of 601 documents, 0.609 of all scored fields right (v0.2 0.602); on a second set of 117 documents, the trust gate accepted no wrong answer.
  • Held-out private real receipts (not released): 8 real Thai receipts and tax invoices, 105 scored fields, read on CPU with the same setup for both versions: 68 right (0.648), v0.2 65 (0.619).
  • Real documents (Netra-Bench-Real): measured on v0.2 (reading 0.693, extraction 0.709 with the guard; base 0.666 / 0.406). v0.3 was not scored on this set.
  • Receipt key mapping (NECTEC thairocr) was measured on v0.1 only (thairocr).

Quick start

Define the two prompts, then run one page. Tested with transformers 5.17.0.

OCR_PROMPT and KIE_PROMPT (copy these exactly)
OCR_PROMPT = """Extract all text from the image.

Instructions:
- Only return the clean Markdown.
- Do not include any explanation or extra text.
- You must include all information on the page.

Formatting Rules:
- Tables: Render tables using <table>...</table> in clean HTML format.
- Equations: Render equations using LaTeX syntax with inline ($...$) and block ($$...$$).
- Images/Charts/Diagrams: Wrap any clearly defined visual areas (e.g. charts, diagrams, pictures) in:

<figure>
Describe the image's main elements (people, objects, text), note any contextual clues (place, event, culture), mention visible text and its meaning, provide deeper analysis when relevant (especially for financial charts, graphs, or documents), comment on style or architecture if relevant, then give a concise overall summary. Describe in Thai.
</figure>

- Page Numbers: Wrap page numbers in <page_number>...</page_number> (e.g., <page_number>14</page_number>).
- Checkboxes: Use ☐ for unchecked and ☑ for checked boxes."""

KIE_PROMPT = """Extract the accounting data from this Thai document image.

Return only one JSON object, no explanation, with these keys (null when the document has no such field):
doc_type, doc_title, doc_no, book_no, date, time, due_date, seller, buyer, payer, payee, items, subtotal, discount,
vat_base, vat_rate, vat, vat_included, wht_rate, wht, total, net_paid, amount_in_words, currency, ref_doc_no, ref_date, payment, extra.
Parties are {name, tax_id, branch, address, phone}; items are [{desc, qty, unit, unit_price, amount}].
Dates YYYY-MM-DD (convert พ.ศ. to ค.ศ.). Tax id = 13 digits, no dashes. Branch = 5 digits, head office "00000".
Write all digits as Arabic numerals. Copy names exactly as printed. Money printed blank or "-" is 0. Numbers must be JSON numbers."""
import torch
from PIL import Image
from transformers import AutoModelForImageTextToText, AutoProcessor
from loop_guard import degenerate  # loop_guard.py from this repo

model_id = "botnick/Netra-2B"
model = AutoModelForImageTextToText.from_pretrained(model_id, dtype=torch.bfloat16, device_map="auto")
processor = AutoProcessor.from_pretrained(model_id)

def load(path, max_side=1400):
    img = Image.open(path).convert("RGB")
    if max(img.size) > max_side:
        k = max_side / max(img.size)
        img = img.resize((round(img.width * k), round(img.height * k)), Image.LANCZOS)
    return img

def run(img, prompt, max_new_tokens, guard=False):
    messages = [{"role": "user", "content": [{"type": "image", "image": img}, {"type": "text", "text": prompt}]}]
    inputs = processor.apply_chat_template(messages, tokenize=True, add_generation_prompt=True,
                                           return_dict=True, return_tensors="pt").to(model.device)
    def gen(**kw):
        out = model.generate(**inputs, max_new_tokens=max_new_tokens, do_sample=False, **kw)
        return processor.batch_decode(out[:, inputs["input_ids"].shape[1]:], skip_special_tokens=True)[0]
    text = gen(repetition_penalty=1.05)
    if guard and degenerate(text):  # loop guard: retry once with stronger anti-repetition
        text = gen(repetition_penalty=1.25, no_repeat_ngram_size=16)
    return text

page = load("invoice.png")
markdown = run(page, OCR_PROMPT, 4096, guard=True)   # page reading
kie_raw = run(page, KIE_PROMPT, 2048)                # accounting JSON

Recommended settings: greedy decoding, repetition_penalty=1.05, long side of the image at most 1400 px, max_new_tokens 4096 for reading and 2048 for extraction, and the loop guard on reading output. The shipped generation_config.json keeps the base's sampling defaults (do_sample=true, temperature=0.7), so pass do_sample=False and repetition_penalty=1.05 explicitly, as above.

For batch inference, see vLLM (offline batch). To ask for your own keys, see key mapping.

Results

This chart shows v0.1 (2026-10-22); it is kept because its thairocr row was measured on v0.1 only. v0.3 numbers are in the tables under Details.

Bar chart, Netra-2B v0.1 vs the base typhoon-ocr1.5-2b, higher is better. Netra-Bench-Real: page reading 0.666 to 0.709, information extraction 0.406 to 0.575. NECTEC thairocr receipt key mapping: key accuracy 0.104 to 0.528, valid JSON 0.416 to 0.973. Synthetic accounting KIE: field accuracy 0.037 to 0.908, valid JSON 0.750 to 1.000, every field right 0.000 to 0.542.

v0.1 improves on its base on every benchmark in the chart, v0.2 raised real-document extraction further (0.575 → 0.713 without the guard), and v0.3 lowers ThaiOCRBench error on all three page tasks. The largest gains are in structured output: asked for specific keys, it returns valid JSON with the right keys far more often. The real-document numbers come from a small set (34 extraction documents), and the synthetic KIE comparison is not a fair head-to-head because the base never saw that schema. Sources and caveats for each number are in Details.

สรุปภาษาไทย (Thai Executive Summary)

  • โมเดลนี้คืออะไร: เนตร (Netra-2B) รุ่น 0.3 ใช้สำหรับอ่านเอกสารบัญชีและเอกสารธุรกิจภาษาไทย เช่น ใบกำกับภาษี ใบเสร็จ ใบลดหนี้/ใบเพิ่มหนี้ หนังสือรับรองการหักภาษี ณ ที่จ่าย (50 ทวิ) สลิปโอนเงิน และใบวางบิล พัฒนาต่อยอดจาก Typhoon OCR 1.5 2B ด้วย LoRA
  • สิ่งที่เปลี่ยนแปลงในรุ่นนี้: เทรนต่อยอดจากรุ่น 0.2 เพิ่มเติมอีก 1 รอบ (รอบที่ 24) โดยเพิ่มสลิปจากเครื่องพิมพ์ใบเสร็จ รวมถึงสลิปปั๊มน้ำมันแบบสังเคราะห์ 1,433 ใบ
  • ผลลัพธ์ที่ได้: ข้อความทั้งหน้าในรูปแบบ Markdown (ตารางเป็น HTML) หรือข้อมูลบัญชีในรูปแบบ JSON 28 คีย์
  • ThaiOCRBench (เปิด loop guard, ค่ายิ่งต่ำยิ่งดี): ทำคะแนนได้ดีกว่าโมเดลตั้งต้นทั้ง 3 ด้าน ได้แก่ เอกสาร 0.183 (โมเดลตั้งต้น 0.218) ทั้งหน้า 0.337 (0.359) ตาราง 0.285 (0.308) และดีกว่ารุ่น 0.2 ทั้ง 3 ด้าน
  • ชุดทดสอบที่ไม่เคยใช้เลือกโมเดล (802 รายการ): ทำผลงานไม่แพ้โมเดลตั้งต้นในชุดใดเลย (ชนะ 5 เสมอ 2) และได้ผลเสมอเท่ากับรุ่น 0.2 ครบทั้ง 7 ชุด
  • ชุดทดสอบจริงภายใน (ไม่เผยแพร่): ชุดแรก 601 ฉบับ มีความถูกต้อง 0.609 ของช่องข้อมูลที่ตรวจ (รุ่น 0.2 ทำได้ 0.602) และชุดที่สอง 117 ฉบับ ระบบตรวจไม่รับคำตอบที่ผิดเลยแม้แต่ฉบับเดียว
  • ระบบตรวจ (trust gate): ไม่รับคำตอบที่ผิดเลยในชุดสังเคราะห์ 3 ชุด (387 ใบ) รวมถึงภาพใบเสร็จปั๊มน้ำมันจริง 1 ใบ โดยรับรองอัตโนมัติ 31 ใบ (4–10% ต่อชุด) ส่วนที่เหลือส่งต่อให้คนตรวจทาน
  • ต้องเปิด loop guard: จำเป็นต้องเปิดใช้งาน guard สำหรับการอ่านทั้งหน้าเสมอ โดยผลการทดสอบข้างต้นทั้งหมดวัดผลขณะเปิดใช้งาน guard
  • ข้อจำกัดที่พบ: ในใบเสร็จปั๊มน้ำมันบางรูปแบบ โมเดลอาจอ่านยอดรวมผิดพลาด (แต่ระบบตรวจจับได้จากการคำนวณ) บางครั้งมีการเติมข้อมูลการชำระเงินที่ไม่มีอยู่ในใบ และบางครั้งสับสนระหว่างอักษร ธ กับ ท ในชื่อผู้ซื้อ
  • ข้อควรระวัง: ข้อมูลบัญชีที่ใช้เทรนเป็นข้อมูลสังเคราะห์ทั้งหมด จึงไม่ควรลงบัญชีโดยอัตโนมัติหากคำตอบไม่ผ่านระบบตรวจหรือไม่มีคนตรวจทาน และห้ามใช้กับบัตรประชาชนหรือเอกสารส่วนตัว

Intended use & limits

Use it for:

  • Transcribing Thai (and Thai/English) business documents to Markdown for search, archiving and downstream parsing.
  • Extracting accounting fields from Thai tax invoices, abbreviated tax invoices, credit/debit notes, 50 ทวิ withholding-tax certificates, bank transfer slips and billing notes into JSON.
  • The extraction stage of a pipeline in which every JSON answer passes a deterministic check and failing documents go to a person.

Know its limits:

  • The accounting training data is synthetic. No real Thai tax invoice, receipt, slip, 50 ทวิ or billing note was used for training. Expect lower accuracy on real layouts than the synthetic numbers suggest.
  • Do not book entries automatically unless each answer passes the trust gate with an OCR cross-read, or a person reviews it. The model can produce plausible but wrong tax IDs, dates and names.
  • Real phone photos of receipts are still error-prone. On some fuel-station receipts the model reads the wrong line as the total; it may fill payment fields (bank, account, PromptPay) the receipt does not print; and it can confuse ธ and ท in buyer names.
  • No ID cards or personal documents (ID cards, passports, house registrations, medical records). The model was not trained or evaluated on them, and processing them raises PDPA obligations this card does not address.
  • Not for general visual question answering or for languages other than Thai and English.

The full list is in Known limitations.

Details

Modes and output formats

Netra-2B is typhoon-ai/typhoon-ocr1.5-2b (Qwen3-VL-2B architecture) with a LoRA adapter trained on Thai accounting and government documents (training round 11, continued for one epoch in round 13 and one more epoch in round 24), merged into the base at full strength. One set of weights does three jobs:

Mode Input Output
Page reading page image + OCR_PROMPT (the Typhoon OCR prompt) Markdown, tables as one-line HTML, <figure> descriptions
Accounting extraction (KIE) page image + KIE_PROMPT one JSON object, fixed 28-key schema
Key mapping page image + a prompt naming the keys you want JSON with exactly the asked keys

Reading output:

Element Format
Text Markdown; title as # …; reading order left column, then right column, top to bottom
Tables HTML on one line: <table><tr><td>…</td></tr></table>; no <th>, no <thead>/<tbody>; colspan/rowspan kept
Pictures, logos, stamps, charts <figure>…</figure> with a Thai description
Page numbers <page_number>…</page_number>
Checkboxes ☐ / ☑
Equations LaTeX, $…$ and $$…$$
Digits in reading mode as printed (Thai digits stay Thai digits; a dashed tax ID stays dashed)

KIE JSON schema

Every object has all 28 keys. A field the document does not have is null.

Key Type Notes
doc_type string tax_invoice, abbreviated_tax_invoice, credit_note, debit_note, wht_certificate, transfer_slip, billing_note; also invoice, quotation, receipt, payment_voucher
doc_title string printed title, plus the English subtitle when printed
doc_no string document number; for a transfer slip, the transaction reference
book_no string เล่มที่ (receipt, 50 ทวิ)
date, due_date YYYY-MM-DD Gregorian, converted from พ.ศ.
time HH:MM[:SS] POS and transfer slips
seller, buyer, payer, payee party {name, tax_id, branch, address, phone}; tax_id 13 digits, no dashes; branch 5 digits, head office "00000", null when none is printed; name without the branch suffix
items list {desc, qty, unit, unit_price, amount}; billing note: {doc_no, date, due_date, desc, amount}; [] when none
subtotal, discount, vat_base, vat, wht, total, net_paid number discount 0 when none; total includes VAT, before WHT; net_paid = total − WHT
vat_rate, wht_rate number percent; wht_rate null when rates are mixed
vat_included bool line prices already include VAT
amount_in_words string จำนวนเงินตัวอักษรภาษาไทยโดยไม่ต้องใส่วงเล็บ (50 ทวิ: จำนวนภาษีที่หักและนำส่งไว้)
currency string "THB"
ref_doc_no, ref_date string, date original tax invoice referenced by a credit/debit note
payment object method and details (cash / transfer / cheque / card / QR / PromptPay fields)
extra object ข้อมูลเฉพาะตามประเภทเอกสาร เช่น 50 ทวิ: form, income[], funds; ใบลดหนี้/ใบเพิ่มหนี้: adjustment, difference

Normalisation: all digits Arabic. Numbers are JSON numbers (int when whole, else at most 2 decimals). Money printed blank or - is 0. Masked account numbers and names on slips stay masked as printed.

Shape of an answer (fictitious values):

{"doc_type": "tax_invoice", "doc_title": "ใบกำกับภาษี/ใบเสร็จรับเงิน TAX INVOICE/RECEIPT", "doc_no": "INV-0001",
 "book_no": null, "date": "2026-01-15", "time": null, "due_date": "2026-02-14",
 "seller": {"name": "บริษัท ตัวอย่าง จำกัด", "tax_id": "0000000000001", "branch": "00000", "address": "…", "phone": null},
 "buyer": {"name": "ห้างหุ้นส่วนจำกัด ทดสอบ", "tax_id": "0000000000001", "branch": "00000", "address": "…", "phone": null},
 "payer": null, "payee": null,
 "items": [{"desc": "ค่าบริการ", "qty": 1, "unit": null, "unit_price": 1000, "amount": 1000}],
 "subtotal": 1000, "discount": 0, "vat_base": 1000, "vat_rate": 7, "vat": 70, "vat_included": false,
 "wht_rate": null, "wht": null, "total": 1070, "net_paid": null,
 "amount_in_words": "หนึ่งพันเจ็ดสิบบาทถ้วน", "currency": "THB", "ref_doc_no": null, "ref_date": null,
 "payment": null, "extra": {"po_no": null, "salesperson": null, "copy": null, "note": null}}

Loop guard

On a small share of pages the model repeats one line or phrase, often until the token limit. Without the guard, degenerate() flags 7 of the 120 v0.2 ThaiOCRBench outputs (v0.1: 9; v0.3 was scored with the guard only). With the guard, no v0.3 output on ThaiOCRBench is left looping. The guard detects the loop and generates once more with stronger anti-repetition. degenerate() ships in loop_guard.py and needs only the standard library:

from loop_guard import degenerate   # True if a non-trivial line repeats ≥ 8× or a 15–80 char span repeats ≥ 6× in a row

text = generate(page, do_sample=False, repetition_penalty=1.05)
if degenerate(text):
    text = generate(page, do_sample=False, repetition_penalty=1.25, no_repeat_ngram_size=16)

What was measured:

  • On ThaiOCRBench the guard was measured with transformers generate (see ThaiOCRBench). There the first pass used repetition_penalty=1.1, not the 1.05 recommended here. It regenerated 8 of 120 v0.3 outputs (v0.2: 8).
  • On Netra-Bench-Real it was measured with vLLM, whose SamplingParams has no no_repeat_ngram_size: an output is regenerated once with repetition_penalty=1.25 when degenerate() flags it or it hits the token limit (12 of 147 v0.2 outputs). The transformers retry above has not been measured with vLLM; to use it, re-run the flagged pages through transformers.
  • The retry also breaks legitimately repeated table cells. On ThaiOCRBench tables it cost v0.2 0.016 CER compared with no guard (0.302 vs 0.286; still better than the base, 0.308). This cost was not measured on v0.3.

vLLM (offline batch)

This is the configuration used for Netra-Bench-Real and the hold-out sets below (vLLM 0.31.0; loop guard only where a row says so).

from transformers import AutoProcessor
from vllm import LLM, SamplingParams

model_id = "botnick/Netra-2B"
processor = AutoProcessor.from_pretrained(model_id)
llm = LLM(model=model_id, max_model_len=8192, max_num_seqs=32, seed=0,
          limit_mm_per_prompt={"image": {"count": 1, "width": 1400, "height": 1400}, "video": 0})

def chat(prompt):
    return processor.apply_chat_template(
        [{"role": "user", "content": [{"type": "image"}, {"type": "text", "text": prompt}]}],
        tokenize=False, add_generation_prompt=True)

read = SamplingParams(temperature=0.0, max_tokens=4096, repetition_penalty=1.05)
extract = SamplingParams(temperature=0.0, max_tokens=2048, repetition_penalty=1.05)

pages = [load(p) for p in ["a.png", "b.png"]]          # load() from the quick start
reqs = [{"prompt": chat(OCR_PROMPT), "multi_modal_data": {"image": im}} for im in pages] + \
       [{"prompt": chat(KIE_PROMPT), "multi_modal_data": {"image": im}} for im in pages]
outs = llm.generate(reqs, [read] * len(pages) + [extract] * len(pages))

An OpenAI-compatible server (vllm serve botnick/Netra-2B --max-model-len 8192) accepts the same prompts. Send the image as an image_url content part and set temperature=0, repetition_penalty=1.05. The server path has not been benchmarked for this card.

Key mapping with your own keys

Name the keys you want. The answer uses exactly those keys, in that order, with null when a key is absent. The prompt decides whether values are copied verbatim or normalised. An example in the style of the training prompts:

ดึงข้อมูลต่อไปนี้จากเอกสาร ตอบเป็น JSON อย่างเดียว:
เลขที่ใบกำกับภาษี
วันที่ออกเอกสาร
ยอดรวมทั้งสิ้น
Seller Tax ID
(ตัวเลขเป็นตัวเลข, วันที่แบบ YYYY-MM-DD, ไม่มีให้ใส่ null)

Ask for "values exactly as printed" instead and the answer keeps the page's own strings (Thai digits, commas and dashes).

Release gate

The release rule was written down before the round-5 results were read: the model must lose to the base on no hold-out set and no ThaiOCRBench task, and since 2026-10-22 the trust gate must accept no wrong answer on any synthetic test set, and a real fuel-station receipt photo must be either read right or rejected by the gate. For v0.3 one rule was added: no hold-out set may be a loss against v0.2 (paired bootstrap 95% CI).

v0.3 (round 24) passes every rule:

Rule v0.3 result
ThaiOCRBench, lose to the base on no task (with the loop guard) Document parsing 0.1829 vs 0.2179, Full-page OCR 0.3373 vs 0.3586, Table parsing 0.2847 vs 0.3076
Hold-out, no loss against the base 5 wins, 2 ties
Hold-out, no loss against v0.2 7 ties
Trust gate, 0 wrong answers accepted on synth2/val, synth3/val, synth4/val 0 / 0 / 0
Real fuel-station receipt photo (test only) 14 of 20 fields right; the gate rejects it

ThaiOCRBench was scored for v0.3 with the guard only, so the guard is part of the recommended inference. Unlike v0.2, the Document-parsing margin over the base (0.035) is not a tie.

The rule compares with the base and v0.2, not with every earlier release. v0.3 does not beat v0.2 or v0.1 everywhere:

  • ThaiOCRBench Document parsing CER with the guard is higher than v0.1's (0.183 vs 0.172). Full-page OCR (0.337 vs 0.340) and Table parsing (0.285 vs 0.293) are lower than v0.1's. All three are lower than v0.2's.
  • Accounting KIE on synth4/val (look-alike names): every field right on 0.580 of documents vs 0.600 for v0.2.
  • Hold-out Thai government documents: 0.576 vs 0.603 for v0.2, a tie, but the CI upper end is close to 0 (−0.027 [−0.064, +0.002]).
  • On the real fuel-station photo it fills four payment fields that are not printed (round 19, an earlier unreleased round, did not).
  • Netra-Bench-Real was not run on v0.3; its numbers below are for v0.2 and earlier.

Several rounds were tested against these rules after v0.2 (rounds 16–24, see Rounds); round 24 is the only one that passed them all. Choosing among rounds on the same gate sets makes its pass slightly optimistic. The replacement was a maintainer decision, not an automatic one.

v0.2 (round 13)

v0.2 passed only with the loop guard. Without it, ThaiOCRBench Document parsing was worse than the base (CER 0.242 vs 0.218); with it, 0.2173 vs 0.2179: a pass by the rule, not evidence of a real gain at n = 40. v0.2 did not beat v0.1 everywhere: Netra-Bench-Real reading with the guard was 0.013 lower (paired difference −0.0132, standard error 0.0140), ThaiOCRBench CER with the guard was higher than v0.1's on all three tasks, and hold-out FinTabNet was 0.804 vs 0.814. It replaced v0.1 because extraction gains were large: Netra-Bench-Real extraction with the guard +0.163 (standard error 0.066), and 0.638 vs 0.495 of 105 fields on 8 real receipts (test only, not released).

Two merge strengths of round 13 were tested against the rule. Strength 0.85 was tested first and failed (Document parsing 0.2227 vs 0.2179 with the guard). Strength 1.0 was then tested on the same 120 pages and passed. Choosing between two strengths on the gate set makes that pass slightly optimistic.

Round 13 was first blocked (2026-10-24) by the trust gate, which accepted wrong shop names spelled one mark off. Rounds 14 and 15 added training data for that error and were not released (see Rounds). Instead the gate gained a character-level third reader on party names (2026-10-26), with which round 13 accepts no wrong answer. That check was added after the false accepts on these test sets had been seen, so the gate's 0 is measured on sets that are no longer fully unseen for the gate.

Netra-Bench-Real

v0.3 was not scored on this benchmark. The rows below are v0.2 and earlier rounds (rounds 16–18 are in Rounds); use ThaiOCRBench and the hold-out sets to compare v0.3.

147 real Thai documents selected from the ThaiOCRBench test split (typhoon-ai/ThaiOCRBench, CC BY-SA 4.0, human-annotated). Selection: category in Finance, Retail, Food & Beverage, Utilities or Insurance, and the question or answer contains a money/tax keyword (ใบเสร็จ, ใบกำกับ, receipt, invoice, ภาษี, VAT, ยอด, บาท, ชำระ, สลิป, โอน).

  • Test only. No ThaiOCRBench image appears in any training source (checked by image path and ID against all 23 training files of rounds 11 and 13, the two rounds v0.2 was trained in; content-level near-duplicates were not checked). Round 24 (v0.3) added only images from in-house synthetic generators.
  • Category mix: Finance 59, Food & Beverage 29, Retail 24, Insurance 21, Utilities 14.
  • Reading (113 docs; Full-page OCR, Document parsing, Table parsing, Text recognition, Handwritten, Fine-grained): the model gets OCR_PROMPT. Score = 1 − min(1, Levenshtein / reference length) after removing <figure> blocks and tags, markdown symbols and extra whitespace on both sides. Table parsing scores only the <table>…</table> span. Higher is better.
  • Extraction (34 docs; Key information extraction, Key information mapping): the model gets the benchmark's own question. Score = share of reference values found verbatim (whitespace-normalised) in the output. Higher is better.
  • Engine: vLLM 0.31.0, greedy, repetition_penalty=1.05, settings as in the quick start. No loop guard unless the row says "+ loop guard" (the vLLM retry described in Loop guard). Same 147 document IDs for every model.
Model Merge strength Reading (113) Extraction (34)
typhoon-ocr1.5-2b (base) — 0.6659 0.4058
typhoon-ocr1.5-3b-qat (larger sibling, reference) — 0.6691 0.4738
round 3 (rejected) 1.0 0.5729 0.4881
round 4 1.0 0.6415 0.506
round 4 (considered for v0.1, not shipped) 0.78 0.6663 0.483
round 5 0.70 0.6819 0.5345
round 5 0.78 0.6841 0.5422
round 5 0.85 0.6798 0.533
round 5 — Netra-2B v0.1 (previous release) 1.0 0.7091 0.575
round 5 — v0.1 + loop guard 1.0 0.7061 0.5456
round 6 (not released) 0.85 0.6945 0.5324
round 7 (not released) 0.85 0.6751 0.5763
round 8 (not released) 0.85 0.6795 0.5652
round 9 (not released) 1.0 0.659 0.5562
round 9 (not released) 0.78 0.69 0.5303
round 10 (not released) 1.0 0.6782 0.5823
round 11 (not released) 0.85 0.6762 0.5811
round 12 (not released) 1.0 0.6653 0.5639
round 13 (not released) 0.85 0.6737 0.6741
round 13 + loop guard (failed the gate) 0.85 0.7030 0.6800
round 13 — Netra-2B v0.2 (previous release) 1.0 0.6802 0.7126
round 13 — v0.2 + loop guard 1.0 0.6929 0.7089

Other models, same 147 documents, harness and prompts (reference only):

Model Reading (113) Extraction (34) Note
datalab-to/chandra-ocr-2 0.6998 0.0282 page reader; does not answer extraction questions as JSON, so its extraction score is not a fair comparison
Qwen/Qwen3-VL-8B-Instruct 0.5412 0.6577 4× larger general model; best extraction measured here
google/gemma-4-12B-it (w4a16 quantised) 0.3828 0.6663 quantised build; extraction strong, reading weak
Pathumma-llm-vision 3.0.0 0.5474 0.3626

v0.2 has the best extraction score measured here (0.713, ahead of the 8B and 12B general models). Without the guard its reading (0.680) is below v0.1 (0.709) and chandra-ocr-2 (0.700); with the guard it is 0.693.

How to read this table:

  • This benchmark is the selection set: rounds and merge strengths were compared on it, so the numbers of the chosen models are somewhat optimistic. The hold-out sets and ThaiOCRBench (below) are the independent checks.
  • Paired difference, v0.2 − base, computed per document, no guard: reading +0.0142 (standard error 0.0225), extraction +0.3068 (standard error 0.0822). The reading difference is within noise; the extraction gain is about 3.7 standard errors. Per-model standard error of the mean is about 0.03 for reading and 0.07 for extraction.
  • Paired difference, v0.2 − v0.1, both with the guard: reading −0.0132 (standard error 0.0140), extraction +0.1633 (standard error 0.0663).
  • Per document, v0.2 vs base (no guard): 63 better, 50 worse, 34 equal. v0.1 vs base: 62 better, 54 worse, 31 equal.
  • Outputs that hit the 4,096-token limit, no guard: v0.2 9 of 147, v0.1 7.
  • The typhoon-ocr1.5-3b-qat row was run with the same harness, prompts and vLLM settings.
  • Round 1–3 reports quote HF-generate numbers for the base (0.657 / 0.434). Compare numbers within one engine only.

Per task (mean score, same runs):

Task n Base v0.1 v0.1 + guard v0.2 v0.2 + guard
Table parsing 42 0.650 0.716 0.698 0.665 0.675
Document parsing 39 0.728 0.756 0.767 0.736 0.766
Key information extraction 17 0.516 0.424 0.424 0.752 0.741
Key information mapping 17 0.296 0.726 0.667 0.673 0.677
Text recognition 14 0.582 0.588 0.588 0.587 0.587
Full-page OCR 10 0.823 0.896 0.892 0.899 0.888
Handwritten content extraction 6 0.531 0.563 0.564 0.500 0.500
Fine-grained text recognition 2 0.000 0.000 0.000 0.000 0.000

Tasks with n ≤ 10 move by large steps per document; do not read trends into them. Key information extraction (free-form questions about menus, receipts and similar) rose from below the base in v0.1 (0.424 vs 0.516) to 0.752. Key information mapping (pair given items with given values) is below v0.1 without the guard (0.673 vs 0.726). Table parsing is below v0.1 (0.665 vs 0.716 without the guard). Handwriting (n = 6) is below the base.

Throughput (vLLM 0.31.0, one RTX 5090, gpu_memory_utilization=0.4, max_num_seqs=32): 147 documents generated in 59.6 s by v0.2 (v0.1: 70.9 s at 0.6). Not a controlled latency benchmark.

ThaiOCRBench

40 documents per task from the ThaiOCRBench test split (the same 120 documents for every row). Metric: CER after tag/whitespace normalisation (table: table span only); lower is better. 22 of these 120 documents are also in Netra-Bench-Real. Engine: transformers generate (Unsloth 2026.10.7, transformers 5.17.0), greedy, repetition_penalty=1.1, max_new_tokens=4096; loop-guard retry with repetition_penalty=1.25, no_repeat_ngram_size=16. Any higher mean CER than the base counts as a loss under the release gate.

Grouped bar chart of ThaiOCRBench character error rate, lower is better, 40 documents per task; Netra versions with the loop guard, base without. Full-page OCR: base 0.359, v0.1 0.340, v0.2 0.343, v0.3 0.337. Document parsing: 0.218, 0.172, 0.217, 0.183. Table parsing: 0.308, 0.293, 0.302, 0.285.

Task (n = 40) Base v0.1 + loop guard v0.2, no guard v0.2 + loop guard v0.3 + loop guard (recommended) Pass? (v0.3 + guard)
Full-page OCR CER 0.3586 0.3401 0.3550 0.3427 0.3373 yes (better by 0.021)
Document parsing CER 0.2179 0.1722 0.2422 0.2173 0.1829 yes (better by 0.035)
Table parsing CER 0.3076 0.2929 0.2861 0.3017 0.2847 yes (better by 0.023)
Outputs with whole-output CER ≥ 0.9 (of 120) 21 19 22 20 16 —
Outputs regenerated by the guard (of 120) — — — 8 8 —
  • With the guard, v0.3 is better than the base and than v0.2 on all three tasks. Against v0.1 with the guard it is better on Full-page OCR and Table parsing and worse on Document parsing (0.183 vs 0.172).
  • v0.3 was not run without the guard on this set.
  • Without the guard, v0.2 failed the rule (Document parsing 0.242 vs 0.218). degenerate() flagged 7 of its 120 outputs; the guard regenerated 8. Round 13 at merge strength 0.85 failed the rule with the guard (Document parsing 0.2227); strength 1.0 was tested afterwards on the same 120 pages (see Release gate).
  • Several rounds after v0.2 were scored on these same 120 pages (see Rounds), so v0.3's pass is one of several looks at the same set.
  • v0.1 (for reference): without the guard it failed on Full-page OCR (0.386 vs 0.359); 6 pages scored CER ≈ 1.0 (4 repetition loops, 2 diagram-heavy pages transcribed inside one <figure>, which the metric strips).

Hold-out sets (never used for selection)

802 rows from seven sets that were never used to choose a model. An image-path leak check of every round-24 training file (121,443 trainable images after the evaluation images are removed) against all 802 images found 0 overlap. Scoring is the same as Netra-Bench-Real reading/extraction per row (vLLM, repetition_penalty=1.05, no loop guard). Difference = v0.3 − base (and v0.3 − v0.2) per row, with a paired bootstrap 95% CI (2,000 resamples). "win" and "loss" are used only when the CI excludes 0.

Dot-and-interval chart of the paired difference v0.3 minus base per hold-out set with 95% confidence intervals, and v0.2 minus base above each in light green. Key mapping +0.695, WildReceipt +0.437, PubTabNet +0.242, FinTabNet +0.078, General Thai pages +0.004 are wins; Thai government documents +0.006 and DocAtlas -0.036 are ties. No set is a loss.

Set n Base v0.1 v0.2 v0.3 Δ (v0.3 − base) [95% CI] vs base Δ (v0.3 − v0.2) [95% CI] vs v0.2
Thai government documents (real) 34 0.570 0.580 0.603 0.576 +0.006 [−0.066, +0.076] tie −0.027 [−0.064, +0.002] tie
FinTabNet tables (real) 150 0.727 0.814 0.804 0.805 +0.078 [+0.054, +0.103] win +0.002 [−0.004, +0.007] tie
PubTabNet tables (real) 150 0.572 0.787 0.813 0.814 +0.242 [+0.205, +0.285] win +0.001 [−0.013, +0.014] tie
DocAtlas Thai pages (real) 7 0.631 0.526 0.597 0.595 −0.036 [−0.104, +0.014] tie −0.002 [−0.009, +0.002] tie
WildReceipt key mapping (real) 61 0.347 0.728 0.787 0.784 +0.437 [+0.332, +0.545] win −0.003 [−0.008, +0.000] tie
Key mapping (synthetic + CORD/FATURA) 300 0.272 0.959 0.964 0.966 +0.695 [+0.658, +0.733] win +0.002 [−0.005, +0.009] tie
General Thai pages (rendered) 100 0.976 0.980 0.980 0.980 +0.004 [+0.003, +0.006] win −0.000 [−0.001, +0.000] tie
  • No set is a loss against the base or against v0.2. The v0.3 − v0.1 differences were not bootstrapped.
  • Watch item: Thai government documents are 0.027 below v0.2. It is a tie, but the CI upper end is close to 0. The v0.3 hold-out run used a different machine from the base and v0.2 runs (same scripts and settings); on this set, a base-model re-run on another machine differed from the original by +0.046, so differences of this size may be engine noise.
  • Training used other pages of the same Thai government collection and of FinTabNet, PubTabNet, WildReceipt and the key-mapping generator. Those hold-out rows are therefore in-distribution (different images; the government pages come from different source PDFs). DocAtlas (n = 7) is too small to call.

Thai receipt key mapping (thairocr)

Measured on v0.1 only; not re-run for v0.2 or v0.3. An extra, report-only check, not used to choose or release the model. It uses 1,091 receipt images from the test split of NECTEC thairocr (photorealistic rendered receipts, not scans of real ones), never used in round-5 training. Each prompt names the keys to return (key mapping). vLLM, no loop guard. Key accuracy = correct keys / asked keys, pooled over all rows. Row score = the same per row, averaged (95% CI). No thairocr image is included in this repository.

Model Key accuracy Row score [95% CI] JSON valid Every key right Hit token limit
typhoon-ocr1.5-2b (base) 0.104 0.105 [0.094, 0.117] 0.416 0.002 412 of 1,091
Netra-2B v0.1 0.528 0.525 [0.508, 0.542] 0.973 0.075 1 of 1,091

Accounting KIE on synthetic documents

120 held-out documents from our synthetic set (synth2/val, first 120 KIE rows). The v0.1 rows: transfer slip 24, tax invoice 21, abbreviated tax invoice 21, credit/debit note 19, 50 ทวิ certificate 18, billing note 17. The validation file gained more document types before v0.2 was scored, so the 120 documents of v0.2 and v0.3 (the same documents) also include receipts, delivery notes, statements, utility bills, purchase orders and menus; the rows are not a paired comparison. Prompt KIE_PROMPT; transformers generate, greedy, max_new_tokens=2048, no repetition penalty, no loop guard.

Metrics:

  • Field accuracy over 15 scored fields: doc_type, doc_no, date, seller/buyer name, tax_id and branch, subtotal, discount, vat, wht, total, net_paid, ref_doc_no. Strings are whitespace-normalised; numbers must match within 0.005.
  • Item F1 on (desc, amount).
  • JSON-valid rate.
  • Doc perfect = every scored field and every item right.

Caveat: the base model never saw this schema. Its score measures schema compliance, not reading ability, so this is not a fair head-to-head. The fine-tuned rows are in-distribution (same generator as the training data).

Model JSON valid Field accuracy Item F1 Doc perfect
typhoon-ocr1.5-2b (base) 0.75 0.0368 0.3634 0.0
round 2 (rejected for release) 0.975 0.8962 0.9662 0.483
round 4 @0.78 (considered for v0.1) 0.942 0.8149 0.9482 0.25
Netra-2B v0.1 (round 5) 1.0 0.9082 0.9208 0.542
Netra-2B v0.2 (round 13) 1.0 0.9536 0.9731 0.692
Netra-2B v0.3 (round 24) 1.0 0.9668 0.9633 0.742

The other two synthetic validation sets (v0.2 and v0.3 on the same documents):

Set v0.2 field acc. / item F1 / doc perfect v0.3 field acc. / item F1 / doc perfect
Phone-photo invoices (synth3/val, 117 documents, rebuilt before round 13; not comparable with v0.1) 0.9857 / 0.9853 / 0.838 0.9873 / 0.9865 / 0.838
Photo invoices with look-alike characters in the names (synth4/val, 150 documents, added 2026-10-25) 0.957 / 0.9785 / 0.600 0.9546 / 0.9818 / 0.580

On synth2/val v0.3 has more documents fully right than v0.2 (0.742 vs 0.692) but a slightly lower item F1 (0.963 vs 0.973). On synth4/val it has fewer documents fully right (0.580 vs 0.600): look-alike marks in names are still the weakest case, which is why the gate checks names character by character.

A synthetic tax invoice (fictitious companies) from the held-out set, next to Netra-2B v0.1's JSON output for it: doc_type tax_invoice, doc_no TX7009-0832, date 2027-09-29 converted from the printed Buddhist-era date, seller and buyer names, tax IDs and branches, subtotal 3910, VAT 7% 273.7, total 4183.7. Every scored field is correct.

v0.1 field accuracy by type: tax invoice 0.971, abbreviated tax invoice 0.960, credit/debit note 0.934, transfer slip 0.933, billing note 0.918, 50 ทวิ certificate 0.623. v0.2, same six types: 0.962, 0.967, 0.976, 1.000, 0.937, 0.952. v0.3: 0.983, 0.973, 0.976, 1.000, 0.956, 0.952.

Trust gate

The trust gate auto-accepts a KIE answer only when every deterministic check passes. Otherwise it names the fields a person must check. Checks: required and forbidden fields per doc_type, item sums, the VAT chain, WHT = total × rate, net = total − WHT, tax-ID checksum, Thai baht words, branch suffix rules, and (when an OCR pass is supplied) that dates, names, tax IDs and branches in the JSON are printed in the OCR text.

First replay, on v0.1's KIE outputs (120 synthetic documents; v0.2 and v0.3 are measured in the production replays below):

Mode Accepted Correct among accepted Wrong but accepted Perfect docs rejected Share of perfect docs accepted
Checks without OCR cross-read 87 / 120 (72.5%) 64.4% 31 9 86.2%
With OCR cross-read, gold OCR text 49 / 120 (40.8%) 95.9% 2 18 72.3%
  • Without the cross-read the gate is not sufficient. About 1 in 3 accepted answers is wrong (31 of 87), mostly a wrong month in a date or a one-letter slip in a name. Arithmetic and checksum checks cannot see these.
  • Caveat (first replay): the cross-read used the synthetic ground-truth text in place of a real OCR pass. That is an upper bound: a real OCR pass (for example this model in reading mode) makes its own errors, some shared with the KIE answer. The cross-read with a real OCR pass has not been measured. The 2 wrong answers it accepted were 50 ทวิ certificates with a wrong subtotal.

Production replay (2026-10-22)

The gate was then extended and replayed the way it runs in practice, on Netra's own OCR pass instead of the ground truth (first on v0.1 outputs; v0.2 and v0.3 in v0.2 production gate and v0.3 production gate):

  • Every field scored. A wrong answer counts if any field is wrong, not only the 15 core fields.
  • Field placement checks: item descriptions must be whole table cells with their amount on the same row; party names must not be cut short; a branch must sit in its own party's block; payment fields (bank, account, PromptPay, reference) and item quantities and prices must be printed; labelled extras (copy mark, cashier, credit days, due date) must not be dropped.
  • Second reader: every OCR check must also pass against an independent reader (typhoon-ocr1.5-3b-qat). Netra's own OCR shares its misreadings: 9 of 10 wrong answers accepted in the first own-OCR replay were the same one-letter Thai name slip in both its OCR and its JSON.
  • Token confidence: a free-text value (name, item, address, bank, extras) is sent to a person when any of its tokens has probability below 0.85. The misread names had 0.45–0.84.
Set Pipeline Accepted Wrong but accepted
synthetic accounting, 120 docs own OCR + confidence 18 (15.0%) 1 (copy mark dropped)
synthetic accounting, 120 docs + second reader 16 (13.3%) 1
phone-photo invoices, 117 docs own OCR + confidence 17 (14.5%) 2 (card mask, salesperson dropped)
phone-photo invoices, 117 docs + second reader 8 (6.8%) 0
  • Correct documents rejected by the checks themselves: 0 of 7,200 ground-truth documents.
  • The gate is close to zero wrong answers, but it accepts only 7–15% of documents; the rest go to a person. Raising that share needs a more accurate model, not a looser gate.
  • 36 adversarial mutations of correct answers (invented fields, shifted rows, cut names) are all rejected; they are regression tests.

v0.2 production gate (2026-10-26)

Pipeline: Netra's own OCR pass, a second reader (typhoon-ocr1.5-3b-qat), token confidence (threshold 0.85, fixed in 2026-10-22 on v0.1 outputs, not refitted), and a character-level third reader on party names: Tesseract (tha+eng, page mode 6, system and frequency dictionaries off). Every seller, buyer, payer and payee name in the JSON must appear, whitespace-insensitive, in the Tesseract text. Netra and the second reader both turn a name printed one mark off into the dictionary word (กู้เงิณ read as กู้เงิน); a reader without a dictionary does not. A document whose OCR text, second-reader text or confidence pass is missing is rejected (fail closed).

Round 13 (v0.2) outputs, stage by stage (accepted / wrong but accepted):

Set + second reader + token confidence + character-level names (shipped)
synthetic accounting (synth2/val), 120 docs 32 / 0 16 / 0 4 / 0 (3.3%)
phone-photo invoices (synth3/val), 117 docs 55 / 1 48 / 0 12 / 0 (10.3%)
photo invoices with look-alike names (synth4/val), 150 docs 60 / 14 49 / 11 16 / 0 (10.7%)
  • All 14 wrong answers accepted on synth4/val before the third reader were a name with one look-alike mark.
  • The confidence pass runs in vLLM and the scored KIE answers in transformers; where the two outputs differ (20, 5 and 6 documents), the document is rejected.
  • The cost is a low accept rate. The third reader rejects most correct answers too (it misses many names on photos), so only 3–11% of documents are auto-accepted and the share of fully correct documents accepted falls to 4.8%, 12.2% and 17.8%. Everything else goes to a person.
  • Caveat: the third-reader check was added after the 14 wrong answers on synth4/val had been read. It has no fitted threshold (exact name containment), but these three sets are no longer fully unseen for the gate.
  • Real fuel-receipt photo (test only): the gate rejects v0.2's answer (13 of 20 fields right). The added checks can only reject more, so this was not re-run.

v0.3 production gate

Same pipeline and thresholds as the v0.2 production gate, nothing refitted. Round 24 (v0.3) outputs, stage by stage (accepted / wrong but accepted):

Set + second reader + token confidence + character-level names (shipped)
synthetic accounting (synth2/val), 120 docs 37 / 0 23 / 0 5 / 0 (4.2%)
phone-photo invoices (synth3/val), 117 docs 60 / 1 48 / 0 12 / 0 (10.3%)
photo invoices with look-alike names (synth4/val), 150 docs 62 / 14 46 / 9 14 / 0 (9.3%)
  • 0 wrong answers accepted on all three sets; 31 of 387 documents auto-accepted. The share of fully correct documents accepted is 5.6%, 12.2% and 16.1%.
  • As with v0.2, the wrong answers that pass the second reader on synth4/val are stopped only by the character-level name check.
  • Real fuel-station receipt photo (test only): v0.3 gets 14 of 20 fields right and the gate rejects the answer. The arithmetic checks catch the misread total (the VAT-inclusive split does not add up, and the amount in words does not match), so the error does not depend on the OCR cross-read to be caught.
  • Held-out private real-world test sets (not released): 601 documents and 117 documents. The gate accepted no wrong answer on either set. It also auto-accepted no document on either set, so on real-world documents of these kinds every answer currently goes to a person.

Training

Rounds

All rounds: LoRA on typhoon-ocr1.5-2b, scored on test sets never used in training.

Round Start Data (samples) lr, epochs Real reading / extraction Verdict
r1 base 6,072 (synthetic forms + Thai-Synth-Receipts) 1e-4, 2 0.624 / 0.394 (HF; base 0.657 / 0.434) Not released: full-page OCR CER 13.8% → 26.3% (n = 10), stopped emitting <figure>
r2 base 42,074 5e-5, 1 0.606 / 0.273 (HF) Rejected: answered in its own schema instead of the asked keys; template hallucination; early stop
r3 r2 adapter 25,778 (+ 8,000 key-mapping rows) 5e-5, 1 0.590 / 0.446 (HF); 0.5729 / 0.4881 (vLLM) Rejected: reading below base; tables regressed
r4 base (fresh LoRA) 37,593 (+ table normalisation, self-distillation, real tables) 5e-5, 1 0.6415 / 0.506 (vLLM) at strength 1.0; 0.6663 / 0.483 at 0.78 Considered for v0.1 at 0.78; replaced: hold-out loss on FinTabNet −0.050
r5 — v0.1 (released 2026-10-22) base (fresh LoRA) 38,630 5e-5, 2 0.7091 / 0.575 (vLLM; base 0.6659 / 0.4058) at strength 1.0 Released as v0.1: no hold-out loss; ThaiOCRBench better on 3/3 with the loop guard (Full-page worse without it)
r6 r5 adapter 53,196 (+ phone-photo tax invoices, + 10,000 thairocr key-mapping rows) 5e-5, 1 0.6945 / 0.5324 at 0.85 Not released: below v0.1 on both
r7 r5 adapter 44,931 (r6 without thairocr; 2,070 crawled government pages replace 300) lower lr, 1 0.6751 / 0.5763 at 0.85 Not released: reading below v0.1
r8 base (fresh LoRA) 44,931 (r7 data) 5e-5, 2 0.6385 / 0.5385 at 1.0; 0.6795 / 0.5652 at 0.85 Not released: hold-out ties v0.1 on all 7 sets, real reading lower
r9 base (fresh LoRA) 51,074 (r5 mix + phone-photo invoices + 14,684 free-form extraction questions) 5e-5, 2 0.659 / 0.5562 at 1.0; 0.69 / 0.5303 at 0.78; 0.6916 / 0.5549 at 1.0 with the loop guard Not released: reading below v0.1
r10 base (fresh LoRA) 51,708 (r5 mix + photo invoices + free-form extraction) 5e-5, 2 0.6782 / 0.5823 at 1.0 Not released: reading below v0.1
r11 base (fresh LoRA) 74,774 (r10 + 8,000 photo invoices + receipt-printer rows) 5e-5, 2 0.6397 / 0.5784 at 1.0; 0.676 / 0.5805 at 0.85; 0.709 / 0.5732 at 0.85 with the loop guard Not released: unguarded reading below v0.1; key mapping fell 0.726 → 0.553. Its adapter is the start of r12 and r13
r12 r11 adapter 38,630 (r5 mix replay) 2e-5, 1 0.6646 / 0.5642 at 1.0 Not released: no gain over r11
r13 @0.85 r11 adapter 46,606 (r5 mix + 5,978 matching questions + 1,977 free-form) 2e-5, 1 0.6737 / 0.6741; 0.703 / 0.68 with the loop guard Not released: ThaiOCRBench Document parsing CER 0.2227 vs base 0.2179 with the guard
r13 — v0.2 (released 2026-10-26) r11 adapter 46,606 (same) 2e-5, 1 0.6802 / 0.7126 at 1.0; 0.6929 / 0.7089 with the loop guard Released as v0.2: no hold-out loss; ThaiOCRBench better than the base on 3/3 with the loop guard (Document parsing by 0.0006); trust gate 0 wrong accepted once the character-level name check was added
r14 r13 adapter 63,964 (r13 mix + 5,679 photo invoices with look-alike name swaps + 3,000 photo-invoice replay) 2e-5, 1 0.6604 / 0.6565; 0.6879 / 0.6736 with the loop guard Not released: trust gate (second reader) accepted 9 wrong answers; extraction below r13
r15 r13 adapter r14 mix + 6,500 documents of the same name swaps over 13 document types 2e-5, 1 0.6535 / 0.5922; 0.6719 / 0.6027 with the loop guard Not released: trust gate (second reader) accepted 11 wrong answers; extraction below r13. ThaiOCRBench with the guard 0.193 / 0.335 / 0.264
r16 r13 adapter r13 mix + 6,000 chain-store receipt-printer slips + 1,500 slips without a shop header + 3,000 photo-invoice replay 2e-5, 1 0.675 / 0.650; 0.673 / 0.683 with the loop guard Not released: ThaiOCRBench Full-page OCR worse than the base (0.372 vs 0.359)
r17 r13 adapter r13 mix + smaller chain-store and headerless doses + 2,395 slips with a large-store totals block + replay 2e-5, 1 0.667 / 0.652; 0.657 / 0.650 with the loop guard Not released: real extraction below v0.2 (0.650 vs 0.709 with the guard)
r18 r13 adapter r17 doses + 2,395 VAT-included slips that print no VAT amount 2e-5, 1 0.646 / 0.645; 0.678 / 0.644 with the loop guard Not released: ThaiOCRBench Full-page OCR worse than the base (0.378)
r19 r13 adapter r18 mix with the no-VAT slips cut to 1,200 2e-5, 1 — Not released: hold-out loss against v0.2 on general Thai pages (−0.006)
r20 r13 adapter r19 mix with the no-VAT slips cut to 600 2e-5, 1 — Not released: no gain over r19; ThaiOCRBench Full-page OCR margin 0.005
r21 r13 adapter r19 mix + 1,428 VAT-inclusive tax invoices with the grand total printed first 2e-5, 1 — Not released: ThaiOCRBench Full-page OCR worse than the base (0.382)
r22 r13 adapter r19 mix + 500 of the r21 invoices 2e-5, 1 — Not released: ThaiOCRBench Full-page OCR worse than the base (0.368)
r23 r13 adapter r19 mix + 250 of the r21 invoices 2e-5, 1 — Not released: hold-out loss against v0.2 on general Thai pages (−0.006)
r24 — v0.3 (released) r13 adapter 64,272 (r19 mix + 1,433 fuel-station slips) 2e-5, 1 — Released as v0.3: ThaiOCRBench better than the base on 3/3 with the loop guard; no hold-out loss against the base or v0.2; trust gate 0 wrong accepted

"—": Netra-Bench-Real was not run for rounds 19–24; they were compared on ThaiOCRBench, the hold-out sets, the synthetic KIE sets and the trust gate (see Release gate).

Rounds 10–13 (2026-10-23/24): the free-form extraction questions raise extraction on real documents (0.575 → 0.713 for r13), but every round since r10 reads full pages about 0.03 below v0.1 without the loop guard, mostly from repetition on long tables. Round 11 also lost key mapping: it copied values as printed instead of choosing from the values given in the question. Round 13 added about 6,000 matching questions, built from gold tables so the answer is one of the offered values, and recovered most of it (0.553 → 0.673; v0.1 0.726). Round 13 at strength 0.85 failed the release gate on ThaiOCRBench Document parsing; at full strength it passed and became v0.2 (see Release gate). On one real phone photo of a fuel receipt (test only), v0.2 read 13 of 20 fields right; it still misread the total and the amount in words and filled payment fields the receipt does not print, and the trust gate rejected the answer.

Rounds 14–15 (2026-10-25/26): round 13's trust gate accepted shop names one look-alike mark off (รุ่งรุจิ for printed รุ่งรุจี). Two rounds of generated invoices with such swaps in the names did not remove the error (wrong accepts on synth4/val: 14 for round 13, 8 for round 14, 10 for round 15) and lowered real-document extraction (0.709 → 0.674 → 0.603 with the guard). The fix moved to the gate instead (v0.2 production gate), and round 13, the most accurate on real documents, became v0.2.

Rounds 16–24 (2026-10-28 to 2026-11-08): all continue from the v0.2 adapter for one epoch and add synthetic receipt-printer slips aimed at errors seen on real receipts: chain-store legal names and branch codes, slips without a shop header, totals blocks with promotions, VAT-included slips that print no VAT amount, and (round 24) fuel-station slips. Too much of any one kind raised ThaiOCRBench Full-page OCR error above the base (rounds 16, 18, 21, 22). Rounds 19 and 23 passed ThaiOCRBench but lost to v0.2 on the general Thai pages hold-out set. Round 24 passed every rule and became v0.3. On the real fuel-station photo it still reads the pre-VAT amount as the total and fills payment fields that are not printed; the gate rejects that answer.

Round-8 root cause: the loss is concentrated in long tables. Round 8 runs into the 4,096-token limit (a repetition loop) on 13 of the 147 pages against 7 for v0.1, and a looped page scores near 0. Rounds 7 and 8 share the larger crawled government set, so round 9 returns to the round-5 mix and adds only the phone-photo invoices, to test that cause in isolation. The comparison is being re-run with the loop guard on, as Netra is used in practice.

Round-9 result: the free-form extraction questions it added worked on their own task ("Key information extraction" 0.424 → 0.497), but key mapping fell (0.726 → 0.616) and loops rose again (13 pages hit the token limit against 7 for v0.1), so reading dropped. On a real fuel receipt (test only, not in any training set) round 9 read 19 of 20 fields right against 11 for v0.1 and no longer invented bank details, but its JSON was invalid (it joined two strings with +) and the total was the pre-VAT amount; the trust gate rejected it. v0.1 stays the release.

Round-5 changes, from the round-4 root-cause analysis:

  • Dot-leader runs (". . . .", up to thousands of dots in 860 of 2,850 FinTabNet targets) collapsed to ... in every OCR target. Round 4 had learned to emit them until the token limit.
  • <figure> pages no longer upsampled. Round 4 used ×4, which pushed figure pages to about a quarter of OCR targets and made the model describe figures at length while dropping page text.
  • 4,427 more self-distilled pages (base model outputs, quality-filtered), on top of the 3,959 from round 4. Sources with real gold labels (government pages, FinTabNet, PubTabNet) keep their own labels.
  • 300 real Thai government pages added (see below).
  • Thai-Synth-Receipts: one OCR target per image (68 contradicting duplicates dropped).
  • 2 epochs instead of 1.

v0.3 training: three stages

v0.3 is one LoRA adapter trained in three stages: round 11 from a fresh adapter, round 13 continuing from it (= v0.2), then round 24 continuing from round 13.

Stage Data (samples) lr, epochs Batch Steps Mean train loss / final eval loss Time (1 × RTX 5090)
r11 74,774 5e-5, 2 2 × 4 18,694 0.0238 / 0.1736 not cleanly measured: a host shutdown stopped it at step 18,483, and it was resumed from the epoch-1 checkpoint
r13 46,606 2e-5, 1 2 × 4 5,826 0.0721 / 0.1697 5,878 s
r24 64,272 2e-5, 1 1 × 8 8,034 0.0545 / 0.1686 12,690 s

Rows added in round 24 on top of the round-13 mix (counts as loaded at train start). Every row is synthetic, made by in-house generators; no real receipt was used:

Source r24 rows Task Images Licence
Chain-store receipt-printer slips (legal name lines, branch codes, member blocks), phone-photo style 2,000 reading + KIE synthetic in-house
Receipt-printer slips without a shop header (some cut below the title) 400 reading + KIE synthetic in-house
Receipt-printer slips with a large-store totals block (promotions before the final total) 800 reading + KIE synthetic in-house
VAT-included receipt-printer slips that print no VAT amount (VAT fields null) 1,200 reading + KIE synthetic in-house
Phone-photo versions of synthetic tax invoices (synth3), replay 3,000 reading + KIE synthetic in-house
Fuel-station receipt-printer slips (synth8): VAT-inclusive, one fuel line, totals printed in varied order, phone-photo style 1,433 reading + KIE synthetic in-house

Rows added in rounds 11 and 13 on top of the round-5 mix below (counts as loaded at train start):

Source r11 rows r13 rows Task Images Licence
Synthetic accounting documents (synth2), raised cap 4,987 (r5: 2,495) 2,495 reading + KIE synthetic in-house
Phone-photo versions of synthetic tax invoices (synth3) 8,000 — reading + KIE synthetic in-house
Receipt-printer (POS thermal) synthetic receipts, clean and photo 5,806 — reading + KIE synthetic in-house
Free-form extraction questions, answers cut from gold page text (synthetic sets, Thai-Synth-Receipts) 2,962 1,977 free-form KIE as source as source
Free-form questions answered by Qwen3-VL-8B-Instruct, kept only when every value is printed in the gold text 620 — free-form KIE as source (incl. 105 Thai government pages, see ATTRIBUTION.md) as source; teacher Apache-2.0
Matching questions (pair given items with given values) from gold tables — 5,978 key mapping as source as source

The Qwen-answered rows are the only rows whose answers came from another model; their images are from Thai-Synth- Receipts, the synthetic sets, SmartWhatt, DocAtlas and Thai government pages. The 105 government pages come from 21 PDFs of 20 agencies; 104 of them are from the wider round-7 crawl rather than the 300-page round-5 set. They passed the same filter that drops pages with personal ID numbers or home addresses.

Round-5 data mix

The round-5 mix is replayed inside all three v0.3 stages. Rows as loaded at train start: after per-source caps, after removal of all evaluation and hold-out images, and after replacing a page's own label with the base model's output where the page was self-distilled. A row that has both a reading and a KIE label becomes two samples: 38,630 training samples, 200 validation.

Source Rows Task Images Licence
In-house synthetic forms (invoice, quotation, receipt, payment voucher) 1,476 reading synthetic in-house
In-house synthetic Thai accounting documents (6 types) 2,439 reading + KIE synthetic in-house
KIE labels for the synthetic forms 1,383 KIE synthetic in-house
Thai-Synth-Receipts 3,000 reading synthetic MIT
Thai Wikipedia text rendered as articles/reports/posters 8 own label (+1,394 pages in self-distillation) reading synthetic render CC BY-SA 4.0 (text)
SmartWhatt thai_doc_parsing (Thai government publications) 39 own label (+1,201 pages in self-distillation) reading real ODC / CC BY / CC BY-SA (per document)
Thai government documents (procurement notices, budget reports, agency financial statements, blank official forms; 13 agencies) 300 reading real not copyrighted (Copyright Act B.E. 2537, section 7)
iapp Thai handwriting 2,101 reading real Apache-2.0
CORD v2 (receipts) 760 partial KIE (annotated keys only) real CC BY 4.0
FATURA2 (invoices) 1,481 partial KIE (annotated keys only) template-generated CC BY 4.0
Key-mapping rows built from the synthetic sets, CORD and FATURA 8,000 key mapping as source as source
Self-distillation (base outputs on train-split images of the sources in this table) 8,386 reading as source base output (Apache-2.0); images as source
FinTabNet.c (table crops → HTML) 2,850 tables real CDLA-Permissive-2.0
PubTabNet (table crops → HTML) 2,850 tables real CDLA-Permissive-1.0
DocAtlas Instruct, Thai rows 31 own label (+537 pages in self-distillation) reading real CC BY 4.0
WildReceipt 1,168 key mapping real Apache-2.0

Every filled-in Thai accounting document in training (tax invoices, receipts, 50 ทวิ, slips, billing notes) is synthetic. The real Thai pages are government publications and Thai handwriting. The government pages (new in round 5) were issued by ministries, departments, state agencies and local administrations, which section 7 of the Thai Copyright Act B.E. 2537 excludes from copyright. Pages showing private individuals' ID numbers or home addresses were filtered out. No customer documents were used.

Hyperparameters

Setting Value
Method LoRA on vision and language layers, attention + MLP
Rank / alpha / dropout 16 / 16 / 0
Trainable parameters 23,724,032
Schedule cosine, warmup ratio 0.05
Batch 8 per step: 2 × 4 gradient accumulation (r11, r13), 1 × 8 (r24)
Optimiser AdamW 8-bit, weight decay 0.01
Precision bf16
Image size long side ≤ 1400 px
<figure> upsampling none
Seed 3407
Learning rate, epochs, losses, time per stage: see v0.3 training (round 5 / v0.1: 5e-5, 2 epochs, 9,658 steps, 0.0953 / 0.1692, 17,550 s)
Software Unsloth 2026.10.7, transformers 5.17.0, TRL 1.15.0, PEFT 0.21.2
Merge LoRA merged into the base at full strength (1.0), bf16. For round 13, strengths 0.85 / 0.78 were evaluated and 0.85 failed the release gate; round 24 was evaluated at 1.0 only

Known limitations

From the per-round root-cause analyses. Items marked not re-measured have not been checked on v0.3.

  • Fuel-station receipts: total misread. On a real fuel-station receipt photo (test only), v0.3 reads the pre-VAT amount as the total and writes the amount in words to match. The gate's arithmetic checks catch it (the VAT-inclusive split does not add up) and reject the answer. Round 24 added 1,433 synthetic fuel-station slips for this error; it did not remove it on that photo.
  • Payment fields filled when absent. On the same photo, v0.3 fills bank, account number, account name and PromptPay fields that the receipt does not print. The gate requires payment fields to be printed in the OCR text; treat any payment field as unverified unless it passed that check.
  • Buyer names: ธ and ท. The model sometimes reads ธ as ท (or the reverse) in buyer names. The character-level name check is meant to catch this, but check party names by eye before using them.
  • Real-world documents are rarely auto-accepted. On two held-out private real-world test sets (601 and 117 documents, not released) the gate accepted no wrong answer, but it also auto-accepted no document. Expect every real receipt to go to a person.
  • Look-alike marks in names. On synth4/val, v0.3 gets every field right on 0.580 of documents (v0.2 0.600).
  • Page reading on Netra-Bench-Real is not re-measured. v0.2 read 0.013 below v0.1 there with the guard (0.693 vs 0.706). On ThaiOCRBench, v0.3 is below v0.1 on Document parsing (CER 0.183 vs 0.172) and better on the other two tasks.
  • Repetition loops. Without the loop guard a few pages loop until the token limit (ThaiOCRBench: 7 of 120 v0.2 outputs flagged; Netra-Bench-Real: 9 of 147 v0.2 outputs hit the limit, v0.1 7). v0.3 was scored with the guard only; use it. The guard is measured with transformers only; with vLLM, flagged pages must be re-run (see Loop guard). Diagram-heavy pages can still be transcribed entirely inside one <figure> block.
  • Template hallucination. Round 2 transcribed a restaurant menu with an invented shop address and TAX ID: line. Cause: most accounting training targets are synthetic documents with shared header layouts. A plausible fabricated tax ID is the most damaging error for accounting use. Not re-measured; a hallucination probe set is planned. Always cross-check extracted tax IDs against an independent OCR pass.
  • The trust gate needs an OCR cross-read. Without it (measured on v0.1), the gate accepted 72.5% of v0.1's synthetic KIE answers, and only 64.4% of those were fully correct (wrong months in dates, one-letter name slips). Use the gate only in cross-read mode with a real OCR pass, the second reader and the character-level name check (see Trust gate); it then auto-accepts only 4–10% of synthetic documents (v0.3).
  • Early stop on long pages. Round 2 returned 30–190 characters where the reference was 600–2,000. Short synthetic targets dominate the length distribution. Rounds 4–5 added distilled long pages; output/reference length ratio not re-measured.
  • Tables. With the loop guard, ThaiOCRBench table CER is 0.285 (base 0.308, v0.2 0.302, v0.1 0.293). On Netra-Bench-Real, v0.2 table parsing was below v0.1 (0.665 vs 0.716 without the guard; v0.3 not measured). The retry's no_repeat_ngram_size=16 also breaks legitimately repeated cells.
  • Accounting data is synthetic. No real Thai tax invoice, receipt, slip, 50 ทวิ or billing note was used for training. Synthetic layouts are low-entropy (round 1 reached train loss 0.0177), so accuracy on unseen real layouts is lower than the synthetic KIE numbers suggest. In one real phone photo of a VAT-inclusive tax invoice, an earlier round (r4) read every key field correctly in reading mode. In KIE mode it returned invalid JSON, recomputed VAT on top of the printed VAT-inclusive total and invented payment fields. On 8 real receipts (test only, not released) v0.2 got 0.638 of 105 fields right (v0.1 0.495): better, but far from bookable without review. 50 ทวิ certificates were the weakest synthetic type in v0.1 (field accuracy 0.623; v0.2 and v0.3 0.952).
  • Small real test sets. Netra-Bench-Real has 113 reading and 34 extraction documents; standard error ≈ 0.03 on reading means and ≈ 0.07 on extraction means. Differences under ~0.05 (reading) are not distinguishable from noise. v0.2's extraction gain over the base (+0.307, standard error 0.082) is clear; its reading difference from the base and from v0.1 is not. ThaiOCRBench uses 40 pages per task.
  • Rounds and merge strength chosen on test sets. Rounds up to 18 were compared on Netra-Bench-Real; rounds 16–24 and the round-13 merge strength were compared on the ThaiOCRBench gate set (see Release gate). The hold-out sets are the independent check, and the Thai government set is 0.027 below v0.2 (a tie, see hold-out).
  • Schema imposition / generic extraction. Round 2 answered free-form questions in its own 28-key schema. Key-mapping data fixed most of it (mapping 0.296 → 0.726 in v0.1). v0.2 answered free-form questions far better (Key information extraction 0.752 vs 0.424 for v0.1 and 0.516 for the base) but paired given items with given values less well than v0.1 (Key information mapping 0.673 vs 0.726). Not re-measured on Netra-Bench-Real for v0.3; on the key-mapping hold-out sets v0.3 ties v0.2.
  • Handwriting (n = 6) scored below the base on v0.2 (0.500 vs 0.531); not re-measured.
  • Fine-grained text recognition scored 0.000 for every model on the 2 documents in the set.
  • Dates. KIE converts พ.ศ. to ค.ศ.; two-digit พ.ศ. years are read as 25yy. Synthetic training dates span 2025–2027.

Licence and attribution

The model weights are released under Apache-2.0, the licence of the base model. Training data carries the terms below. Attribution is required for CC BY, ODC and CDLA sources.

Data Licence Attribution
typhoon-ai/typhoon-ocr1.5-2b (base) Apache-2.0 Nonesung et al., "Typhoon OCR: Open Vision-Language Model For Thai Document Extraction", arXiv:2601.14722 (2026)
Thai-Synth-Receipts MIT DuckerMaster/Thai-Synth-Receipts on Hugging Face
iapp Thai handwriting Apache-2.0 iapp/thai_handwriting_dataset on Hugging Face
SmartWhatt thai_doc_parsing Open Data Common / CC BY / CC BY-SA, per document SmartWhatt/thai_doc_parsing; per-document title, publisher, licence and URL in ATTRIBUTION.md
Thai government documents (rounds 5 and 11) Not copyrighted: Copyright Act B.E. 2537, section 7 Issuing agencies listed in ATTRIBUTION.md
Qwen/Qwen3-VL-8B-Instruct (teacher for 620 free-form answers, round 11) Apache-2.0 Qwen Team, Qwen3-VL; Qwen/Qwen3-VL-8B-Instruct on Hugging Face
Thai Wikipedia CC BY-SA 4.0 Thai Wikipedia contributors; article URLs recorded per training page
CORD v2 CC BY 4.0 Park et al., "CORD: A Consolidated Receipt Dataset for Post-OCR Parsing", NeurIPS 2019 Document Intelligence Workshop; naver-clova-ix/cord-v2
FATURA2 CC BY 4.0 Limam, Dhiaf, Kessentini, "FATURA: A Multi-Layout Invoice Image Dataset for Document Analysis and Understanding", arXiv:2311.11856 (2023); Zenodo record 10371464
FinTabNet.c CDLA-Permissive-2.0 (original FinTabNet: CDLA-Permissive-1.0) Smock, Pesala, Abraham, "Aligning benchmark datasets for table structure recognition", ICDAR 2023, arXiv:2303.00716; IBM FinTabNet, Zheng et al., WACV 2021
PubTabNet CDLA-Permissive-1.0 Zhong, ShafieiBavani, Jimeno Yepes, "Image-based table recognition: data, model, and evaluation", ECCV 2020, arXiv:1911.10683; images from the PubMed Central Open Access Subset
DocAtlas Instruct (Thai rows) CC BY 4.0 Heakl et al., "DocAtlas: Multilingual Document Understanding Across 80+ Languages", arXiv:2605.12623 (2026)
WildReceipt Apache-2.0 Sun et al., "Spatial Dual-Modality Graph Reasoning for Key Information Extraction", arXiv:2103.14470 (2021); OpenMMLab MMOCR
ThaiOCRBench (evaluation only) CC BY-SA 4.0 Nonesung et al., "ThaiOCRBench: A Task-Diverse Benchmark for Vision-Language Understanding in Thai", arXiv:2511.04479 (2025)

Modifications to third-party data: table crops and HTML targets rebuilt from annotations (FinTabNet.c, PubTabNet); markdown normalised to the output conventions above (DocAtlas); key-mapping prompts generated from box labels (WildReceipt); CORD/FATURA labels converted to the KIE schema with unannotated keys removed from the target.

Licence decision for this release: the weights are Apache-2.0. CC BY-SA material (Thai Wikipedia text rendered to pages; 36 page images from 15 CC BY-SA SmartWhatt documents) was a training input only. No training data, page image or label is redistributed with the model, and no ThaiOCRBench image is included in this repository.

Citation

@misc{netra2026,
  title  = {Netra-2B: a Thai accounting-document reader fine-tuned from Typhoon OCR 1.5},
  author = {botnick},
  year   = {2026},
  note   = {Version 0.3},
  url    = {https://huggingface.co/botnick/Netra-2B}
}

Please also cite the base model:

@misc{nonesung2026typhoonocropenvisionlanguage,
  title         = {Typhoon OCR: Open Vision-Language Model For Thai Document Extraction},
  author        = {Surapon Nonesung and Natapong Nitarach and Teetouch Jaknamon and Pittawat Taveekitworachai and Kunat Pipatanakul},
  year          = {2026},
  eprint        = {2601.14722},
  archivePrefix = {arXiv},
  primaryClass  = {cs.CL},
  url           = {https://arxiv.org/abs/2601.14722}
}
Downloads last month
40
Safetensors
Model size
2B params
Tensor type
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for botnick/Netra-2B

Finetuned
(1)
this model
Quantizations
1 model

Datasets used to train botnick/Netra-2B

Papers for botnick/Netra-2B