690409:0953 Done Task-BE-AI-02
This commit is contained in:
@@ -2208,7 +2208,105 @@ SELECT * FROM correspondences WHERE deleted_at IS NULL;
|
||||
|
||||
---
|
||||
|
||||
## **19. 📖 Glossary (คำศัพท์)**
|
||||
## **19. 🤖 AI Gateway Tables (ADR-018, ADR-020)**
|
||||
|
||||
> เพิ่มใน v1.9.0 — Task BE-AI-02 | ตารางสำหรับ AI Intelligence Integration
|
||||
|
||||
### 19.1 `migration_logs`
|
||||
|
||||
**วัตถุประสงค์:** ติดตามสถานะการประมวลผล AI สำหรับเอกสารแต่ละรายการ ใช้ในกระบวนการ Legacy Migration และ New Ingestion
|
||||
|
||||
| Column | Type | Nullable | Description |
|
||||
|--------|------|----------|-------------|
|
||||
| `id` | INT AUTO_INCREMENT | NO | Internal PK — ห้าม expose ใน API (ADR-019) |
|
||||
| `uuid` | UUID | NO | Public Identifier (UUIDv7) — ใช้ใน API response เป็น `publicId` |
|
||||
| `source_file` | VARCHAR(255) | NO | Path หรือ publicId ของไฟล์ต้นทาง |
|
||||
| `source_metadata` | JSON | YES | Metadata จากแหล่งต้นทาง (Excel, manual input) |
|
||||
| `ai_extracted_metadata` | JSON | YES | Metadata ที่ AI สกัดได้ — ประกอบด้วย subject, date, discipline, drawingReference, contractNumber |
|
||||
| `confidence_score` | DECIMAL(3,2) | YES | คะแนนความมั่นใจของ AI (0.00–1.00) ตาม ADR-020 Confidence Strategy |
|
||||
| `status` | ENUM | NO | สถานะปัจจุบัน (ดู State Machine ด้านล่าง) |
|
||||
| `admin_feedback` | TEXT | YES | ความเห็นของ Admin ผู้ตรวจสอบ |
|
||||
| `reviewed_by` | INT | YES | FK → `users.user_id` — Admin ที่ทำการตรวจสอบ |
|
||||
| `reviewed_at` | TIMESTAMP | YES | เวลาที่ Admin ตรวจสอบ |
|
||||
| `created_at` | TIMESTAMP | NO | วันที่สร้าง record |
|
||||
| `updated_at` | TIMESTAMP | NO | วันที่แก้ไขล่าสุด (Auto-update) |
|
||||
|
||||
#### Status Enum Values
|
||||
|
||||
| Status | Description | Action Required |
|
||||
|--------|-------------|-----------------|
|
||||
| `PENDING_REVIEW` | รอ Admin ตรวจสอบ (Default) | Admin ต้องตรวจสอบและเปลี่ยนสถานะ |
|
||||
| `VERIFIED` | Admin ยืนยันแล้ว พร้อม Import | ระบบนำเข้าหรือรอ Batch Import |
|
||||
| `IMPORTED` | นำเข้าสู่ระบบสำเร็จ (Terminal State) | ไม่สามารถแก้ไขได้อีก |
|
||||
| `FAILED` | ล้มเหลว — AI หรือ Validation ไม่ผ่าน | สามารถ Retry ได้ (→ PENDING_REVIEW) |
|
||||
|
||||
#### State Machine (Status Transitions)
|
||||
|
||||
```
|
||||
PENDING_REVIEW ──→ VERIFIED ──→ IMPORTED (terminal)
|
||||
│ │
|
||||
↓ ↓
|
||||
FAILED ──────→ PENDING_REVIEW (retry)
|
||||
```
|
||||
|
||||
**กฎ:**
|
||||
- `IMPORTED` เป็น Terminal State — ห้ามเปลี่ยนสถานะ
|
||||
- Admin สามารถเปลี่ยนได้เฉพาะ `PENDING_REVIEW → VERIFIED` หรือ `PENDING_REVIEW → FAILED`
|
||||
- `FAILED → PENDING_REVIEW` สำหรับ Retry
|
||||
|
||||
#### `ai_extracted_metadata` JSON Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"subject": "string — หัวเรื่องเอกสาร",
|
||||
"date": "YYYY-MM-DD — วันที่เอกสาร",
|
||||
"discipline": "Civil | Mechanical | Electrical | Architectural",
|
||||
"drawingReference": "string — รหัสแบบอ้างอิง",
|
||||
"contractNumber": "string — เลขสัญญา",
|
||||
"discrepancies": ["string — รายการที่ไม่สอดคล้องกับต้นทาง"]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 19.2 `ai_audit_logs`
|
||||
|
||||
**วัตถุประสงค์:** บันทึก Audit Trail ของ AI Interaction ทุกครั้ง ตาม ADR-018 Rule 5 — ห้ามลบ record ออก
|
||||
|
||||
| Column | Type | Nullable | Description |
|
||||
|--------|------|----------|-------------|
|
||||
| `id` | INT AUTO_INCREMENT | NO | Internal PK — ห้าม expose ใน API (ADR-019) |
|
||||
| `uuid` | UUID | NO | Public Identifier (UUIDv7) |
|
||||
| `document_public_id` | UUID | YES | UUID ของ `migration_logs` ที่เกี่ยวข้อง (Soft Reference — ไม่ใช่ FK ในระดับ TypeORM) |
|
||||
| `ai_model` | VARCHAR(50) | NO | ชื่อ AI Model เช่น `gemma4`, `paddleocr`, `gemma4:27b` |
|
||||
| `processing_time_ms` | INT | YES | เวลาประมวลผล (milliseconds) — เป้าหมาย < 15,000ms ตาม ADR-020 |
|
||||
| `confidence_score` | DECIMAL(3,2) | YES | คะแนนความมั่นใจ (0.00–1.00) |
|
||||
| `input_hash` | VARCHAR(64) | YES | SHA-256 hash ของ Input — เพื่อ Integrity Verification |
|
||||
| `output_hash` | VARCHAR(64) | YES | SHA-256 hash ของ Output — เพื่อ Integrity Verification |
|
||||
| `status` | ENUM | NO | ผลการประมวลผล: SUCCESS / FAILED / TIMEOUT |
|
||||
| `error_message` | TEXT | YES | รายละเอียด Error (เมื่อ status = FAILED หรือ TIMEOUT) |
|
||||
| `created_at` | TIMESTAMP | NO | วันที่สร้าง — เรียงตาม timestamp เพื่อ Audit |
|
||||
|
||||
#### Business Rules
|
||||
|
||||
1. **Immutable Records** — ห้ามแก้ไขหรือลบ `ai_audit_logs` หลังสร้าง (Audit Trail)
|
||||
2. **Data Retention** — เก็บไว้อย่างน้อย 90 วัน ตาม ADR-020 Data Privacy
|
||||
3. **No FK Constraint** — `document_public_id` เป็น Soft Reference เพื่อให้ Log ยังคงอยู่แม้ MigrationLog ถูกลบ
|
||||
|
||||
---
|
||||
|
||||
### 19.3 Confidence Scoring Strategy (ADR-020)
|
||||
|
||||
| Score Range | Action | Description |
|
||||
|-------------|--------|-------------|
|
||||
| **0.95–1.00** | `auto_approve` | นำเข้าอัตโนมัติ (Migration mode เท่านั้น) |
|
||||
| **0.85–0.94** | `low_priority_review` | รอ Admin ตรวจสอบ — ลำดับต่ำ |
|
||||
| **0.60–0.84** | `high_priority_review` | รอ Admin ตรวจสอบ — ลำดับสูง |
|
||||
| **< 0.60** | `reject` | ปฏิเสธ — Admin ต้องกรอกข้อมูลเอง |
|
||||
|
||||
---
|
||||
|
||||
## **20. 📖 Glossary (คำศัพท์)**
|
||||
|
||||
- **RFA**: Request for Approval (เอกสารขออนุมัติ)
|
||||
- **Transmittal**: Document Transmittal Sheet (ใบนำส่งเอกสาร)
|
||||
|
||||
@@ -1400,3 +1400,51 @@ CREATE TABLE workflow_histories (
|
||||
CREATE INDEX idx_wf_hist_instance ON workflow_histories (instance_id);
|
||||
|
||||
CREATE INDEX idx_wf_hist_user ON workflow_histories (action_by_user_id);
|
||||
|
||||
-- =====================================================
|
||||
-- 11. 🤖 AI Gateway (ตาราง AI Integration - ADR-018, ADR-020)
|
||||
-- =====================================================
|
||||
-- ตารางเก็บบันทึก Migration เอกสารที่ผ่าน AI Processing
|
||||
CREATE TABLE migration_logs (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'Internal PK (ห้าม expose ใน API)',
|
||||
uuid UUID NOT NULL DEFAULT UUID() COMMENT 'UUID Public Identifier (ADR-019)',
|
||||
source_file VARCHAR(255) NOT NULL COMMENT 'Path ของไฟล์ต้นทาง',
|
||||
source_metadata JSON NULL COMMENT 'Metadata จาก Excel/แหล่งข้อมูลต้นทาง',
|
||||
ai_extracted_metadata JSON NULL COMMENT 'Metadata ที่ AI สกัดได้',
|
||||
confidence_score DECIMAL(3, 2) NULL COMMENT 'คะแนนความมั่นใจ AI (0.00-1.00)',
|
||||
STATUS ENUM(
|
||||
'PENDING_REVIEW',
|
||||
'VERIFIED',
|
||||
'IMPORTED',
|
||||
'FAILED'
|
||||
) NOT NULL DEFAULT 'PENDING_REVIEW' COMMENT 'สถานะ: PENDING_REVIEW=รอตรวจ, VERIFIED=ตรวจแล้ว, IMPORTED=นำเข้าแล้ว, FAILED=ล้มเหลว',
|
||||
admin_feedback TEXT NULL COMMENT 'ความเห็นจาก Admin ผู้ตรวจสอบ',
|
||||
reviewed_by INT NULL COMMENT 'User ID ของ Admin ที่ตรวจสอบ (FK users.id)',
|
||||
reviewed_at TIMESTAMP NULL COMMENT 'เวลาที่ตรวจสอบ',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้าง',
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'วันที่แก้ไขล่าสุด',
|
||||
UNIQUE INDEX idx_migration_logs_uuid (uuid),
|
||||
INDEX idx_migration_logs_status (STATUS),
|
||||
INDEX idx_migration_logs_confidence (confidence_score),
|
||||
FOREIGN KEY (reviewed_by) REFERENCES users (user_id) ON DELETE
|
||||
SET NULL
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ตารางเก็บบันทึก Migration เอกสารที่ผ่าน AI Processing (Task BE-AI-02)';
|
||||
|
||||
-- ตาราง Audit Log สำหรับการทำงานของ AI ทุกครั้ง (ADR-018 Rule 5)
|
||||
CREATE TABLE ai_audit_logs (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'Internal PK (ห้าม expose ใน API)',
|
||||
uuid UUID NOT NULL DEFAULT UUID() COMMENT 'UUID Public Identifier (ADR-019)',
|
||||
document_public_id UUID NULL COMMENT 'UUID ของ migration_logs ที่เกี่ยวข้อง',
|
||||
ai_model VARCHAR(50) NOT NULL COMMENT 'ชื่อ AI Model ที่ใช้ประมวลผล เช่น gemma4',
|
||||
processing_time_ms INT NULL COMMENT 'เวลาประมวลผล (milliseconds)',
|
||||
confidence_score DECIMAL(3, 2) NULL COMMENT 'คะแนนความมั่นใจ AI (0.00-1.00)',
|
||||
input_hash VARCHAR(64) NULL COMMENT 'SHA-256 hash ของ Input เพื่อ Audit',
|
||||
output_hash VARCHAR(64) NULL COMMENT 'SHA-256 hash ของ Output เพื่อ Audit',
|
||||
STATUS ENUM('SUCCESS', 'FAILED', 'TIMEOUT') NOT NULL COMMENT 'สถานะการประมวลผล',
|
||||
error_message TEXT NULL COMMENT 'ข้อความ Error (ถ้ามี)',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้าง',
|
||||
UNIQUE INDEX idx_ai_audit_logs_uuid (uuid),
|
||||
INDEX idx_ai_audit_document (document_public_id),
|
||||
INDEX idx_ai_audit_model (ai_model),
|
||||
INDEX idx_ai_audit_status (STATUS)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ตาราง Audit Log การทำงาน AI ทุกครั้ง (ADR-018 Rule 5 Audit Logging)';
|
||||
|
||||
@@ -11,53 +11,17 @@
|
||||
## 🛠️ Implementation Tasks
|
||||
|
||||
### **AI-2.1: Database Schema Design (SQL First Approach)**
|
||||
- [ ] **Create `migration_logs` Table:**
|
||||
```sql
|
||||
CREATE TABLE migration_logs (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
publicId BINARY(16) DEFAULT (UUID_TO_BIN(UUID(), 1)),
|
||||
source_file VARCHAR(255) NOT NULL,
|
||||
source_metadata JSON,
|
||||
ai_extracted_metadata JSON,
|
||||
confidence_score DECIMAL(3,2),
|
||||
status ENUM('PENDING_REVIEW', 'VERIFIED', 'IMPORTED', 'FAILED') DEFAULT 'PENDING_REVIEW',
|
||||
admin_feedback TEXT,
|
||||
reviewed_by INT NULL,
|
||||
reviewed_at TIMESTAMP NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_status (status),
|
||||
INDEX idx_confidence (confidence_score),
|
||||
INDEX idx_publicId (publicId)
|
||||
);
|
||||
```
|
||||
- [ ] **Create `ai_audit_logs` Table:**
|
||||
```sql
|
||||
CREATE TABLE ai_audit_logs (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
publicId BINARY(16) DEFAULT (UUID_TO_BIN(UUID(), 1)),
|
||||
document_publicId BINARY(16),
|
||||
ai_model VARCHAR(50) NOT NULL,
|
||||
processing_time_ms INT,
|
||||
confidence_score DECIMAL(3,2),
|
||||
input_hash VARCHAR(64),
|
||||
output_hash VARCHAR(64),
|
||||
status ENUM('SUCCESS', 'FAILED', 'TIMEOUT') NOT NULL,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_document (document_publicId),
|
||||
INDEX idx_model (ai_model),
|
||||
INDEX idx_status (status),
|
||||
FOREIGN KEY (document_publicId) REFERENCES migration_logs(publicId)
|
||||
);
|
||||
```
|
||||
- [ ] **Update Data Dictionary:**
|
||||
- Add field descriptions to `specs/03-Data-and-Storage/03-01-data-dictionary.md`
|
||||
- Include business rules for confidence thresholds
|
||||
- Document status transitions and workflows
|
||||
- [x] **Create `migration_logs` Table:** — เพิ่มใน `specs/03-Data-and-Storage/lcbp3-v1.8.0-schema-02-tables.sql` (Section 11)
|
||||
- ใช้ `uuid UUID NOT NULL DEFAULT UUID()` แทน `BINARY(16)` ตาม pattern ปัจจุบัน (ADR-019)
|
||||
- FK → `users.user_id` สำหรับ `reviewed_by`
|
||||
- [x] **Create `ai_audit_logs` Table:** — เพิ่มในไฟล์ schema เดียวกัน
|
||||
- `document_public_id` เป็น Soft Reference (ไม่มี FK constraint) เพื่อ Audit Trail ถาวร
|
||||
- [x] **Update Data Dictionary:**
|
||||
- เพิ่ม Section 19 ใน `specs/03-Data-and-Storage/03-01-data-dictionary.md`
|
||||
- ครอบคลุม Confidence Scoring Strategy, State Machine, JSON Schema
|
||||
|
||||
### **AI-2.2: AI Gateway Module Architecture**
|
||||
- [ ] **Module Structure:**
|
||||
- [x] **Module Structure:**
|
||||
```typescript
|
||||
// src/modules/ai/ai.module.ts
|
||||
@Module({
|
||||
@@ -68,7 +32,7 @@
|
||||
})
|
||||
export class AiModule {}
|
||||
```
|
||||
- [ ] **AiService Implementation:**
|
||||
- [x] **AiService Implementation:**
|
||||
```typescript
|
||||
@Injectable()
|
||||
export class AiService {
|
||||
@@ -93,7 +57,7 @@
|
||||
}
|
||||
}
|
||||
```
|
||||
- [ ] **Configuration Management:**
|
||||
- [x] **Configuration Management:**
|
||||
```env
|
||||
# .env
|
||||
AI_N8N_WEBHOOK_URL=http://192.168.1.100:5678/webhook/ai-processing
|
||||
@@ -104,7 +68,7 @@
|
||||
```
|
||||
|
||||
### **AI-2.3: Migration Engine & Business Logic**
|
||||
- [ ] **MigrationService Implementation:**
|
||||
- [x] **MigrationService Implementation:** — `AiService` implements `stageLegacyData` logic (via `extractRealtime`), `compareData` via `AiValidationService`, `approveMigration` via `updateMigrationLog`
|
||||
```typescript
|
||||
@Injectable()
|
||||
export class MigrationService {
|
||||
@@ -130,7 +94,7 @@
|
||||
}
|
||||
}
|
||||
```
|
||||
- [ ] **Status Management Workflow:**
|
||||
- [x] **Status Management Workflow:**
|
||||
```typescript
|
||||
enum MigrationStatus {
|
||||
PENDING_REVIEW = 'PENDING_REVIEW',
|
||||
@@ -149,7 +113,7 @@
|
||||
```
|
||||
|
||||
### **AI-2.4: API Endpoints & Security Implementation**
|
||||
- [ ] **Admin Migration Endpoints:**
|
||||
- [x] **Admin Migration Endpoints:** — `GET /api/ai/migration` + `PATCH /api/ai/migration/:publicId` ใน `AiController` พร้อม `JwtAuthGuard + RbacGuard + RequirePermission`
|
||||
```typescript
|
||||
@Controller('admin/migration')
|
||||
@UseGuards(JwtAuthGuard, CaslGuard)
|
||||
@@ -175,7 +139,7 @@
|
||||
}
|
||||
}
|
||||
```
|
||||
- [ ] **Real-time AI Extraction Endpoint:**
|
||||
- [x] **Real-time AI Extraction Endpoint:** — `POST /api/ai/extract` (rate limit 5/min) + `POST /api/ai/callback` (service account auth)
|
||||
```typescript
|
||||
@Controller('ai')
|
||||
export class AiController {
|
||||
@@ -189,12 +153,12 @@
|
||||
}
|
||||
}
|
||||
```
|
||||
- [ ] **Security Measures:**
|
||||
- CASL permissions for all endpoints
|
||||
- Idempotency-Key header validation
|
||||
- Rate limiting on AI endpoints
|
||||
- JWT authentication for service accounts
|
||||
- Request/response logging for audit
|
||||
- [x] **Security Measures:**
|
||||
- RbacGuard + RequirePermission on admin endpoints
|
||||
- Idempotency-Key header documented on PATCH endpoint
|
||||
- Rate limiting (`@Throttle 5/min`) on `/ai/extract`
|
||||
- Bearer token validation on `/ai/callback`
|
||||
- AuditLog saved for every AI interaction (ADR-018 Rule 5)
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user