teach-me-ai / sources / HO-3
⟵ กลับหน้าแทร็กเสริม
HO-3 · Hands-On AI Engineering

Multimodal + OCR — เปลี่ยนภาพ/เอกสารเป็น JSON ที่เชื่อถือได้

⏱️ ~22 นาที 🎯 ถอด pattern “structured visual extraction” + ชั้น validate ภายนอก แล้ว map ไป NestJS 📦 ต้นทาง: multimodal/ + OCR/ (10 โปรเจกต์)

หมวดนี้รวม 2 กลุ่มที่เกี่ยวกัน: OCR (ดึงข้อมูลจากเอกสาร/ภาพ) และ Multimodal (โมเดลที่รับได้ทั้งภาพ/วิดีโอ/เสียง ไม่ใช่แค่ข้อความ) pattern หัวใจของทั้งหมวดคือสิ่งเดียว: เปลี่ยนของที่ "ไม่มีโครงสร้าง" (ภาพถ่ายใบเสร็จ, PDF, ใบสั่งยา) ให้กลายเป็นข้อมูลมีโครงสร้างที่โค้ดใช้ต่อได้ — ซึ่งตรงกับงาน backend ของคุณเป๊ะ (แนะนำเข้าใจ HO-0 เรื่อง structured output มาก่อน)

OCR แบบเก่า vs Structured Visual Extraction

OCR สมัยก่อนให้ "ก้อนข้อความดิบ" กลับมา แล้วคุณต้องเขียน regex ไล่แกะเอาเอง — เปราะและพังทันทีถ้า layout เปลี่ยน โปรเจกต์ image_to_structured_data อธิบายการก้าวข้ามนี้ไว้ตรง ๆ: "move beyond raw text OCR to Structured Visual Extraction" โดยใช้ library Instructor บังคับให้ VLM (Vision Language Model) ตอบเป็น JSON ตาม schema โดยตรง

แบบเก่า (เปราะ) 🧾 ภาพ OCR → ข้อความดิบ "ยุ่งเหยิง" regex แกะเอง พังเมื่อ layout เปลี่ยน structured visual extraction 🧾 ภาพ 🤖 VLM + schema (Instructor) "เข้าใจ" ภาพแล้ว map ลง object ✅ JSON พร้อมใช้ validate แล้ว = โค้ดใช้ต่อได้เลย
หัวใจของหมวดนี้: ข้ามขั้น "แกะข้อความดิบ" ไปสู่ "VLM + schema" ที่ได้ object พร้อมใช้

นี่คือ pattern เดียวกับ "structured output" ใน HO-0 — แค่ input เป็นภาพแทนข้อความ:

# image_to_structured_data (แนวจริง) — บังคับ VLM ตอบตาม Pydantic schema
class Receipt(BaseModel):
    merchant: str
    date: str
    total: float
    items: list[Item]

# ส่งรูป + schema → ได้ object ที่ validate แล้ว (ไม่ใช่ข้อความมั่ว ๆ)
receipt = client.chat.completions.create(response_model=Receipt, messages=[img])

3 pattern ที่ควรถอดจากหมวดนี้

① Preprocessing ก่อนเข้าโมเดล = คุณภาพพุ่ง

receipt_expense_tracker ทำงาน offline ทั้งหมด (ไม่ต้องมี API key) และมีจุดที่ควรจำ: มันใช้ Pillow ปรับ contrast/ความคมชัดก่อน ส่งภาพเข้าโมเดล README บอกว่าช่วย "significantly with low-light photos and bleached thermal paper" — บทเรียน: อย่าโยนภาพดิบเข้าโมเดลตรง ๆ เตรียมภาพให้ดีก่อน ผลลัพธ์ต่างกันมาก

② ชั้น validate ภายนอก — อย่าเชื่อ LLM ล้วน ๆ

