690530:1345 ADR-030-231-ocr-sandbox-two-step-flow #05
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
// - 2026-05-15: เพิ่ม OCR auto-detection service สำหรับ ADR-023A.
|
||||
// - 2026-05-25: แก้ไข AggregateError (empty message) จาก axios โดย wrap เป็น Error พร้อม context ที่ชัดเจน.
|
||||
// - 2026-05-25: เพิ่ม path remapping (OCR_UPLOAD_BASE_PATH) เพื่อแปลง local upload path เป็น path ที่ sidecar เห็นผ่าน CIFS.
|
||||
// - 2026-05-29: เพิ่ม checkHealth() เพื่อตรวจสอบสุขภาพของ PaddleOCR sidecar สำหรับ getSystemHealth() (ADR-027)
|
||||
// - 2026-05-29: เพิ่ม checkHealth() เพื่อตรวจสอบสุขภาพของ OCR sidecar สำหรับ getSystemHealth() (ADR-027)
|
||||
// - 2026-05-30: เปลี่ยนจาก PaddleOCR เป็น Tesseract OCR เพื่อความเข้ากันได้กับ CPU เก่า
|
||||
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
@@ -20,7 +21,7 @@ export interface OcrDetectionResult {
|
||||
ocrUsed: boolean;
|
||||
}
|
||||
|
||||
interface PaddleOcrResponse {
|
||||
interface OcrSidecarResponse {
|
||||
text?: string;
|
||||
}
|
||||
|
||||
@@ -31,7 +32,7 @@ export interface OcrHealthResult {
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/** บริการเลือก fast path หรือ PaddleOCR sidecar ตามจำนวนตัวอักษรที่ extract ได้ */
|
||||
/** บริการเลือก fast path หรือ OCR sidecar (Tesseract) ตามจำนวนตัวอักษรที่ extract ได้ */
|
||||
@Injectable()
|
||||
export class OcrService {
|
||||
private readonly logger = new Logger(OcrService.name);
|
||||
@@ -64,7 +65,7 @@ export class OcrService {
|
||||
return localPath;
|
||||
}
|
||||
|
||||
/** ตรวจสอบสุขภาพและ latency ของ PaddleOCR sidecar ผ่าน GET /health */
|
||||
/** ตรวจสอบสุขภาพและ latency ของ OCR sidecar (Tesseract) ผ่าน GET /health */
|
||||
async checkHealth(): Promise<OcrHealthResult> {
|
||||
const startTime = Date.now();
|
||||
try {
|
||||
@@ -105,7 +106,7 @@ export class OcrService {
|
||||
try {
|
||||
const sidecarPath = this.remapPath(input.pdfPath);
|
||||
this.logger.debug(`OCR path remap: ${input.pdfPath} → ${sidecarPath}`);
|
||||
const response = await axios.post<PaddleOcrResponse>(
|
||||
const response = await axios.post<OcrSidecarResponse>(
|
||||
`${this.ocrApiUrl}/ocr`,
|
||||
{ pdfPath: sidecarPath },
|
||||
{ timeout: 90000 }
|
||||
@@ -124,7 +125,7 @@ export class OcrService {
|
||||
? err.message
|
||||
: String(err);
|
||||
throw new Error(
|
||||
`PaddleOCR sidecar unreachable at ${this.ocrApiUrl} — ${cause}`
|
||||
`OCR sidecar (Tesseract) unreachable at ${this.ocrApiUrl} — ${cause}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -508,7 +508,7 @@ export default function OcrSandboxPromptManager() {
|
||||
OCR Raw Text (Step 1 Result)
|
||||
</CardTitle>
|
||||
<Badge variant="outline" className="text-xs">
|
||||
{ocrResult.ocrUsed ? 'PaddleOCR' : 'Fast Path (Text Layer)'}
|
||||
{ocrResult.ocrUsed ? 'Tesseract' : 'Fast Path (Text Layer)'}
|
||||
</Badge>
|
||||
</CardHeader>
|
||||
<CardContent className="pt-4">
|
||||
|
||||
+72
-22
@@ -10,6 +10,7 @@
|
||||
- 2026-05-25 (Session 7): PaddleOCR Sidecar setup บน Desk-5439 — สร้าง FastAPI sidecar (port 8765) รองรับ `/ocr` + `/normalize`, แก้ AggregateError ใน ocr.service.ts, เพิ่ม path remapping (`OCR_SIDECAR_UPLOAD_BASE`), CIFS volume mount จาก QNAP.
|
||||
- 2026-05-26: เพิ่ม system memories ที่หายไป — QNAP SSH Key Authentication, TransformInterceptor double registration, ADR-021 Transmittals/Circulation integration, Correspondence detail fixes, Playwright E2E setup, Tag/Contract UUID fixes.
|
||||
- 2026-05-27: Context-Aware Prompts & DB CC Typo Cleanup (ADR-030) — นำเสนอการผูก Master Data เข้ากับ Prompt Extraction, ออกแบบ JSON Context-Aware configuration, อัปเดต Entity/DTOs, ออกแบบ JSON format ผู้รับเป็น Object Array ป้องกันบัค และแก้ whitespace typo 'CC ' ในฐานข้อมูล
|
||||
- 2026-05-30 (Session 8): OCR Engine Migration — เปลี่ยนจาก PaddleOCR เป็น Tesseract OCR เพื่อแก้ปัญหา SIGILL (Illegal Instruction) บน CPU เก่าที่ไม่รองรับ AVX: อัปเดต requirements.txt (ลบ paddlepaddle/paddleocr, เพิ่ม pytesseract), app.py (เปลี่ยนใช้ pytesseract, OCR_LANG=tha+eng), Dockerfile (ติดตั้ง tesseract-ocr + ภาษาไทย/อังกฤษ), docker-compose.yml (OCR_LANG=tha+eng, ลบ paddleocr_models volume), backend ocr.service.ts (เปลี่ยน comment/error message), frontend OcrSandboxPromptManager.tsx (เปลี่ยน Badge text)
|
||||
-->
|
||||
|
||||
# 🧠 Agent Long-term Project Memory
|
||||
@@ -184,18 +185,18 @@ docker compose ps # Check status
|
||||
|
||||
## 🌐 7. Environment & Services
|
||||
|
||||
| Service | Local URL / Port | Production | Notes |
|
||||
| ---------------- | ----------------------------- | ------------------------- | ------------------------------------ |
|
||||
| **Backend API** | `http://localhost:3001` | QNAP `192.168.10.8` | NestJS — `/api` prefix |
|
||||
| **Frontend** | `http://localhost:3000` | QNAP `192.168.10.8` | Next.js |
|
||||
| **MariaDB** | `localhost:3307` | QNAP internal | DB: `lcbp3`, root via docker |
|
||||
| **Redis** | `localhost:6379` | QNAP internal | BullMQ + session store |
|
||||
| **n8n** | `http://localhost:5678` | QNAP `192.168.10.8:5678` | Migration orchestrator only |
|
||||
| **Ollama** | `http://192.168.10.100:11434` | Admin Desktop (Desk-5439) | gemma4:e2b + nomic-embed-text |
|
||||
| **Qdrant** | `http://localhost:6333` | Admin Desktop (Desk-5439) | Vector DB — requires projectPublicId |
|
||||
| **PaddleOCR** | `http://192.168.10.100:8765` | Admin Desktop (Desk-5439) | `/ocr` + `/normalize` (FastAPI) |
|
||||
| **Gitea** | `https://git.np-dms.work` | QNAP `192.168.10.8` | Source + CI/CD |
|
||||
| **Gitea Runner** | ASUSTOR `192.168.10.9` | — | CI runner |
|
||||
| Service | Local URL / Port | Production | Notes |
|
||||
| ----------------- | ----------------------------- | ------------------------- | ------------------------------------ |
|
||||
| **Backend API** | `http://localhost:3001` | QNAP `192.168.10.8` | NestJS — `/api` prefix |
|
||||
| **Frontend** | `http://localhost:3000` | QNAP `192.168.10.8` | Next.js |
|
||||
| **MariaDB** | `localhost:3307` | QNAP internal | DB: `lcbp3`, root via docker |
|
||||
| **Redis** | `localhost:6379` | QNAP internal | BullMQ + session store |
|
||||
| **n8n** | `http://localhost:5678` | QNAP `192.168.10.8:5678` | Migration orchestrator only |
|
||||
| **Ollama** | `http://192.168.10.100:11434` | Admin Desktop (Desk-5439) | gemma4:e2b + nomic-embed-text |
|
||||
| **Qdrant** | `http://localhost:6333` | Admin Desktop (Desk-5439) | Vector DB — requires projectPublicId |
|
||||
| **Tesseract OCR** | `http://192.168.10.100:8765` | Admin Desktop (Desk-5439) | `/ocr` + `/normalize` (FastAPI) |
|
||||
| **Gitea** | `https://git.np-dms.work` | QNAP `192.168.10.8` | Source + CI/CD |
|
||||
| **Gitea Runner** | ASUSTOR `192.168.10.9` | — | CI runner |
|
||||
|
||||
### Key Environment Variables (ตรวจสอบใน `docker-compose.yml`)
|
||||
|
||||
@@ -211,15 +212,16 @@ QDRANT_URL
|
||||
|
||||
## 🚀 8. Recent Rollouts
|
||||
|
||||
| วันที่ | Version | รายการ | สถานะ |
|
||||
| ---------- | ------- | ---------------------------------------------------------------------------------------------------- | --------------------------- |
|
||||
| 2026-05-23 | v1.9.6 | Specs reorganization (`100/200/300-*` folders), AGENTS.md v1.9.6 update | ✅ Complete |
|
||||
| 2026-05-23 | v1.9.6 | N8N Workflow v2 (`n8n.workflow.v2.json`) — ADR-023A compliant, ลบ Ollama direct | ⏳ Pending import to n8n UI |
|
||||
| 2026-05-24 | v1.9.6 | AGENTS.md Project Memory Override rule (Windsurf / Antigravity / Codex) | ✅ Complete |
|
||||
| 2026-05-25 | v1.9.6 | Migration Queue attachment UUID fix — DTO + Service + n8n.workflow.v2.json (Session 3) | ✅ Complete (tsc verified) |
|
||||
| 2026-05-25 | v1.9.6 | Migration error normalization + `job_id` logging — workflow + backend + SQL/delta (Session 4) | ✅ Complete |
|
||||
| 2026-05-25 | v1.9.6 | PaddleOCR Sidecar บน Desk-5439 — FastAPI `/ocr`+`/normalize`, CIFS mount, path remapping (Session 7) | ✅ Running |
|
||||
| 2026-05-27 | v1.9.7 | Context-Aware Prompt Templates & DB CC Whitespace Cleanup (ADR-030) (Session 9) | ✅ Complete (v1.9.7 main) |
|
||||
| วันที่ | Version | รายการ | สถานะ |
|
||||
| ---------- | ------- | ---------------------------------------------------------------------------------------------------- | ----------------------------- |
|
||||
| 2026-05-23 | v1.9.6 | Specs reorganization (`100/200/300-*` folders), AGENTS.md v1.9.6 update | ✅ Complete |
|
||||
| 2026-05-23 | v1.9.6 | N8N Workflow v2 (`n8n.workflow.v2.json`) — ADR-023A compliant, ลบ Ollama direct | ⏳ Pending import to n8n UI |
|
||||
| 2026-05-24 | v1.9.6 | AGENTS.md Project Memory Override rule (Windsurf / Antigravity / Codex) | ✅ Complete |
|
||||
| 2026-05-25 | v1.9.6 | Migration Queue attachment UUID fix — DTO + Service + n8n.workflow.v2.json (Session 3) | ✅ Complete (tsc verified) |
|
||||
| 2026-05-25 | v1.9.6 | Migration error normalization + `job_id` logging — workflow + backend + SQL/delta (Session 4) | ✅ Complete |
|
||||
| 2026-05-25 | v1.9.6 | PaddleOCR Sidecar บน Desk-5439 — FastAPI `/ocr`+`/normalize`, CIFS mount, path remapping (Session 7) | ✅ Running |
|
||||
| 2026-05-27 | v1.9.7 | Context-Aware Prompt Templates & DB CC Whitespace Cleanup (ADR-030) (Session 9) | ✅ Complete (v1.9.7 main) |
|
||||
| 2026-05-30 | v1.9.7 | OCR Engine Migration — PaddleOCR → Tesseract (Session 8) | ✅ Complete (pending rebuild) |
|
||||
|
||||
---
|
||||
|
||||
@@ -450,7 +452,51 @@ OCR_SIDECAR_UPLOAD_BASE=/mnt/uploads (env var)
|
||||
|
||||
---
|
||||
|
||||
### Session 8 — 2026-05-26 (System Memories Consolidation)
|
||||
### Session 8 — 2026-05-30 (OCR Engine Migration — PaddleOCR → Tesseract)
|
||||
|
||||
#### ปัญหาที่พบ (Root Cause)
|
||||
|
||||
**Bug 1: PaddleOCR SIGILL (Illegal Instruction)**
|
||||
|
||||
- PaddleOCR 2.6.2 ต้องการ AVX instruction set ซึ่ง CPU บน Desk-5439 ไม่รองรับ
|
||||
- ลองลดรุ่นเป็น 2.5.2 → ยังมี dependency conflict กับ paddleocr 2.7.3
|
||||
- ลองใช้ paddlepaddle-cpu → ยังคงมีปัญหา dependency
|
||||
|
||||
**Bug 2: OCR ภาษาไทยผิด**
|
||||
|
||||
- PaddleOCR ตั้งค่า `lang="en"` ทำให้ข้อความภาษาไทยถูกแปลงเป็นอักษรละตินผิดๆ
|
||||
- เช่น: "10 กุมภาพันธ์ 2568" → "10 qunnwus 2568"
|
||||
|
||||
#### การแก้ไข (Fix)
|
||||
|
||||
เปลี่ยนจาก PaddleOCR เป็น Tesseract OCR เพื่อ:
|
||||
|
||||
1. แก้ปัญหา SIGILL บน CPU เก่าที่ไม่รองรับ AVX
|
||||
2. รองรับภาษาไทยด้วย `tha+eng` language code
|
||||
|
||||
| ไฟล์ | การเปลี่ยนแปลง |
|
||||
| ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
||||
| `specs/04-Infrastructure-OPS/04-00-docker-compose/Desk-5439/ocr-sidecar/requirements.txt` | ลบ paddlepaddle/paddleocr, เพิ่ม pytesseract, Pillow |
|
||||
| `specs/04-Infrastructure-OPS/04-00-docker-compose/Desk-5439/ocr-sidecar/app.py` | เปลี่ยนใช้ pytesseract, OCR_LANG เป็น `tha+eng`, ลบ PaddleOCR initialization |
|
||||
| `specs/04-Infrastructure-OPS/04-00-docker-compose/Desk-5439/ocr-sidecar/Dockerfile` | ติดตั้ง tesseract-ocr, tesseract-ocr-tha, tesseract-ocr-eng |
|
||||
| `specs/04-Infrastructure-OPS/04-00-docker-compose/Desk-5439/ocr-sidecar/docker-compose.yml` | OCR_LANG เป็น `tha+eng`, ลบ paddleocr_models volume |
|
||||
| `backend/src/modules/ai/services/ocr.service.ts` | เปลี่ยน comment/error message จาก PaddleOCR เป็น Tesseract |
|
||||
| `frontend/components/admin/ai/OcrSandboxPromptManager.tsx` | เปลี่ยน Badge text จาก PaddleOCR เป็น Tesseract |
|
||||
|
||||
#### กฎที่ Lock แล้ว
|
||||
|
||||
- Tesseract OCR ไม่ต้องการ AVX instruction set → ทำงานได้บน CPU ทุกรุ่น
|
||||
- Tesseract รองรับภาษาไทยด้วย `tha+eng` language code
|
||||
- API contract ยังเหมือนเดิม (`POST /ocr` คืน `{ text, ocrUsed }`) → backend/frontend ไม่ต้องเปลี่ยน logic
|
||||
|
||||
#### Verification ที่ต้องทำ
|
||||
|
||||
- Rebuild container บน Desk-5439: `docker compose down && docker compose up -d --build`
|
||||
- ทดสอบ OCR ภาษาไทย: "10 กุมภาพันธ์ 2568" ควรออกมาถูกต้อง
|
||||
|
||||
---
|
||||
|
||||
### Session 9 — 2026-05-26 (System Memories Consolidation)
|
||||
|
||||
#### QNAP SSH Key Authentication & CI/CD Deployment
|
||||
|
||||
@@ -649,6 +695,7 @@ npx playwright show-report # Generate report
|
||||
**Summary:** ดำเนินการอิมพลีเมนต์ ADR-030 (Context-Aware Prompt Templates สำหรับการสกัดข้อมูลเอกสาร) และทำการแก้ไขบัคช่องว่างประเภทผู้รับ `'CC '` ในฐานข้อมูล
|
||||
|
||||
**Backend Changes (B1-B6):**
|
||||
|
||||
- **AiPrompt Entity**: เพิ่มการแมปคอลัมน์ `contextConfig` ไปยัง JSON ฟิลด์ `context_config` ในฐานข้อมูลเพื่อควบคุม master data resolution
|
||||
- **CreateAiPromptDto / Response DTO**: ปรับแต่งให้รองรับการรับและส่งออกคอลัมน์ `contextConfig`
|
||||
- **AiPromptsService**:
|
||||
@@ -662,14 +709,17 @@ npx playwright show-report # Generate report
|
||||
- แก้ไข mock dependencies ของ `AiPromptsService` ใน `ai-batch.processor.spec.ts` ป้องกันปัญหา `TypeError: getActive is not a function` ทำให้ผ่าน unit tests 100%
|
||||
|
||||
**Database & Schema Changes (ADR-009):**
|
||||
|
||||
- **schema-02-tables.sql**: แก้ไข line 338 ปรับปรุง `ENUM('TO', 'CC ')` เป็น `ENUM('TO', 'CC')`
|
||||
- **SQL Delta**: สร้าง `2026-05-27-add-context-aware-prompts-and-cleanup.sql` ดำเนินการ `UPDATE` ข้อมูลเก่าที่เป็น `'CC '` ให้เป็น `'CC'` เพื่อล้างช่องว่าง จากนั้นสั่ง `ALTER TABLE` ปรับปรุงฟิลด์ enum และ Seed template ภาษาไทยเวอร์ชัน 2
|
||||
- **Rollback SQL**: สร้างไฟล์ย้อนกลับ `2026-05-27-add-context-aware-prompts-and-cleanup.rollback.sql` เรียบร้อย
|
||||
|
||||
**Frontend Changes:**
|
||||
|
||||
- **detail.tsx**: ตรวจสอบการใช้งาน `normalizeRecipientType` ซึ่งครอบคลุมการล้างช่องว่างและการกรองผู้รับ TO/CC ได้อย่างทนทาน
|
||||
|
||||
**Verification:**
|
||||
|
||||
- `pnpm --filter backend build` — ✅ Compile ผ่านแบบ Strict Mode
|
||||
- unit tests AI module & backend suites — ✅ ผ่านทั้งหมด 60 suites / 521 tests
|
||||
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
# Change Log:
|
||||
# - 2026-05-25: Initial Dockerfile สำหรับ PaddleOCR sidecar (port 8765)
|
||||
# - 2026-05-30: เปลี่ยนจาก PaddleOCR เป็น Tesseract OCR เพื่อความเข้ากันได้กับ CPU เก่า
|
||||
# - 2026-05-30: เพิ่ม system dependencies สำหรับ OpenCV (libsm6, libxext6, libxrender1, libfontconfig1, libx11-6)
|
||||
|
||||
FROM python:3.10-slim
|
||||
|
||||
# ติดตั้ง system dependencies สำหรับ PDF processing, Tesseract OCR และภาษาไทย
|
||||
# ติดตั้ง system dependencies สำหรับ PDF processing, Tesseract OCR, ภาษาไทย และ OpenCV
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libglib2.0-0 \
|
||||
libgl1 \
|
||||
@@ -16,6 +17,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
tesseract-ocr \
|
||||
tesseract-ocr-tha \
|
||||
tesseract-ocr-eng \
|
||||
libsm6 \
|
||||
libxext6 \
|
||||
libxrender1 \
|
||||
libfontconfig1 \
|
||||
libx11-6 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# - 2026-05-25: Initial FastAPI server สำหรับ PaddleOCR sidecar
|
||||
# - 2026-05-30: เปลี่ยน lang='en' เป็น lang='ch' (CTJK) เพื่อรองรับภาษาไทย
|
||||
# - 2026-05-30: เปลี่ยนจาก PaddleOCR เป็น Tesseract OCR เพื่อความเข้ากันได้กับ CPU เก่า
|
||||
# - 2026-05-30: เพิ่ม OpenCV preprocessing (threshold, denoise) และ DPI 300 เพื่อเพิ่มความแม่นยำ
|
||||
|
||||
import os
|
||||
import logging
|
||||
@@ -15,6 +16,8 @@ from typing import Optional
|
||||
from PIL import Image
|
||||
import pytesseract
|
||||
import io
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel
|
||||
@@ -34,6 +37,26 @@ OCR_LANG = os.getenv("OCR_LANG", "tha+eng") # Tesseract language code (tha+eng
|
||||
logger.info(f"Tesseract OCR Sidecar initialized (lang={OCR_LANG})")
|
||||
|
||||
|
||||
def preprocess_image(pil_image: Image.Image) -> Image.Image:
|
||||
"""Preprocess image ด้วย OpenCV เพื่อเพิ่มความแม่นยำ OCR"""
|
||||
# แปลง PIL Image เป็น numpy array (OpenCV format)
|
||||
img_array = np.array(pil_image)
|
||||
|
||||
# แปลงเป็น grayscale
|
||||
gray = cv2.cvtColor(img_array, cv2.COLOR_RGB2GRAY)
|
||||
|
||||
# Denoise ด้วย median blur
|
||||
denoised = cv2.medianBlur(gray, 3)
|
||||
|
||||
# Adaptive threshold เพื่อแยก background จาก text
|
||||
thresh = cv2.adaptiveThreshold(
|
||||
denoised, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2
|
||||
)
|
||||
|
||||
# แปลงกลับเป็น PIL Image
|
||||
return Image.fromarray(thresh)
|
||||
|
||||
|
||||
class OcrRequest(BaseModel):
|
||||
pdfPath: str
|
||||
maxPages: Optional[int] = None
|
||||
@@ -89,10 +112,14 @@ def ocr_extract(req: OcrRequest):
|
||||
ocr_text_parts = []
|
||||
for i in pages_to_process:
|
||||
page = doc[i]
|
||||
pix = page.get_pixmap(dpi=200)
|
||||
pix = page.get_pixmap(dpi=300) # เพิ่ม DPI เป็น 300 เพื่อความชัด
|
||||
img_bytes = pix.tobytes("png")
|
||||
img = Image.open(io.BytesIO(img_bytes))
|
||||
text = pytesseract.image_to_string(img, lang=OCR_LANG)
|
||||
|
||||
# Preprocess ด้วย OpenCV เพื่อเพิ่มความแม่นยำ
|
||||
processed_img = preprocess_image(img)
|
||||
|
||||
text = pytesseract.image_to_string(processed_img, lang=OCR_LANG)
|
||||
ocr_text_parts.append(text.strip())
|
||||
|
||||
ocr_text = "\n".join(ocr_text_parts).strip()
|
||||
|
||||
+2
@@ -2,6 +2,7 @@
|
||||
# Change Log:
|
||||
# - 2026-05-30: เปลี่ยนจาก PaddleOCR เป็น Tesseract OCR เพื่อความเข้ากันได้กับ CPU เก่า (ไม่ต้องการ AVX)
|
||||
# - 2026-05-30: ลบ paddlepaddle/paddleocr dependencies เนื่องจาก SIGILL บน CPU ที่ไม่รองรับ AVX
|
||||
# - 2026-05-30: เพิ่ม opencv-python สำหรับ image preprocessing (threshold, denoise) เพื่อเพิ่มความแม่นยำ OCR
|
||||
|
||||
numpy<2.0
|
||||
PyMuPDF==1.24.0
|
||||
@@ -12,3 +13,4 @@ python-multipart==0.0.9
|
||||
pythainlp==5.0.4
|
||||
httpx==0.27.0
|
||||
Pillow==10.0.0
|
||||
opencv-python==4.8.1.78
|
||||
|
||||
Reference in New Issue
Block a user