690603:2041 ADR-034-134 #01
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
# ADR-034: AI Model Change — Thai-Optimized Model Stack
|
||||
|
||||
**Status:** Accepted
|
||||
**Date:** 2026-06-03
|
||||
**Decision Makers:** Development Team, AI Integration Lead
|
||||
**Supersedes:** ADR-023A Section 2.1 (Model Stack & Configuration)
|
||||
**Related Documents:**
|
||||
- [ADR-023A: Unified AI Architecture — Model Revision](./ADR-023A-unified-ai-architecture.md)
|
||||
- [ADR-033: Active Model & OCR Management](./ADR-033-active-model-and-ocr-management.md)
|
||||
- [CONTEXT.md](../../../CONTEXT.md)
|
||||
|
||||
---
|
||||
|
||||
## Context and Problem Statement
|
||||
|
||||
การใช้งาน `gemma4:e2b` (~2GB) เป็นโมเดลหลักในสภาพแวดล้อมภาษาไทย พบว่าประสิทธิภาพด้าน OCR และการสกัดข้อมูลจากเอกสารภาษาไทยยังไม่เพียงพอ จึงต้องเปลี่ยนเป็นโมเดลที่ถูก fine-tune มาสำหรับภาษาไทยโดยเฉพาะ
|
||||
|
||||
**ข้อจำกัด:**
|
||||
- VRAM Budget: RTX 2060 Super 8GB
|
||||
- Main Model + OCR Model ไม่สามารถโหลดพร้อมกันได้ (รวม ~5.7GB ขณะประมวลผล แต่ peak อาจเกิน 8GB)
|
||||
- ต้องรักษา mechanism `keep_alive` และ VRAM monitoring ตาม ADR-033
|
||||
|
||||
---
|
||||
|
||||
## Decision Drivers
|
||||
|
||||
- **Thai Language Optimization:** โมเดลต้องรองรับ OCR และการสกัดข้อมูลภาษาไทยได้ดีกว่า gemma4
|
||||
- **VRAM Safety:** ไม่เกิน 8GB ในทุกสถานการณ์
|
||||
- **Model Switching:** ใช้ BullMQ processor ควบคุมการสลับโมเดลเท่านั้น
|
||||
- **No Direct n8n Access:** n8n ห้ามเรียก Ollama โดยตรง ต้องผ่าน DMS API → BullMQ
|
||||
|
||||
---
|
||||
|
||||
## Decision Outcome
|
||||
|
||||
### Selected Models
|
||||
|
||||
| Model | Role | Base Model | Size | Keep-Alive |
|
||||
|-------|------|------------|------|------------|
|
||||
| `typhoon2.5-np-dms:latest` | Main AI (General + OCR Post-processing + Extraction + RAG Q&A) | `scb10x/typhoon2.5-qwen3-4b:latest` | ~2.5GB | Stand by ตลอด (ไม่ใช่ 0) |
|
||||
| `typhoon-np-dms-ocr:latest` | OCR ภาษาไทย | `scb10x/typhoon-ocr1.5-3b:latest` | ~3.2GB | `0` (unload ทันที) |
|
||||
|
||||
### Key Parameters (Main Model)
|
||||
|
||||
```
|
||||
PARAMETER num_ctx 8192
|
||||
PARAMETER num_predict 2048
|
||||
PARAMETER temperature 0.1
|
||||
PARAMETER top_p 0.85
|
||||
PARAMETER repeat_penalty 1.15
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### 1. Model Files (Desk-5439)
|
||||
|
||||
---
|
||||
|
||||
file: E:\np-dms\lcbp3\specs\04-Infrastructure-OPS\04-00-docker-compose\Desk-5439\typhoon2.5-np-dms.model.md
|
||||
```t
|
||||
# ollama create typhoon2.5-np-dms -f ./typhoon2.5-np-dms.model.md
|
||||
|
||||
FROM scb10x/typhoon2.5-qwen3-4b:latest
|
||||
|
||||
# 1. ปรับขนาดพื้นที่ประมวลผลข้อความ (Context Window)
|
||||
# ตั้งไว้ที่ 16K ถึง 32K ถือว่าเหลือเฟือมากสำหรับเอกสารข้อความ OCR หลายสิบหน้า
|
||||
PARAMETER num_ctx 8192
|
||||
PARAMETER num_predict 2048
|
||||
# 2. ปรับความนิ่งของคำตอบ (Determinism)
|
||||
# บีบให้เป็น 0 เพื่อป้องกันโมเดล "คิดแทน" หรือเดาตัวเลข/วันที่ขึ้นมาเอง (สำคัญมากสำหรับเลขที่เอกสาร)
|
||||
PARAMETER temperature 0.1
|
||||
PARAMETER top_p 0.85
|
||||
PARAMETER repeat_penalty 1.15
|
||||
PARAMETER stop "\n\n"
|
||||
|
||||
# 3. ล็อกบทบาทและโครงสร้างผลลัพธ์ที่ต้องการ (System Prompt)
|
||||
SYSTEM """คุณคือระบบ AI ผู้เชี่ยวชาญด้านการวิเคราะห์และจัดการเอกสารโครงการ (Document Management System)
|
||||
หน้าที่ของคุณคืออ่านข้อความภาษาไทยที่ได้มาจากระบบ OCR อย่างละเอียด แล้วทำตามคำสั่งต่อไปนี้อย่างเคร่งครัด:
|
||||
Guidelines:
|
||||
1. ข้อมูลเข้าคือข้อความดิบจาก OCR ซึ่งอาจมีคำผิด บรรทัดขาดหาย หรือสัญลักษณ์รบกวน
|
||||
2. ค้นหาและสกัด 'เลขที่เอกสาร' (Document Number) และ 'วันที่ของเอกสาร' ออกมาให้ถูกต้อง หากไม่พบให้ระบุว่า 'ไม่ระบุ'
|
||||
3. สรุปเนื้อหาสำคัญของเอกสารนี้อย่างกระชับ เข้าใจง่าย โดยใช้บริบทโดยรวมในการตีความ หากไม่แน่ใจให้ระบุสถานะ "ไม่ชัดเจน"
|
||||
4. ห้ามสร้างข้อมูล (hallucinate) ที่ไม่มีอยู่ในข้อความต้นฉบับ
|
||||
5. ห้ามเดาตัวเลข วันที่ หรือเนื้อหาใดๆ ที่ไม่ได้ปรากฏอยู่ในข้อความดิบเด็ดขาด
|
||||
6. หากข้อมูลไม่ครบ ให้เติม null พร้อมระบุ reason ในฟิลด์ _missing_fields
|
||||
ตอบกลับเฉพาะ JSON ที่กำหนดเท่านั้น ห้ามเพิ่มข้อความนอกโครงสร้าง
|
||||
""”
|
||||
```
|
||||
|
||||
---
|
||||
file: E:\np-dms\lcbp3\specs\04-Infrastructure-OPS\04-00-docker-compose\Desk-5439\typhoon-np-dms-ocr.model.md
|
||||
```t
|
||||
# ollama create typhoon-np-dms-ocr -f ./typhoon-np-dms-ocr.model.md
|
||||
|
||||
# ใส่ชื่อ tag โมเดล 3B ที่คุณต้องการจูนตรงนี้ได้เลย
|
||||
FROM scb10x/typhoon-ocr1.5-3b:latest
|
||||
|
||||
# ลดจาก 125k → 8k เพื่อประหยัด และ ล็อกให้ตัวโมเดล + KV Cache กิน VRAM ไม่เกิน 5GB (เหลือโควตาให้ Windows อีก 3GB)
|
||||
PARAMETER num_ctx 8192
|
||||
PARAMETER num_predict 4096
|
||||
|
||||
# งานดึงข้อความจากภาพสแกน สามารถปรับค่า temperature เป็น 0 เพื่อลดการเดา/มโนคำภาษาไทย
|
||||
PARAMETER temperature 0.1
|
||||
PARAMETER top_p 0.1
|
||||
|
||||
# ป้องกันไม่ให้โมเดลพิมพ์อักษรซ้ำซากเวลาเจอจุดที่ภาพเบลอหรือรอยเปื้อนบนกระดาษ
|
||||
PARAMETER repeat_penalty 1.1
|
||||
|
||||
# ใส่คำสั่งหลักเพื่อให้โมเดลเข้าใจบทบาทและรูปแบบผลลัพธ์ที่ต้องการ (ตัวอย่าง)
|
||||
SYSTEM """You are an expert in structuring Thai documents.
|
||||
Extract the information from the image in the most correct and organized format.
|
||||
|
||||
Instructions:
|
||||
- Return ONLY clean Markdown output.
|
||||
- Include ALL information visible on the page.
|
||||
- Preserve document structure and hierarchy.
|
||||
- Do NOT add explanations or interpretations.
|
||||
|
||||
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 in:
|
||||
<figure>
|
||||
Describe the image's main elements, note contextual clues, mention visible text and meaning. Describe in Thai.
|
||||
</figure>
|
||||
- Page Numbers: Wrap page numbers in <page_number>...</page_number>.
|
||||
- Checkboxes: Use ☐ for unchecked and ☑ for checked boxes.
|
||||
- Signatures/Stamps: Describe location and context
|
||||
- Unclear text: [unclear: context description]
|
||||
"""
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. Model Switching Logic (BullMQ Processor)
|
||||
|
||||
```typescript
|
||||
// Pseudo-code for BullMQ processor (ai-batch queue)
|
||||
async function processJob(job: Job) {
|
||||
const { jobType, documentId } = job.data;
|
||||
|
||||
if (jobType === 'ocr-extract') {
|
||||
// OCR job: unload main, load OCR, process, unload OCR
|
||||
await ollama.unloadModel('typhoon2.5-np-dms');
|
||||
await ollama.loadModel('typhoon-np-dms-ocr', { keep_alive: 0 });
|
||||
const result = await ollama.generate('typhoon-np-dms-ocr', prompt);
|
||||
// keep_alive: 0 จะ unload อัตโนมัติหลังเสร็จ
|
||||
|
||||
// โหลด main model กลับเข้า VRAM สำหรับงานถัดไป
|
||||
await ollama.loadModel('typhoon2.5-np-dms');
|
||||
return result;
|
||||
}
|
||||
|
||||
// Main model jobs: extraction, rag-query, ai-suggest
|
||||
const result = await ollama.generate('typhoon2.5-np-dms', prompt);
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
**กฎ:**
|
||||
- **n8n ห้ามเรียก Ollama โดยตรง** — ต้องผ่าน `POST /api/ai/jobs` → BullMQ เท่านั้น
|
||||
- **BullMQ concurrency = 1** — ป้องกัน VRAM overflow
|
||||
- **Cold start OCR:** 30-60 วินาทีต่อ job ยอมรับได้
|
||||
- **OCR job ซ้อนกัน 3-5 งาน:** รวม 2-5 นาที ยอมรับได้
|
||||
|
||||
---
|
||||
|
||||
### 3. Code Changes
|
||||
|
||||
**ไฟล์ที่ต้องแก้ไข:**
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `backend/src/modules/ai/services/ai-settings.service.ts` | Hardcode `DEFAULT_MODEL = 'typhoon2.5-np-dms:latest'` |
|
||||
| `backend/src/modules/ai/services/ollama.service.ts` | เพิ่ม method `unloadModel()` และ `loadModel()` สำหรับ switching |
|
||||
| `backend/src/modules/ai/processors/ai-batch.processor.ts` | Implement switching logic ตาม pseudo-code ด้านบน |
|
||||
|
||||
**Note:** ไม่ต้อง update `ai_settings` table — ใช้ hardcode value เพื่อความเร็วในการ deploy
|
||||
|
||||
---
|
||||
|
||||
### 4. Migration Plan
|
||||
|
||||
**ขั้นตอนการ deploy:**
|
||||
|
||||
1. **Desk-5439:** สร้าง custom models บน Ollama
|
||||
```bash
|
||||
cd /path/to/model/files
|
||||
ollama create typhoon2.5-np-dms -f ./typhoon2.5-np-dms.model.md
|
||||
ollama create typhoon-np-dms-ocr -f ./typhoon-np-dms-ocr.model.md
|
||||
```
|
||||
|
||||
2. **QNAP Backend:** Deploy ด้วย code changes (ADR-033 mechanism ยังคงใช้ได้)
|
||||
|
||||
3. **Verification:**
|
||||
- Test OCR job → ตรวจสอบว่า unload/load ทำงานถูกต้อง
|
||||
- Test main model job → ตรวจสอบว่า main model พร้อมใช้หลัง OCR
|
||||
|
||||
---
|
||||
|
||||
### 5. Rollback Strategy
|
||||
|
||||
**ไม่มี automatic rollback mechanism**
|
||||
|
||||
หากพบปัญหา:
|
||||
1. สร้าง custom model ใหม่จาก base model ตัวอื่น (เช่น กลับไป `gemma4:e2b`)
|
||||
2. หรือแก้ไข `typhoon2.5-np-dms.model.md` แล้วสร้าง version ใหม่ (`:v2`)
|
||||
3. Update code ให้ชี้ไป model ใหม่ แล้ว redeploy
|
||||
|
||||
---
|
||||
|
||||
## Impact on Related ADRs
|
||||
|
||||
| ADR | Section | Impact |
|
||||
|-----|---------|--------|
|
||||
| **ADR-023A** | Section 2.1 Model Stack | Superseded by ADR-034 — model config ใช้ค่าจากนี้ |
|
||||
| **ADR-033** | VRAM Monitor + Model Switching | ยังใช้ได้ — mechanism เดิม เปลี่ยนแค่ชื่อ model |
|
||||
| **ADR-032** | Typhoon OCR Integration | OCR model ถูกแทนที่โดย `typhoon-np-dms-ocr` |
|
||||
|
||||
---
|
||||
|
||||
## Glossary Updates (CONTEXT.md)
|
||||
|
||||
เพิ่มคำศัพท์ใหม่:
|
||||
|
||||
| Term | Definition |
|
||||
|------|------------|
|
||||
| **Thai-Optimized Model** | โมเดล AI ที่ถูก fine-tune มาสำหรับภาษาไทย (เช่น Typhoon series) |
|
||||
| **Model Unload/Load** | กระบวนการยกเลิกโหลดโมเดลจาก VRAM และโหลดโมเดลใหม่เข้าไป |
|
||||
| **Cold Start Penalty** | ความล่าช้า 5-15 วินาทีจากการโหลดโมเดล weights เข้า VRAM |
|
||||
|
||||
---
|
||||
|
||||
**สำหรับ Implementation:** ดูไฟล์ใน `specs/100-Infrastructures/134-AI-model-change` (สร้างเมื่อเริ่ม implement)
|
||||
Reference in New Issue
Block a user