68 lines
3.6 KiB
Markdown
68 lines
3.6 KiB
Markdown
# Session 10 — 2026-05-30 (OCR Sandbox Two-Step Flow)
|
|
|
|
## Summary
|
|
|
|
แยก OCR Sandbox เป็น 2 steps ตาม spec 231: Step 1 OCR-only → Step 2 AI Extraction เพื่อให้ admin ตรวจคุณภาพ OCR ก่อนทดสอบ AI prompt
|
|
|
|
## Backend Changes (B1-B5)
|
|
|
|
- **AiBatchJobType**: เพิ่ม `sandbox-ocr-only` และ `sandbox-ai-extract` job types
|
|
- **AiBatchProcessor**:
|
|
- เพิ่ม `processSandboxOcrOnly()` — รัน OCR เท่านั้น, cache OCR text ใน Redis key `ai:sandbox:ocr:{idempotencyKey}` (TTL 3600s)
|
|
- เพิ่ม `processSandboxAiExtract()` — ดึง OCR text จาก cache, resolve prompt version (active หรือ version ที่ระบุ), replace {{ocr_text}} และ {{master_data_context}}, run LLM
|
|
- **AiPromptsService**: เพิ่ม `findByVersion(promptType, versionNumber)` method สำหรับดึง prompt version ที่ระบุ
|
|
- **AiController**:
|
|
- เพิ่ม `POST /ai/admin/sandbox/ocr` — Step 1 endpoint (รับ file multipart/form-data)
|
|
- เพิ่ม `POST /ai/admin/sandbox/ai-extract` — Step 2 endpoint (รับ requestPublicId + optional promptVersion)
|
|
- **AiQueueService**: อัปเดต `enqueueSandboxJob()` รองรับ job types ใหม่และ extraPayload สำหรับส่ง promptVersion
|
|
|
|
## Frontend Changes (F1-F3)
|
|
|
|
- **adminAiService**: เพิ่ม `submitSandboxOcr(file)` และ `submitSandboxAiExtract(requestPublicId, promptVersion)` methods
|
|
- **OcrSandboxPromptManager.tsx**:
|
|
- เพิ่ม states: `sandboxStep` ('ocr'|'ai'), `ocrResult` (requestPublicId, ocrText, ocrUsed), `selectedPromptVersion`
|
|
- เพิ่ม handlers: `handleStep1Ocr()` (poll OCR result), `handleStep2AiExtract()` (poll AI result), `handleResetSandbox()`
|
|
- Refactor UI: Step 1 (upload + Run OCR button) → Step 2 (prompt version dropdown + Run AI Extraction button + Reset button)
|
|
- แสดง OCR Raw Text card หลัง Step 1 เสร็จ (สีน้ำเงิน, badge บอก PaddleOCR/Fast Path)
|
|
- แสดง AI Extraction result หลัง Step 2 เสร็จ (สีเขียว, badge บอก promptVersionUsed)
|
|
|
|
## Schema Fix (ADR-009 + ADR-019)
|
|
|
|
- **Delta SQL**: สร้าง `2026-05-30-add-ai-prompts-publicId.sql` เพิ่ม `publicId CHAR(36) UNIQUE` column ใน `ai_prompts` table
|
|
- **Root Cause**: Entity มี `publicId` field แต่ DB table ไม่มี column นี้ → QueryFailedError: "Unknown column 'AiPrompt.publicId' in 'SELECT'"
|
|
- **Fix**: ใช้ CHAR(36) แทน UUID type (MariaDB compatible), generate UUID สำหรับ existing records ด้วย `UUID()` function
|
|
|
|
## Verification
|
|
|
|
- Backend TypeScript: ✅ ผ่าน (`npx tsc --noEmit`)
|
|
- Frontend TypeScript: ✅ ผ่าน (`npx tsc --noEmit`)
|
|
- ESLint: ✅ ผ่าน (แก้ unused `user` parameter ใน `submitSandboxAiExtract`)
|
|
|
|
## Data Flow
|
|
|
|
```
|
|
Step 1: Upload PDF → POST /ai/admin/sandbox/ocr
|
|
↓
|
|
BullMQ: sandbox-ocr-only job
|
|
↓
|
|
OCR Service → Cache OCR text (ai:sandbox:ocr:{id})
|
|
↓
|
|
Frontend displays OCR Raw Text
|
|
|
|
Step 2: Select prompt version → POST /ai/admin/sandbox/ai-extract
|
|
↓
|
|
BullMQ: sandbox-ai-extract job
|
|
↓
|
|
Retrieve OCR text from cache (ai:sandbox:ocr:{id})
|
|
↓
|
|
Replace {{ocr_text}} → LLM → JSON result
|
|
↓
|
|
Frontend displays AI Extraction result
|
|
```
|
|
|
|
## Pending
|
|
|
|
- Run delta SQL `2026-05-30-add-ai-prompts-publicId.sql` ใน production database
|
|
- Restart backend service หลัง apply delta
|
|
- Test 2-step flow จริงใน production environment
|