14 KiB
ADR-032: Typhoon OCR & LLM Integration Architecture
Status: Active Date: 2026-05-30 Decision Makers: Development Team, System Architect, AI Integration Lead Related Documents:
- ADR-023: Unified AI Architecture (Base)
- ADR-023A: Unified AI Architecture — Model Revision (gemma4:e2b, 2-Model Stack)
- ADR-016: Security & Authentication
- Feature Specification (spec.md)
🎯 Context and Problem Statement
โครงการ LCBP3-DMS มีความต้องการยกระดับความแม่นยำในการทำ OCR เอกสารภาษาไทยในระบบ OCR Sandbox Runner ให้สูงขึ้น (เป้าหมาย 95%+) โดยใช้โมเดลภาษาไทยเฉพาะทาง และเพิ่มโมเดลภาษาไทยระดับผู้เชี่ยวชาญใน AI Model Management
อย่างไรก็ดี การเพิ่มโมเดลสกัดข้อความที่เป็นวิสัยทัศน์คอมพิวเตอร์ (Vision-Language Model) และโมเดลภาษาขนาดใหญ่ (Large Language Model) เช่น scb10x/typhoon-ocr-3b (~3.5GB VRAM) และ typhoon2.1-gemma3-4b (~4.5GB VRAM) อาจส่งผลให้เกิดปัญหา GPU VRAM Overflow (เกินขีดจำกัด 8GB ของ RTX 2060 Super บน Admin Desktop Desk-5439) หากมีการโหลดเข้าสู่หน่วยความจำพร้อมกับโมเดลพื้นฐานอย่าง gemma4 และ nomic-embed-text.
⚙️ Decision Drivers
- Accuracy Focus: ยกระดับความถูกต้องในการแปลผลภาษาไทยผ่าน
Typhoon OCR-3Bเป็นเอนจินทางเลือกใน OCR Sandbox. - GPU VRAM Budget ≤ 8GB: ต้องควบคุมไม่ให้การโหลดโมเดลรันพร้อมกันจน VRAM ล้นและระบบแครช (Out-of-Memory).
- Graceful Degradation: หากบริการ AI ติดขัดหรือประมวลผลล้มเหลว ระบบ DMS หลักและฟังก์ชัน OCR สำรองต้องยังคงทำงานได้ปกติ.
- Physical Isolation (Zero Trust): รันโมเดลทั้งหมดภายในเครือข่าย On-premises บน Admin Desktop เท่านั้น ห้ามผ่าน Cloud.
🏛️ Proposed Decisions & Architecture
1. การเลือกเอนจินและรุ่นโมเดล (Engine & Model Selection)
- AI Model Option: เพิ่ม
typhoon2.1-gemma3-4bเข้าไปในระบบ AI Model Management สำหรับงานวิเคราะห์ความหมายขั้นสูงในบริบทไทย. - OCR Sandbox Option: วางแผนเพิ่ม
Typhoon OCR-3B(รันบน Ollama ที่เครื่อง Admin Desktop) เป็นตัวเลือกคู่ขนานกับ Tesseract OCR.
2. การส่งไฟล์ระหว่าง Backend และ OCR Sidecar (File Transfer Architecture)
การตัดสินใจ (2026-06-01): เปลี่ยนจาก shared volume mount เป็น multipart HTTP upload ผ่าน endpoint /ocr-upload ใหม่
สาเหตุ: Docker Desktop บน Windows 11 ใช้ WSL2 เป็น backend — Linux VM ภายใน WSL2 ไม่สามารถ bind mount จาก Windows mapped drive letter (Z:) หรือ CIFS named volume ที่ mount ผ่าน Docker Desktop ได้ ทำให้ /mnt/uploads ใน sidecar container ว่างเปล่าเสมอ และเกิด 404 เมื่อ sidecar พยายามเปิดไฟล์
Architecture ใหม่:
Backend (QNAP)
└── fs.readFileSync(pdfPath) ← อ่านจาก /app/uploads/
└── POST /ocr-upload (multipart) ← ส่ง file bytes ผ่าน LAN 2.5 Gbps
└── Sidecar (Desk-5439)
└── fitz.open(stream=pdf_bytes) ← ประมวลผลใน memory
ข้อดีเพิ่มเติม:
- ไม่มี path coupling — sidecar ไม่รู้จัก path ของ backend
- Sidecar ย้าย host ได้โดยไม่ต้องแก้ config mount
- Overhead จาก file transfer < 200ms บน LAN 2.5 Gbps (น้อยกว่า OCR processing time มาก)
- endpoint
/ocr(path-based, legacy) ยังคงอยู่เพื่อ backward compatibility
3. นโยบายการจัดการ VRAM ด้วย Ollama Model Swapping (VRAM Swapping Policy)
เพื่อหลีกเลี่ยงข้อจำกัด 8GB VRAM ของ GPU โดยยังคงใช้โมเดลขนาดใหญ่ได้ ระบบจะเปลี่ยนจากการโหลดโมเดลค้างไว้พร้อมกัน (Simultaneous) เป็น "การทำงานแบบสลับลำดับและจำกัดการจองหน่วยความจำ (Sequential with Ollama keep_alive)":
keep_alive = 0: ในคำสั่งเรียกประมวลผล (Inference) ทุกชนิดไปยังโมเดล Typhoon จะต้องบังคับพารามิเตอร์"keep_alive": 0เพื่อให้ Ollama ทำการคลายโมเดลออกจากหน่วยความจำ GPU ทันทีหลังตอบกลับสำเร็จ คืนพื้นที่ VRAM ให้โมเดลถัดไปทำงานได้ทันที.- Stateless Sidecar: ตัว Python OCR Sidecar Container จะรับตัวแปรสภาพแวดล้อม
OLLAMA_API_URLในdocker-compose.yml(ชี้ไปที่http://192.168.10.100:11434) เพื่อประมวลผล PDF-to-Image และส่งภาพสกัดต่อไปยัง Ollama.
4. Hyperparameters และ System Prompt สำหรับ Typhoon OCR
เพื่อให้ได้ผลลัพธ์การสกัดอักษรภาษาไทยที่ถูกต้องและลดสัญญาณรบกวน (Noise):
- System Prompt:
"สกัดข้อความภาษาไทยและอังกฤษทั้งหมดจากภาพนี้อย่างถูกต้อง รักษาโครงสร้างบรรทัดและการเว้นวรรคให้ใกล้เคียงต้นฉบับมากที่สุด ห้ามเพิ่มคำอธิบายใดๆ" - LLM Hyperparameters:
temperature = 0.0(เพิ่มความเป็นระเบียบและให้ผลลัพธ์คงเดิม)top_p = 0.9repeat_penalty = 1.0(หรือrepetition_penalty)keep_alive = 0
5. ระบบการเก็บแคชชิ่ง (24-Hour Redis Caching)
ระบบจะทำการแคชผลลัพธ์ของการทำ OCR ด้วยโมเดลและไฟล์เดิมไว้เป็นเวลา 24 ชั่วโมง ผ่าน Redis เพื่อลดต้นทุนเวลาประมวลผล (SLA < 60 วินาที/หน้า)
- Cache Key:
ocr:cache:{documentPublicId}:{engine}:{hash} - TTL: 86,400 วินาที (24 ชั่วโมง)
- การเคลียร์แคช: ทำโดยอัตโนมัติเมื่อเอกสารอัปเดต หรือแอดมินสั่งล้างผ่านระบบหลังบ้าน.
6. ระบบสลับเอนจินสำรองอัตโนมัติ (Graceful Fallback)
- หาก Ollama หรือโมเดล Typhoon ไม่สามารถเข้าถึงได้ หรือใช้เวลาทำ OCR นานเกิน 60 วินาที ระบบ NestJS backend (
OcrService) จะทำการสลับเอนจินสำรองไปยัง Tesseract OCR (tha+eng) อัตโนมัติในเวลาไม่เกิน 5 วินาที พร้อมแจ้งเตือนผู้ใช้บนหน้าเว็บอินเตอร์เฟส.
📋 Implementation Status
| Component | Status | File |
|---|---|---|
| SQL delta: ai_audit_logs fields | ✅ Complete | specs/03-Data-and-Storage/deltas/2026-05-30-extend-ai-audit-logs.sql |
| SQL delta: typhoon_ocr_system prompt | ✅ Complete | specs/03-Data-and-Storage/deltas/2026-05-30-add-typhoon-ocr-prompt.sql |
| VRAMMonitorService | ✅ Complete | backend/src/modules/ai/services/vram-monitor.service.ts |
| OcrCacheService (24h Redis) | ✅ Complete | backend/src/modules/ai/services/ocr-cache.service.ts |
| AiAuditLog entity extension | ✅ Complete | backend/src/modules/ai/entities/ai-audit-log.entity.ts |
| OCR Sidecar: Typhoon OCR function | ✅ Complete | specs/04-Infrastructure-OPS/.../ocr-sidecar/app.py |
OCR Sidecar: /ocr-upload multipart endpoint |
✅ Complete | specs/04-Infrastructure-OPS/.../ocr-sidecar/app.py |
| OCR Sidecar: Dockerfile update | ✅ Complete | specs/04-Infrastructure-OPS/.../ocr-sidecar/Dockerfile |
| OCR Sidecar: docker-compose.yml (volumes ลบออก) | ✅ Complete | specs/04-Infrastructure-OPS/.../ocr-sidecar/docker-compose.yml |
| OcrService: multipart upload แทน remapPath | ✅ Complete | backend/src/modules/ai/services/ocr.service.ts |
| SandboxOcrEngineService: multipart upload แทน remapPath | ✅ Complete | backend/src/modules/ai/services/sandbox-ocr-engine.service.ts |
| TyphoonOcrProcessor (BullMQ) | ✅ Complete | backend/src/modules/ai/processors/typhoon-ocr.processor.ts |
| TyphoonLlmProcessor (BullMQ) | ✅ Complete | backend/src/modules/ai/processors/typhoon-llm.processor.ts |
| ai.module.ts registration | ✅ Complete | backend/src/modules/ai/ai.module.ts |
| i18n keys (Thai) | ✅ Complete | frontend/public/locales/th/ai.json |
| OCR Engine Selector (Frontend) | 🔄 Pending | frontend/src/features/ocr-sandbox/ |
| Fallback + Audit integration | 🔄 Pending | backend/src/modules/ai/services/ocr.service.ts |
| Model seeding (Admin Desktop) | 🔄 Manual | Ollama pull on Admin Desktop |
| Unit tests | 🔄 Pending | — |
📋 Consequences
Positive
- ✅ ความแม่นยำภาษาไทยสูง: ได้ความถูกต้อง 95%+ บนข้อความภาษาไทย in Sandbox Runner.
- ✅ แก้ปัญหา VRAM 8GB อย่างยั่งยืน: การใช้
keep_alive = 0และ sequential queue ช่วยให้โมเดลรันแบบหมุนเวียนได้โดยไม่เกิด OOM บน RTX 2060 Super. - ✅ การเชื่อมต่ออิสระ (Stateless Sidecar): ออกแบบสถาปัตยกรรม Sidecar ให้ Stateless และตั้งค่าผ่านตัวแปรสภาพแวดล้อมได้ยืดหยุ่น.
- ✅ มีระบบสำรอง (High Uptime): ผู้ใช้งานสามารถประมวลผลต่อได้ผ่าน Tesseract เสมอแม้โมเดล AI ขัดข้อง.
Negative
- ❌ Overhead ในการโหลดโมเดล (Latency): การตั้งค่า
keep_alive = 0ทำให้การรันงานข้ามคิวอาจเกิดดีเลย์เล็กน้อย (3-5 วินาที) ในการดึงโมเดลเข้า VRAM ใหม่ แต่นับเป็น Trade-off ที่ยอมรับได้เมื่อเทียบกับระบบแครช.
🔄 Review & Maintenance
- Review Cycle: ทุก 6 เดือน หรือเมื่อมีการอัปเกรดเครื่องประมวลผล (Admin Desktop GPU)
- ผู้รับผิดชอบ: AI Integration Lead ร่วมกับ System Architect Team