LoRA adapter on typhoon-ai/typhoon-ocr-7b, fine-tuned to read Thai handwriting from an image and return the transcription as JSON ({"naturaltext": "..."}).
Fuente del modelo
Descripción de la fuente
LoRA adapter on typhoon-ai/typhoon-ocr-7b, fine-tuned to read Thai handwriting from an
image and return the transcription as JSON ({"natural_text": "..."}).
Fuentes
1 fuenteVerificado 11 sept
Artefactos del modelo
3 artefactosExtractos de fuentes
2 extractostyphoon-ai/typhoon-ocr-7b (Qwen2.5-VL-7B, Apache-2.0)max_pixels=1048576), greedy decoding
(do_sample=False), max_new_tokens=512. Other regimes are outside the evaluation scope.This is the evaluation attached to the branch promoted to main:
phase2-downsample-money-keep25-300steps, evaluated on the 559-sample CPE-OPH full test with
1024px images, greedy decoding, and max_new_tokens=512.
| Metric | Promotion baseline | Promoted main | Delta | Direction |
|---|---|---|---|---|
valid_json_rate | 1.0000 | 1.0000 | +0.0000 | higher is better |
raw_cer | 0.1560 | 0.1336 | -0.0224 | lower is better |
normalized_cer | 0.1560 | 0.1336 | -0.0224 | lower is better |
thai_char_accuracy | 0.8440 | 0.8664 | +0.0224 | higher is better |
exact_match_rate | 0.4204 | 0.4526 |
Baseline: phase2-baseline-greedy-res1024. Source:
published metrics artifact.
The CPE-OPH full-test result is not a clean generalization score because gold texts overlap between its train and test splits.
Install dependencies first (qwen-vl-utils is a separate package — hyphens in the pip name,
underscores in the import):
pip install "transformers>=4.49" accelerate peft torch pillow qwen-vl-utils
import json, torch
from PIL import Image
from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
from peft import PeftModel
from qwen_vl_utils import process_vision_info
BASE = "typhoon-ai/typhoon-ocr-7b"
ADAPTER = "sivakorn-su/typhoon-ocr-7b-thai-handwriting-lora-v1" # the `main` adapter
processor = AutoProcessor.from_pretrained(BASE, max_pixels=1048576) # 1024px regime
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(BASE, torch_dtype="auto", device_map="auto")
model = PeftModel.from_pretrained(model, ADAPTER)
model.eval()
PROMPT = (
"Below is an image of a document page along with its dimensions. "
"Simply return the markdown representation of this document, presenting tables in markdown format as they naturally appear.\n"
"If the document contains images, use a placeholder like dummy.png for each image.\n"
"Your final output must be in JSON format with a single key `natural_text` containing the response.\n"
"RAW_TEXT_START\n\nRAW_TEXT_END"
)
image = Image.open("handwriting.png").convert("RGB")
messages = [{"role": "user", "content": [
{"type": "text", "text": PROMPT},
{"type": "image", "image": image},
]}]
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
image_inputs, video_inputs = process_vision_info(messages)
inputs = processor(text=[text], images=image_inputs, videos=video_inputs,
padding=True, return_tensors="pt").to(model.device)
with torch.no_grad():
out = model.generate(**inputs, max_new_tokens=512, do_sample=False) # greedy
decoded = processor.batch_decode(out[:, inputs.input_ids.shape[1]:],
skip_special_tokens=True)[0].strip()
print(json.loads(decoded)["natural_text"])
Prompt note (important): the prompt above is the exact one this adapter was fine-tuned with — Typhoon's
defaulttask template with an emptyRAW_TEXTanchor and no injected page dimensions. Base Typhoon normally runs via thetyphoon-ocrpackage (ocr_document), which builds a richer prompt (OCR anchor text fromget_anchor_text+ real dimensions). Because this adapter was trained on the simplified, empty-anchor prompt, use it as-is — do not substitute the package's full prompt, or inference will mismatch training. (Typhoon: the model only works with its specific prompt templates.)
The Performance table reports only the CPE-OPH evaluation used to promote this adapter to main.
Phase 3 evaluations belong to their experimental branches and are intentionally excluded here.
The result does not establish performance on full document forms, layouts, unseen writers, or
capture conditions outside the evaluation set.
Promoted to main from branch phase2-downsample-money-keep25-300steps after full-test evaluation and
promotion-gate checks. Base: typhoon-ai/typhoon-ocr-7b; trained and evaluated
on Thinnaphat/TH-HANDWRITTEN-CPE-OPH2025.
Apache-2.0, inheriting the base model typhoon-ai/typhoon-ocr-7b → Qwen/Qwen2.5-VL-7B-Instruct.
Training data: Thinnaphat/TH-HANDWRITTEN-CPE-OPH2025 (a subset of iapp/thai_handwriting_dataset,
Apache-2.0). This repository is a LoRA adapter only.
--- license: apache-2.0 base_model: typhoon-ai/typhoon-ocr-7b library_name: peft pipeline_tag: image-text-to-text tags: - ocr - thai - handwriting-recognition - qwen2.5-vl - lora --- # Typhoon OCR 7B — Thai Handwriting LoRA LoRA adapter on `typhoon-ai/typhoon-ocr-7b`, fine-tuned to read **Thai handwriting** from an image and return the transcription as JSON (`{"natural_text": "..."}`). ## Overview - **Base model:** `typhoon-ai/typhoon-ocr-7b` (Qwen2.5-VL-7B, Apache-2.0) - **Task:** Thai handwriting image → text - **Type:** PEFT/LoRA adapter — load on top of the base model (base weights are not redistributed here) - **Intended inference:** images at 1024px (`max_pixels=1048576`), **greedy** decoding (`do_sample=False`), `max_new_tokens=512`. Other regimes are outside the evaluation scope. ## Performance This is the evaluation attached to the branch promoted to `main`: `phase2-downsample-money-keep25-300steps`, evaluated on the 559-sample CPE-OPH full test with 1024px images, greedy decoding, and `max_new_tokens=512`. | Metric | Promotion baseline | Promoted `main` | Delta | Direction | |---|---:|---:|---:|---| | `valid_json_rate` | 1.0000 | 1.0000 | +0.0000 | higher is better | | `raw_cer` | 0.1560 | 0.1336 | -0.0224 | lower is better | | `normalized_cer` | 0.1560 | 0.1336 | -0.0224 | lower is better | | `thai_char_accuracy` | 0.8440 | 0.8664 | +0.0224 | higher is better | | `exact_match_rate` | 0.4204 | 0.4526 | +0.0322 | higher is better | Baseline: `phase2-baseline-greedy-res1024`. Source: [published metrics artifact](https://huggingface.co/sivakorn-su/typhoon-ocr-7b-thai-handwriting-lora-v1/blob/phase2-downsample-money-keep25-300steps/phase2_artifacts/metrics.json). The CPE-OPH full-test result is not a clean generalization score because gold texts overlap between its train and test splits. ## Example use Install dependencies first (`qwen-vl-utils` is a separate package — hyphens in the pip name, underscores in the import): ```bash pip install "transformers>=4.49" accelerate peft torch pillow qwen-vl-utils ``` ```python import json, torch from PIL import Image from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor from peft import PeftModel from qwen_vl_utils import process_vision_info BASE = "typhoon-ai/typhoon-ocr-7b" ADAPTER = "sivakorn-su/typhoon-ocr-7b-thai-handwriting-lora-v1" # the `main` adapter processor = A...
Source context: 24 downloads · 0 likes · Pipeline image-text-to-text · Library peft · Repo sivakorn-su/typhoon-ocr-7b-thai-handwriting-lora-v1
| +0.0322 |
| higher is better |