260322:1648 Correct Coresspondence / Doing RFA / Correct CI
This commit is contained in:
@@ -35,25 +35,28 @@
|
||||
### Phase 1: การเตรียม Infrastructure และ Storage (สัปดาห์ที่ 1)
|
||||
|
||||
**File Migration:**
|
||||
|
||||
- ย้ายไฟล์ PDF ทั้งหมดจากแหล่งเก็บไปยัง Folder ชั่วคราวบน NAS (QNAP)
|
||||
- Target Path: `/share/np-dms/staging_ai/`
|
||||
|
||||
**Mount Folder:**
|
||||
|
||||
- Bind Mount `/share/np-dms/staging_ai/` เข้ากับ n8n Container แบบ **read-only**
|
||||
- สร้าง `/share/np-dms/n8n/migration_logs/` Volume แยกสำหรับเขียน Log แบบ **read-write**
|
||||
|
||||
**Ollama Config:**
|
||||
|
||||
- ติดตั้ง Ollama บน Desktop (Desk-5439, RTX 2060 SUPER 8GB)
|
||||
- No DB credentials, Internal network only
|
||||
|
||||
#### 🔍 เปรียบเทียบผลลัพธ์ที่คาดหวัง
|
||||
|
||||
| งาน | Typhoon2-4B | Qwen2.5-7B | OpenThaiGPT-7B |
|
||||
|-----|-------------|------------|----------------|
|
||||
| ความเร็ว (ток/วินาที) | ~35-45 | ~8-12 | ~10-15 |
|
||||
| ความเข้าใจบริบทไทย | ดีมาก | ดี | ดีมาก |
|
||||
| การสร้างแท็กแม่นยำ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||
| ความเสถียรบน 8GB | ✅ สูง | ⚠️ ปานกลาง | ⚠️ ปานกลาง |
|
||||
| งาน | Typhoon2-4B | Qwen2.5-7B | OpenThaiGPT-7B |
|
||||
| --------------------- | ----------- | ---------- | -------------- |
|
||||
| ความเร็ว (ток/วินาที) | ~35-45 | ~8-12 | ~10-15 |
|
||||
| ความเข้าใจบริบทไทย | ดีมาก | ดี | ดีมาก |
|
||||
| การสร้างแท็กแม่นยำ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||||
| ความเสถียรบน 8GB | ✅ สูง | ⚠️ ปานกลาง | ⚠️ ปานกลาง |
|
||||
|
||||
```bash
|
||||
# แนะนำ: llama3.2:3b (เร็ว, VRAM ~3GB, เหมาะ Classification) หรือ ollama run llama3.2:3b
|
||||
@@ -79,15 +82,18 @@ watch -n 1 nvidia-smi
|
||||
# Fallback: mistral:7b-instruct-q4_K_M (แม่นกว่า, VRAM ~5GB)
|
||||
# ollama pull mistral:7b-instruct-q4_K_M
|
||||
```
|
||||
|
||||
ใช้ ทางเลือกที่ 1
|
||||
|
||||
**ทดสอบ Ollama:**
|
||||
|
||||
```bash
|
||||
curl http://192.168.20.100:11434/api/generate \
|
||||
-d '{"model":"llama3.2:3b","prompt":"reply: ok","stream":false}'
|
||||
```
|
||||
|
||||
**Concurrency Configuration:**
|
||||
|
||||
- Sequential: Batch Size = 1, Delay ≥ 2 วินาที, ปิด Parallel Execution
|
||||
- เพิ่ม Health Check Node ก่อนเริ่ม Batch เพื่อป้องกัน Workflow ค้างหาก Desktop Sleep หรือ Overheat
|
||||
|
||||
@@ -96,6 +102,7 @@ curl http://192.168.20.100:11434/api/generate \
|
||||
### Phase 2: การเตรียม Target Database และ API (สัปดาห์ที่ 1)
|
||||
|
||||
**SQL Indexing:**
|
||||
|
||||
```sql
|
||||
ALTER TABLE correspondences ADD INDEX idx_doc_number (document_number);
|
||||
ALTER TABLE correspondences ADD INDEX idx_deleted_at (deleted_at);
|
||||
@@ -103,6 +110,7 @@ ALTER TABLE correspondences ADD INDEX idx_created_by (created_by);
|
||||
```
|
||||
|
||||
**Checkpoint Table:**
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS migration_progress (
|
||||
batch_id VARCHAR(50) PRIMARY KEY,
|
||||
@@ -113,6 +121,7 @@ CREATE TABLE IF NOT EXISTS migration_progress (
|
||||
```
|
||||
|
||||
**Tags Table (สำหรับ AI Tag Extraction):**
|
||||
|
||||
```sql
|
||||
-- ตาราง Master เก็บ Tags (Global หรือ Project-specific)
|
||||
CREATE TABLE tags (
|
||||
@@ -143,6 +152,7 @@ CREATE TABLE correspondence_tags (
|
||||
```
|
||||
|
||||
**Idempotency Table :**
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS import_transactions (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
@@ -158,6 +168,7 @@ CREATE TABLE IF NOT EXISTS import_transactions (
|
||||
> **Idempotency Logic:** ถ้า `idempotency_key` ซ้ำ → Backend คืน HTTP 200 ทันที (ไม่สร้าง Revision ซ้ำ) ถ้าไม่ซ้ำ → ประมวลผลปกติ
|
||||
|
||||
**API Authentication — Migration Token:**
|
||||
|
||||
```sql
|
||||
INSERT INTO users (username, email, role, is_active)
|
||||
VALUES ('migration_bot', 'migration@system.internal', 'SYSTEM_ADMIN', true);
|
||||
@@ -165,14 +176,14 @@ VALUES ('migration_bot', 'migration@system.internal', 'SYSTEM_ADMIN', true);
|
||||
|
||||
**Scope ของ Migration Token (Patch — คำนิยามชัดเจน):**
|
||||
|
||||
| สิทธิ์ | ปกติ | Migration Token | หมายเหตุ |
|
||||
| ------------------------------------- | --- | --------------- | --------------------------------- |
|
||||
| Bypass File Virus Scan | ❌ | ✅ | ไฟล์ผ่าน Scan มาแล้วก่อน Import |
|
||||
| Bypass Duplicate **Validation Error** | ❌ | ✅ | **Revision Logic ยัง enforce ปกติ** |
|
||||
| Bypass Created-by User validation | ❌ | ✅ | |
|
||||
| Overwrite existing revision | ❌ | ❌ | **ห้ามโดยเด็ดขาด** |
|
||||
| Delete previous revision | ❌ | ❌ | **ห้ามโดยเด็ดขาด** |
|
||||
| ลบ / แก้ไข Record อื่น | ❌ | ❌ | **ห้ามโดยเด็ดขาด** |
|
||||
| สิทธิ์ | ปกติ | Migration Token | หมายเหตุ |
|
||||
| ------------------------------------- | ---- | --------------- | ----------------------------------- |
|
||||
| Bypass File Virus Scan | ❌ | ✅ | ไฟล์ผ่าน Scan มาแล้วก่อน Import |
|
||||
| Bypass Duplicate **Validation Error** | ❌ | ✅ | **Revision Logic ยัง enforce ปกติ** |
|
||||
| Bypass Created-by User validation | ❌ | ✅ | |
|
||||
| Overwrite existing revision | ❌ | ❌ | **ห้ามโดยเด็ดขาด** |
|
||||
| Delete previous revision | ❌ | ❌ | **ห้ามโดยเด็ดขาด** |
|
||||
| ลบ / แก้ไข Record อื่น | ❌ | ❌ | **ห้ามโดยเด็ดขาด** |
|
||||
|
||||
> ⚠️ **Patch Clarification:** "Bypass Duplicate Number Check" ถูกแทนด้วย "Bypass Duplicate **Validation Error**" — Revision increment logic ยังทำงานตามปกติทุกกรณี
|
||||
|
||||
@@ -194,21 +205,25 @@ VALUES ('migration_bot', 'migration@system.internal', 'SYSTEM_ADMIN', true);
|
||||
4. File Mount Check → `staging_ai` มีไฟล์, `migration_logs` เขียนได้
|
||||
|
||||
**Fetch System Categories (Patch — ห้าม hardcode):**
|
||||
|
||||
```http
|
||||
GET /api/meta/categories
|
||||
Authorization: Bearer <MIGRATION_TOKEN>
|
||||
```
|
||||
|
||||
Response:
|
||||
|
||||
```json
|
||||
{ "categories": ["Correspondence","RFA","Drawing","Transmittal","Report","Other"] }
|
||||
{ "categories": ["Correspondence", "RFA", "Drawing", "Transmittal", "Report", "Other"] }
|
||||
```
|
||||
|
||||
n8n ต้องเก็บ categories นี้ไว้ใน Workflow Variable (`system_categories`) และ inject เข้า AI Prompt ทุก Request
|
||||
|
||||
#### Node 1: Data Reader & Checkpoint
|
||||
|
||||
#### Node 1: Data Reader & Checkpoint
|
||||
|
||||
- อ่าน Checkpoint จาก **MariaDB Node แยก**
|
||||
- อ่าน Checkpoint จาก **MariaDB Node แยก**
|
||||
- Batch ทีละ **50–100 แถว** ตาม `$env.MIGRATION_BATCH_SIZE` (ควรจำกัด Batch Size ป้องกัน DB Connection Overload)
|
||||
- ติด `original_index` ทุก Item และ Normalize Encoding (UTF-8 NFC) สำหรับ ชื่อไฟล์ และ เลขเอกสารเก่า
|
||||
|
||||
@@ -221,7 +236,7 @@ n8n ต้องเก็บ categories นี้ไว้ใน Workflow Variab
|
||||
3. แปลง `receiver_code` -> `receiver_organization_id`
|
||||
4. หา Tags ที่มีอยู่ในโปรเจ็กต์: `SELECT * FROM tags WHERE project_id = {{project_id}}`
|
||||
- **Output:** n8n เก็บ `project_id`, `organization_ids` และ `existing_tags_json` ไว้ในแต่ละ item
|
||||
- *ถ้าหารหัสโปรเจ็กต์ไม่เจอ ให้ส่งเข้า Error Log ไม่ทำต่อ*
|
||||
- _ถ้าหารหัสโปรเจ็กต์ไม่เจอ ให้ส่งเข้า Error Log ไม่ทำต่อ_
|
||||
|
||||
#### Node 3: File Processor (Extract PDF Text & Temp Upload)
|
||||
|
||||
@@ -235,6 +250,7 @@ n8n ต้องเก็บ categories นี้ไว้ใน Workflow Variab
|
||||
#### Node 4: AI Analysis (Sequential เท่านั้น)
|
||||
|
||||
**System Prompt:**
|
||||
|
||||
```text
|
||||
You are a Document Controller for a large construction project.
|
||||
Your task is to validate document metadata, summarize content, and suggest relevant tags.
|
||||
@@ -242,6 +258,7 @@ You MUST respond ONLY with valid JSON. No explanation, no markdown.
|
||||
```
|
||||
|
||||
**User Prompt:**
|
||||
|
||||
```text
|
||||
Validate and summarize this document. Respond in JSON.
|
||||
Document Number: {{$json.document_number}}
|
||||
@@ -273,12 +290,14 @@ Respond ONLY with this exact JSON structure:
|
||||
ข้อมูลทั้งหมดที่ผ่าน n8n และ AI Model **จะต้องไม่ถูกอัพเดทเข้าตารางหลักอัตโนมัติ** แต่จะถูกบังคับนำเข้าตาราง Staging `migration_review_queue` แทน เพื่อรอมนุษย์จัดการผ่าน Frontend UI
|
||||
|
||||
**Status Routing Policy:**
|
||||
|
||||
- `confidence >= 0.85` และ `is_valid = true` -> Status **`PENDING`** (พร้อมรับ Batch Import)
|
||||
- `confidence >= 0.60` และ `< 0.85` -> Status **`PENDING`** (ติด Flag ให้ระวัง)
|
||||
- `confidence < 0.60` หรือ `is_valid = false` -> Status **`REJECTED`**
|
||||
- Parse Error / AI ไม่ตอบ -> **Error Log** (Node ถัดไป)
|
||||
|
||||
**Insert into staging:**
|
||||
|
||||
```sql
|
||||
INSERT INTO migration_review_queue (
|
||||
document_number, title, project_id, sender_organization_id, receiver_organization_id,
|
||||
@@ -290,7 +309,7 @@ ON DUPLICATE KEY UPDATE status = VALUES(status), ai_summary = VALUES(ai_summary)
|
||||
|
||||
#### Node 6: Error Log & Reject Log
|
||||
|
||||
- Parse Error → เขียนลงไฟล์ `/share/np-dms/n8n/migration_logs/error_log.csv`
|
||||
- Parse Error → เขียนลงไฟล์ `/share/np-dms/n8n/migration_logs/error_log.csv`
|
||||
- ทุก 10-50 ราบการอัพเดท MariaDB `migration_progress` เพื่อเป็น Checkpoint.
|
||||
|
||||
---
|
||||
@@ -308,10 +327,12 @@ ON DUPLICATE KEY UPDATE status = VALUES(status), ai_summary = VALUES(ai_summary)
|
||||
### Phase 4: แผนการทดสอบ (Testing & QA)
|
||||
|
||||
**Dry Run Policy (Mandatory):**
|
||||
|
||||
- All migrations MUST run with `--dry-run`
|
||||
- No DB commit until validation approved
|
||||
|
||||
**Dry Run Validation (20–50 แถว):**
|
||||
|
||||
- JSON Parse Success Rate > 95%
|
||||
- Category ที่ AI ตอบตรงกับ System Enum ทุกรายการ
|
||||
- รัน Batch เดิมซ้ำ 2 รอบ → ต้องไม่สร้าง Duplicate หรือ Revision ซ้ำ (Idempotency Test)
|
||||
@@ -319,6 +340,7 @@ ON DUPLICATE KEY UPDATE status = VALUES(status), ai_summary = VALUES(ai_summary)
|
||||
- Revision Drift ถูก route ไป Review Queue
|
||||
|
||||
**Integrity Check:**
|
||||
|
||||
```sql
|
||||
-- ตรวจยอด
|
||||
SELECT COUNT(*) FROM correspondences WHERE created_by = 'SYSTEM_IMPORT';
|
||||
@@ -351,11 +373,13 @@ WHERE created_by = 'SYSTEM_IMPORT' AND action = 'IMPORT';
|
||||
## 4. Rollback Plan
|
||||
|
||||
**Step 1:** หยุด n8n และ Disable Token
|
||||
|
||||
```sql
|
||||
UPDATE users SET is_active = false WHERE username = 'migration_bot';
|
||||
```
|
||||
|
||||
**Step 2:** ลบ Records (Transaction)
|
||||
|
||||
```sql
|
||||
START TRANSACTION;
|
||||
DELETE FROM correspondence_files
|
||||
@@ -369,6 +393,7 @@ COMMIT;
|
||||
**Step 3:** ย้ายไฟล์กลับ `/share/np-dms/staging_ai/` ผ่าน Script แยก
|
||||
|
||||
**Step 4:** Reset State
|
||||
|
||||
```sql
|
||||
UPDATE migration_progress
|
||||
SET status = 'FAILED', last_processed_index = 0
|
||||
@@ -383,19 +408,19 @@ WHERE batch_id = 'migration_20260226';
|
||||
|
||||
## 5. แผนรับมือความเสี่ยง (Risk Management)
|
||||
|
||||
| ลำดับที่ | ความเสี่ยง | การจัดการ (Mitigation) |
|
||||
| ---- | -------------------------- | -------------------------------------------------- |
|
||||
| 1 | AI Node หรือ GPU ค้าง | Timeout 30 วินาที, Retry 3 รอบ, Delay 60 วินาที |
|
||||
| 2 | Ollama ตอบไม่ใช่ JSON | JSON Pre-processor + ส่ง Human Review Queue |
|
||||
| 3 | Category ไม่ตรง System Enum | Fetch `/api/meta/categories` ก่อน Batch ทุกครั้ง |
|
||||
| 4 | Idempotency ซ้ำ | `import_transactions` table + Backend คืน HTTP 200 |
|
||||
| 5 | Revision Drift | ตรวจ Excel revision column → Route ไป Review Queue |
|
||||
| 6 | Storage bypass | ห้าม move file โดยตรง — ผ่าน Backend API เท่านั้น |
|
||||
| 7 | GPU VRAM Overflow | ใช้เฉพาะ Quantized Model (q4_K_M) |
|
||||
| 8 | ดิสก์ NAS เต็ม | ปิด "Save Successful Executions" ใน n8n |
|
||||
| 9 | Migration Token ถูกขโมย | Token 7 วัน, IP Whitelist `<NAS_IP>` เท่านั้น |
|
||||
| 11 | AI Tag Extraction ผิดพลาด | Tag confidence < 0.6 → ส่งไป Review Queue / บันทึกใน metadata |
|
||||
| 12 | Tag ซ้ำ/คล้ายกัน | Normalization ก่อนบันทึก (lowercase, trim, deduplicate) |
|
||||
| ลำดับที่ | ความเสี่ยง | การจัดการ (Mitigation) |
|
||||
| -------- | --------------------------- | ------------------------------------------------------------- |
|
||||
| 1 | AI Node หรือ GPU ค้าง | Timeout 30 วินาที, Retry 3 รอบ, Delay 60 วินาที |
|
||||
| 2 | Ollama ตอบไม่ใช่ JSON | JSON Pre-processor + ส่ง Human Review Queue |
|
||||
| 3 | Category ไม่ตรง System Enum | Fetch `/api/meta/categories` ก่อน Batch ทุกครั้ง |
|
||||
| 4 | Idempotency ซ้ำ | `import_transactions` table + Backend คืน HTTP 200 |
|
||||
| 5 | Revision Drift | ตรวจ Excel revision column → Route ไป Review Queue |
|
||||
| 6 | Storage bypass | ห้าม move file โดยตรง — ผ่าน Backend API เท่านั้น |
|
||||
| 7 | GPU VRAM Overflow | ใช้เฉพาะ Quantized Model (q4_K_M) |
|
||||
| 8 | ดิสก์ NAS เต็ม | ปิด "Save Successful Executions" ใน n8n |
|
||||
| 9 | Migration Token ถูกขโมย | Token 7 วัน, IP Whitelist `<NAS_IP>` เท่านั้น |
|
||||
| 11 | AI Tag Extraction ผิดพลาด | Tag confidence < 0.6 → ส่งไป Review Queue / บันทึกใน metadata |
|
||||
| 12 | Tag ซ้ำ/คล้ายกัน | Normalization ก่อนบันทึก (lowercase, trim, deduplicate) |
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user