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"
processor = AutoProcessor.from_pretrained(BASE, max_pixels=1048576)
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)
decoded = processor.batch_decode(out[:, inputs.input_ids.shape[1]:],
skip_special_tokens=True)[0].strip()
print(json.loads(decoded)["natural_text"])