Files
lcbp3/specs/100-Infrastructures/134-ai-model-change/spec.md
T
admin 3274dede7a
CI / CD Pipeline / build (push) Failing after 4m28s
CI / CD Pipeline / deploy (push) Has been skipped
690603:2041 ADR-034-134 #01
2026-06-03 20:41:42 +07:00

128 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// File: specs/100-Infrastructures/134-ai-model-change/spec.md
// Change Log:
// - 2026-06-03: Initial specification for Thai-Optimized AI Model Stack (ADR-034)
# Feature Specification: Thai-Optimized AI Model Stack
**Feature Branch**: `134-ai-model-change`
**Created**: 2026-06-03
**Status**: Draft
**Category**: 100-Infrastructures
**ADR Reference**: ADR-034 (Supersedes ADR-023A Section 2.1)
**Input**: User description: "Implement ADR-034 — Switch AI model stack from gemma4:e2b to Thai-optimized Typhoon series: typhoon2.5-np-dms:latest (main AI) + typhoon-np-dms-ocr:latest (Thai OCR). Requires model switching logic in BullMQ processor, new unload/load methods in OllamaService, updated default model config. VRAM budget: RTX 2060 Super 8GB."
---
## User Scenarios & Testing _(mandatory)_
### User Story 1 — Thai OCR Extraction With New OCR Model (Priority: P1)
ในฐานะ DevOps Engineer ฉันต้องการให้งาน OCR ภาษาไทยใช้ Typhoon OCR-3B ที่ถูก fine-tune มาสำหรับภาษาไทย เพื่อให้ข้อความที่สกัดจาก PDF ภาษาไทยมีความแม่นยำสูงกว่า gemma4:e2b
**Why this priority**: งาน OCR ภาษาไทยคือจุดอ่อนหลักของระบบปัจจุบัน การเปลี่ยนเป็น Typhoon OCR model จะส่งผลโดยตรงต่อคุณภาพการ extract metadata และ text จากเอกสาร
**Independent Test**: ส่ง OCR job (`jobType: 'ocr-extract'`) เข้า BullMQ ด้วย PDF ภาษาไทย และตรวจสอบว่า (1) job สำเร็จโดยไม่มี VRAM OOM error (2) ข้อความ OCR อ่านออกได้ (3) หลัง OCR เสร็จ main model ยังพร้อมใช้งาน
**Acceptance Scenarios**:
1. **Given** `typhoon-np-dms-ocr:latest` ถูก create บน Desk-5439, **When** BullMQ ได้รับ job `ocr-extract` หรือ `sandbox-ocr-only`, **Then** processor unload main model → load OCR model (keep_alive:0) → ประมวลผล → OCR model unload อัตโนมัติ
2. **Given** OCR job เสร็จแล้ว, **When** main model job เข้ามาต่อ, **Then** processor reload main model และประมวลผลสำเร็จภายใน 60 วินาที
3. **Given** VRAM ถูกใช้งานสูงขณะมี OCR job, **When** job เข้าคิว, **Then** BullMQ concurrency=1 ป้องกัน VRAM overflow — ไม่เกิด OOM error
---
### User Story 2 — General AI Tasks Use Thai-Optimized Main Model (Priority: P2)
ในฐานะ DevOps Engineer ฉันต้องการให้ระบบ AI ใช้ `typhoon2.5-np-dms:latest` เป็น main model สำหรับงาน extraction, RAG Q&A, และ AI suggestion แทน gemma4:e2b เพื่อประสิทธิภาพภาษาไทยที่ดีขึ้น
**Why this priority**: เมื่อ OCR ทำงานได้แล้ว ต้องมั่นใจว่า AI extraction/RAG ที่ใช้ main model ทำงานได้กับโมเดลใหม่
**Independent Test**: ส่ง `ai-extract` job เข้า BullMQ → ตรวจสอบว่า backend เรียก `typhoon2.5-np-dms:latest` (ไม่ใช่ `gemma4:e2b`) และได้ผลลัพธ์ที่ถูกต้อง
**Acceptance Scenarios**:
1. **Given** `typhoon2.5-np-dms:latest` ถูก create บน Desk-5439, **When** backend start up, **Then** `AiSettingsService.DEFAULT_MODEL = 'typhoon2.5-np-dms:latest'`
2. **Given** main model พร้อม, **When** ส่ง extraction/RAG/suggestion job, **Then** ผลลัพธ์ return โดยไม่มี "model not found" error
3. **Given** การ reload main model หลัง OCR job, **When** warm reload, **Then** ใช้เวลา ≤ 60 วินาที (cold start acceptable)
---
### User Story 3 — System Health Reflects New Model Stack (Priority: P3)
ในฐานะ AI Admin ฉันต้องการเห็นสถานะของ model stack ใหม่ใน AI Admin Console เพื่อยืนยันว่าระบบทำงานถูกต้องหลัง deploy
**Why this priority**: Operations team ต้องการ observability เพื่อตรวจสอบหลัง deployment
**Independent Test**: เปิด AI Admin Console → System Health → เห็นชื่อ `typhoon2.5-np-dms` และ `typhoon-np-dms-ocr` แทน gemma4
**Acceptance Scenarios**:
1. **Given** backend รันกับ model stack ใหม่, **When** GET `/api/ai/health`, **Then** response แสดง main model = `typhoon2.5-np-dms:latest` และ ocr model = `typhoon-np-dms-ocr:latest`
2. **Given** มี model switching เกิดขึ้น, **When** ดู BullMQ job logs, **Then** เห็น log บันทึก unload/load พร้อม model name และ timestamp
---
### Edge Cases
- VRAM เต็ม (>8GB) ขณะ load OCR model → BullMQ retry; ไม่ crash; error log ชัดเจน
- Ollama API timeout ขณะ `unloadModel`/`loadModel` → throw descriptive error; ไม่ swallow silently
- โมเดล `typhoon2.5-np-dms` ไม่ถูก create บน Desk-5439 → backend start ได้; job fail พร้อม clear "model not found" error
- OCR job และ main job เข้าคิวพร้อมกัน → BullMQ concurrency=1 handle อยู่แล้ว; ไม่ต้องแก้
- Cold start OCR (3060s) ขณะ user รอ → ยอมรับได้; job polling แสดงสถานะ
---
## Requirements _(mandatory)_
### Functional Requirements
- **FR-001**: ระบบ MUST ใช้ `typhoon2.5-np-dms:latest` เป็น default main model สำหรับทุก AI job ที่ไม่ใช่ OCR
- **FR-002**: ระบบ MUST ใช้ `typhoon-np-dms-ocr:latest` เฉพาะ job type `ocr-extract` และ `sandbox-ocr-only`
- **FR-003**: BullMQ processor MUST unload main model ก่อน load OCR model ทุกครั้งที่มี OCR job
- **FR-004**: OCR model MUST unload อัตโนมัติหลัง job เสร็จ (keep_alive: 0)
- **FR-005**: หลัง OCR job เสร็จ processor MUST reload main model (keep_alive: -1 หรือ indefinite)
- **FR-006**: OllamaService MUST expose `unloadModel(modelName)` และ `loadModel(modelName, keepAlive?)` methods
- **FR-007**: `AiSettingsService.DEFAULT_MODEL` MUST hardcoded เป็น `'typhoon2.5-np-dms:latest'` (ตาม ADR-034)
- **FR-008**: Embedding model `nomic-embed-text` MUST ไม่เปลี่ยนแปลง (นอก scope)
- **FR-009**: n8n MUST ไม่เรียก Ollama โดยตรง — ยังคง pattern `POST /api/ai/jobs` → BullMQ (ADR-023A)
- **FR-010**: BullMQ concurrency MUST = 1 เพื่อป้องกัน VRAM overflow
### Key Entities
- **Custom Ollama Model `typhoon2.5-np-dms`**: Configuration ของ main AI model — base: typhoon2.5-qwen3-4b, keep_alive: indefinite, size ~2.5GB
- **Custom Ollama Model `typhoon-np-dms-ocr`**: Configuration ของ OCR model — base: typhoon-ocr1.5-3b, keep_alive: 0, size ~3.2GB
- **OllamaService.unloadModel / loadModel**: Methods สำหรับ explicit model management ผ่าน Ollama API
- **AiSettingsService.DEFAULT_MODEL**: Hardcoded constant ชี้ไปยัง main model ใหม่
---
## Success Criteria _(mandatory)_
### Measurable Outcomes
- **SC-001**: OCR job ประมวลผล PDF ภาษาไทยได้ข้อความที่อ่านออกได้ (ไม่มี garbled Thai characters) > 90% ของ pages
- **SC-002**: ไม่มี VRAM OOM error ตลอดการ process OCR + main jobs ต่อเนื่อง 10 jobs
- **SC-003**: OCR cold start ≤ 60 วินาที; main model warm response ≤ 5 วินาที
- **SC-004**: Deploy custom models บน Desk-5439 (`ollama create`) ใช้เวลา ≤ 15 นาทีต่อ model (download ขึ้นกับ network)
- **SC-005**: ไม่มี regression ใน AI extraction/RAG functionality ที่เดิมทำงานได้
---
## Assumptions
- **A1**: Desk-5439 มี internet access สำหรับ pull base models (`scb10x/typhoon*`) จาก Ollama registry
- **A2**: ADR-033 VRAM monitoring mechanism ใช้งานได้กับ Typhoon models
- **A3**: Custom Modelfiles ถูก define ใน `specs/04-Infrastructure-OPS/04-00-docker-compose/Desk-5439/` แล้ว
- **A4**: Embedding model `nomic-embed-text` ไม่เปลี่ยนแปลง
- **A5**: `ai_available_models` table (ADR-027) จำเป็นต้อง update seed เพื่อแสดง model ใหม่ใน admin console
---
## Clarifications
### Session 2026-06-03
- Q: nomic-embed-text embedding model เปลี่ยนหรือไม่? → A: ไม่เปลี่ยน — ADR-034 supersedes LLM stack เท่านั้น
- Q: Keep-alive value สำหรับ main model หลัง reload คือเท่าไร? → A: -1 (indefinite) ตาม ADR-034 "Stand by ตลอด (ไม่ใช่ 0)"
- Q: `sandbox-ocr-only` ต้องใช้ OCR model switching ด้วยหรือไม่? → A: ใช่ — เป็น OCR job type เหมือน `ocr-extract`