medical_prescription_digitizer ใช้ Mistral Large 3 อ่านลายมือหมอ (ยากมาก) แต่จุดสำคัญคือ มันไม่เชื่อผล LLM ตรง ๆ — เอาชื่อยาที่สกัดได้ไปตรวจกับฐานข้อมูลยาจริง (RxNorm) ยาที่ผ่าน = เขียว, ยาที่ไม่รู้จัก/น่าสงสัย = แดง

💡

pattern พกพา (สำคัญมากในงานจริง): LLM/VLM อาจ hallucinate ค่าที่ดูสมเหตุสมผลแต่ผิด — งานที่เดิมพันสูง (การเงิน, การแพทย์) ต้องมี ชั้น validate ด้วยกฎ/ฐานข้อมูลจริง เสมอ ใน NestJS คือ pipe validation + business rule check หลังได้ JSON กลับมา

③ Multimodal = ขยาย modality ของ RAG

multimodal_rag ต่อยอดจาก HO-2 โดยตรง: รับ input 6 แบบ (text, URL, PDF, ภาพ, เสียง, วิดีโอ) เข้า ChromaDB เดียวกัน แล้วตอนถาม ส่งไฟล์ต้นฉบับให้ Gemini อ่านสด ๆ ส่วน video_understanding_agent ให้ Gemini "reads the video natively" — ไม่ต้องดาวน์โหลด/ถอดเสียงก่อน โมเดลรุ่นใหม่ดูวิดีโอได้เลย

โปรเจกต์เปลี่ยนอะไร → เป็นอะไร
image_to_structured_dataภาพ → JSON ตาม schema (Instructor)
receipt_expense_trackerใบเสร็จ → รายการค่าใช้จ่าย (offline + preprocess)
medical_prescription_digitizerใบสั่งยา → ข้อมูลยา (validate กับ RxNorm)
multimodal_rag6 modality → คำตอบพร้อม citation
video_understanding_agentYouTube URL → สรุป/chapter/action items

map ลงงาน NestJS ของคุณ

  • Structured extraction = pattern เดิมที่คุณทำอยู่แล้ว — กำหนด DTO/Zod schema ส่งไปกับ vision API แล้ว validate ผลลัพธ์ (เหมือน validate request body)
  • Preprocessing = ขั้นเตรียมข้อมูลก่อน pipeline (resize/ปรับ contrast) — ทำใน worker ก่อนเรียกโมเดล
  • ชั้น validate = business rule / lookup กับ DB จริง (เช่น เช็ครหัสสินค้ามีจริงไหม) หลังได้ JSON — อย่าข้าม
  • เก็บผล = JSON ที่ validate แล้วลง PostgreSQL ได้ตรง ๆ (คอลัมน์ jsonb หรือแตกเป็นตาราง)
⚠️

ระวัง: vision model แพงกว่า text model (คิดตามจำนวน/ขนาดภาพ) — resize ภาพให้พอดีก่อนส่ง และงานที่ความถูกต้องสำคัญ ต้องมีทางให้คน review ผลที่โมเดลไม่มั่นใจ (เหมือน prescription ที่ไฮไลต์แดง) ไม่ใช่ปล่อยผ่านอัตโนมัติทั้งหมด

🎯 แบบฝึกหัด
  1. เปิด README ของ OCR/image_to_structured_data/ แล้วตอบว่า "ใช้ Instructor แทนการเขียน regex เอง ได้ประโยชน์อะไร 2 ข้อ"
  2. medical_prescription_digitizer ทำไมต้องเช็คกับ RxNorm ทั้งที่ LLM อ่านออกแล้ว — เขียนอธิบายเชื่อมกับคำว่า hallucination
  3. นึกงานจริงในบริษัทคุณที่ต้องแปลงเอกสารเป็นข้อมูล (เช่น ใบกำกับภาษี, ใบสมัคร) แล้วออกแบบ DTO/Zod schema คร่าว ๆ + บอกว่าจะมี "ชั้น validate ภายนอก" อะไรบ้าง

เมื่อทำเสร็จ พิมพ์ /quiz HO-3 เพื่อทดสอบความเข้าใจ