Demo cho giải pháp extract dữ liệu văn bản từ file scan pdf hay ảnh
  • Python 62.8%
  • TypeScript 36.6%
  • Makefile 0.3%
  • Dockerfile 0.2%
  • Mako 0.1%
Find a file
tant d3cf0199a2 docs: update README to reflect current state
Changes:
- Fix demo URL: molly.tetra.vn → molly.carp.vn (correct domain)
- Use documents dashboard as hero image (more impactful than review page)
- Add 2x2 screenshot gallery showcasing 4 key pages
- Add 🎨 emoji icons to feature list for scannability
- Mention PageHeader + breadcrumb navigation (new UI)
- Document NEXT_PUBLIC_API_BASE_URL as build-time env var with warning
- Add production HTTPS section with Caddy reverse proxy example
- Add WEBHOOK_SIGNING_SECRET, FILE_SIGNING_SECRET, MEILI_MASTER_KEY
  to env var table
- Add /api/v1/integration/records/{id} to integration API list
- Add proposal.md, state.md to documentation index
- Expand tech stack: react-pdf, dayjs, Caddy, openai SDK, PyMuPDF
- Replace ASCII architecture diagram with unicode box-drawing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 15:38:13 +04:00
api fix(api,web): security fixes and robustness improvements 2026-04-17 18:27:25 +04:00
docs docs(user-guide): refresh screenshots and content for v2.0 UI 2026-04-24 15:28:59 +04:00
scripts feat(scripts): seed integration clients + webhook subscriptions 2026-04-16 12:39:54 +04:00
web docs(user-guide): refresh screenshots and content for v2.0 UI 2026-04-24 15:28:59 +04:00
.env.example feat(infra): add file_storage_path config + volume mount 2026-04-15 17:58:13 +04:00
.gitignore docs: add E2E screenshots to user guide 2026-04-17 19:02:41 +04:00
docker-compose.yml fix(web): pass NEXT_PUBLIC_API_BASE_URL as build arg 2026-04-24 11:52:59 +04:00
Makefile chore: sprint 0 — bootstrap project scaffold 2026-04-15 13:43:31 +04:00
README.md docs: update README to reflect current state 2026-04-24 15:38:13 +04:00

Molly — Hệ thống Số hóa Văn bản AI

Số hóa văn bản giấy tờ tự động bằng trí tuệ nhân tạo. Upload PDF/ảnh → AI phân loại → trích xuất dữ liệu có cấu trúc → review → lưu tra cứu full-text.

Demo trực tuyến: https://molly.carp.vn · Source: https://wedev.carp.vn/tant/molly

Dashboard hồ sơ

Tính năng

  • 📄 Thiết kế kiểu văn bản không cần code — Tạo schema cho từng loại giấy tờ (khai sinh, kết hôn, hợp đồng...) với primitive/array/nested object, enum, flag nhạy cảm.
  • Đề xuất schema từ AI — Upload file mẫu, hệ thống Gemma 4 phân tích và đề xuất cấu trúc schema tự động.
  • ☁️ Upload & xử lý tự động — PDF/PNG/JPG/TIFF, auto convert, phân loại theo tiêu đề, trích xuất dữ liệu multimodal.
  • Review side-by-side — Xem PDF gốc cạnh form dữ liệu, chỉnh sửa và duyệt chính thức.
  • ✏️ Đính chính có lý do — Sửa hồ sơ đã duyệt với JSON Patch, lưu audit trail đầy đủ.
  • 🔍 Tra cứu full-text — Meilisearch với highlight từ khóa, lọc theo kiểu văn bản.
  • 🔌 Integration API — API key auth, webhook outbound có chữ ký HMAC, signed file URL.
  • 📋 Audit log — Append-only, ghi nhận mọi thao tác quan trọng (upload, approve, correct, cancel).
  • 🎨 Giao diện hiện đại — Breadcrumb navigation, responsive, thống nhất design trên 11 trang.

Kiến trúc

┌──────────────────────────────────────────────────┐
│   Browser (Next.js 16 + Ant Design)               │
└────────────────────┬─────────────────────────────┘
                     │ HTTPS (qua Caddy reverse proxy)
┌────────────────────▼─────────────────────────────┐
│   FastAPI (Python 3.12, async SQLAlchemy)         │
└──┬──────────────┬──────────────┬──────────────┬──┘
   │              │              │              │
   ▼              ▼              ▼              ▼
┌──────┐   ┌──────────┐   ┌───────────┐   ┌──────────┐
│ PG16 │   │ Temporal │   │Meilisearch│   │ Gemma 4  │
│      │   │  (orch.) │   │  (search) │   │(Ollama/  │
│      │   │          │   │           │   │LM Studio)│
└──────┘   └──────────┘   └───────────┘   └──────────┘
Component Vai trò
web Next.js 16 client-side, Ant Design v6, TanStack Query v5, PageHeader + breadcrumb nav
api FastAPI async, SQLAlchemy 2.0, Pydantic v2, unit-of-work session
worker-document Temporal workflow: convert PDF, classify, extract
worker-ai Activity gọi Gemma 4 multimodal (concurrency hạn chế 1-2)
worker-webhook Outbound webhook delivery với HMAC signature, exponential backoff
worker-outbox Đồng bộ Meilisearch qua outbox pattern (atomic với approve)
postgres PostgreSQL 16, schema app (business) + temporal (workflow store)
temporal Workflow orchestration, durable retry
meilisearch Full-text search engine, 1 index approved_records

Demo giao diện

Review side-by-side
Review side-by-side PDF + form
Tra cứu
Tra cứu full-text với highlight
Schemas
Quản lý kiểu văn bản
Upload
Upload 2-column với tips

Xem đầy đủ 10 ảnh minh họa tại docs/user-guide.md.

Yêu cầu

  • Docker & Docker Compose v2
  • AI inference server chạy trên host với model Gemma 4:
    • Dev: Ollama + gemma4:e4b (~9.6 GB, chạy được trên GPU 16 GB VRAM)
    • Prod: LM Studio + Gemma 4 26B MoE hoặc 31B trên Mac Studio M4 Max ≥96 GB unified memory
  • Reverse proxy (tùy chọn, cho HTTPS production): Caddy/Nginx

Cài đặt nhanh

# 1. Clone và cấu hình
git clone https://wedev.carp.vn/tant/molly.git molly-quy-ngs
cd molly-quy-ngs
cp .env.example .env

# 2. Sửa .env:
#    AI_BASE_URL=http://host.docker.internal:11434/v1  (Ollama trên host)
#    NEXT_PUBLIC_API_BASE_URL=http://localhost:30081   (dev) 
#      hoặc https://molly.yourdomain.vn                 (prod qua reverse proxy)
#    CORS_ORIGINS=http://localhost:30080,https://molly.yourdomain.vn

# 3. Khởi động tất cả services
docker compose up -d --build

# 4. Chạy database migration
docker compose exec api alembic upgrade head

# 5. Kiểm tra health
curl http://localhost:30081/health | jq .

Mở trình duyệt tại http://localhost:30080 để bắt đầu sử dụng.

⚠️ Chú ý: Biến NEXT_PUBLIC_API_BASE_URL được inline vào bundle JS lúc build. Đổi giá trị thì phải rebuild docker compose build --no-cache web.

Cấu hình

Biến môi trường Mô tả Mặc định
WEB_PORT Cổng web UI 30080
API_PORT Cổng API 30081
TEMPORAL_UI_PORT Cổng Temporal UI 30082
POSTGRES_PORT Cổng PostgreSQL 30432
MEILISEARCH_PORT Cổng Meilisearch 30700
AI_BASE_URL URL AI inference server http://host.docker.internal:11434/v1
AI_MODEL Model AI sử dụng gemma4:e4b
NEXT_PUBLIC_API_BASE_URL URL API từ browser (build arg)
CORS_ORIGINS Allowed origins (phân cách bằng dấu phẩy)
FILE_STORAGE_PATH Thư mục lưu file /var/molly/files
MEILI_MASTER_KEY API key Meilisearch
WEBHOOK_SIGNING_SECRET Secret ký HMAC webhook change-me-...
FILE_SIGNING_SECRET Secret ký signed file URL change-me-...

Xem đầy đủ tại .env.example.

Luồng xử lý

Upload file → Convert PDF → Phân loại AI → Trích xuất AI → Chờ review
                                  │                              │
                                  ▼                              ▼
                          (auto match                    Người dùng sửa
                           theo tiêu đề)                      + duyệt
                                  │                              │
                                  ▼                              ▼
                        Chờ xác nhận kiểu            Đã duyệt → Meilisearch
                        ↑ user chọn thủ công           │         + Webhook
                                                        │
                                            Đính chính / Hủy
  1. Upload — PDF hoặc ảnh (PNG/JPG/TIFF), tự gộp nhiều ảnh thành 1 PDF
  2. Phân loại — AI đọc tiêu đề + fuzzy match (pg_trgm) với kiểu đã có
  3. Trích xuất — Gemma 4 multimodal extract theo schema (structured JSON)
  4. Review — Side-by-side PDF + form, chỉnh sửa trước khi duyệt
  5. Duyệt — Lưu chính thức, đồng bộ Meilisearch, gửi webhook (HMAC signed)

Cấu trúc thư mục

molly-quy-ngs/
├── api/                    # FastAPI backend
│   ├── app/
│   │   ├── api/v1/         # Route handlers
│   │   ├── services/       # Business logic
│   │   ├── models/         # SQLAlchemy models
│   │   ├── schemas/        # Pydantic DTOs
│   │   ├── temporal/       # Workflows & activities
│   │   ├── core/           # Audit, security, exceptions
│   │   └── db/             # Engine, session, migrations
│   ├── tests/
│   ├── worker.py           # Temporal worker entry
│   └── Dockerfile
├── web/                    # Next.js frontend
│   ├── src/
│   │   ├── app/            # Pages (App Router)
│   │   ├── components/     # PageHeader, Breadcrumbs, SchemaBuilder, PdfViewer...
│   │   └── lib/            # API client, utilities
│   └── package.json
├── scripts/                # Backup, seed, setup
├── docs/                   # Tài liệu dự án + screenshots
├── docker-compose.yml
├── Makefile
└── .env.example

Phát triển

Chạy test

# Backend (pytest trong container)
docker compose exec api python -m pytest tests/ -v

# Frontend unit (vitest)
cd web && npm run test:unit

# Frontend E2E (Playwright)
cd web && npx playwright test

Makefile shortcuts

make up          # docker compose up -d
make down        # docker compose down
make logs        # Follow logs
make ps          # Container status
make health      # Kiểm tra health tất cả services
make psql        # Vào psql shell
make sync        # Rsync code lên dev server
make pull-model  # ollama pull gemma4:e4b

Regenerate API types

cd web && npm run gen:api

Services & Ports

Service Port URL
Web (Next.js) 30080 http://localhost:30080
API (FastAPI) 30081 http://localhost:30081/docs
Health check 30081 http://localhost:30081/health
Temporal UI 30082 http://localhost:30082
PostgreSQL 30432 psql -h localhost -p 30432 -U molly
Meilisearch 30700 http://localhost:30700

API

Public endpoints (UI)

Method Path Mô tả
GET /api/v1/schemas Danh sách kiểu văn bản
POST /api/v1/schemas Tạo kiểu mới
POST /api/v1/schemas/{id}/versions Tạo version mới
POST /api/v1/schemas/infer Đề xuất schema từ file mẫu (AI)
POST /api/v1/documents Upload hồ sơ
GET /api/v1/documents Danh sách hồ sơ
GET /api/v1/documents/{id} Chi tiết hồ sơ
POST /api/v1/documents/{id}/approve Duyệt hồ sơ
POST /api/v1/documents/{id}/correct Đính chính
POST /api/v1/documents/{id}/cancel Hủy hồ sơ
GET /api/v1/search Tra cứu full-text (Meilisearch)
GET /api/v1/audit Nhật ký hệ thống

Integration API (API key auth)

Method Path Mô tả
POST /api/v1/integration/documents Submit file qua API
GET /api/v1/integration/documents/{id} Query status
GET /api/v1/integration/records Query hồ sơ đã duyệt (phân trang)
GET /api/v1/integration/records/{id} Chi tiết 1 hồ sơ + signed file URL
GET /api/v1/integration/files/{id}?token=... Download file qua signed URL

Tài liệu Swagger UI đầy đủ: https://molly.carp.vn/docs

Triển khai production

HTTPS qua Caddy reverse proxy

Dùng reverse proxy trên host để expose HTTPS + domain thay vì port trần:

# Caddyfile
molly.yourdomain.vn {
    # API + health + docs
    @api path /api/* /docs* /openapi.json /health
    handle @api {
        reverse_proxy sstc-llm:30081
    }
    # Còn lại → web
    handle {
        reverse_proxy sstc-llm:30080
    }
    encode gzip zstd
    request_body { max_size 2GB }
}

Lưu ý set NEXT_PUBLIC_API_BASE_URL=https://molly.yourdomain.vn trong .envrebuild web.

Backup & Restore

./scripts/backup.sh            # pg_dump app + temporal, tar file storage, dump meilisearch
./scripts/restore.sh <backup>  # Restore từ file backup

Tài liệu

Tài liệu Mô tả
Hướng dẫn sử dụng Hướng dẫn cho người dùng cuối (tiếng Việt, 10 ảnh minh họa)
Đề xuất triển khai Proposal chuyên nghiệp gửi khách hàng
Kiến trúc Tài liệu kiến trúc chi tiết
PRD Product Requirements Document
Pilot Handoff Checklist triển khai pilot
State Trạng thái hiện tại của dự án

Tech Stack

Backend: Python 3.12 · FastAPI · SQLAlchemy 2.0 async · Temporal 1.25 · Alembic · Pydantic v2 · openai SDK · PyMuPDF · Meilisearch client

Frontend: Next.js 16 · TypeScript 5.9 · React 19 · Ant Design v6 · TanStack Query v5 · react-pdf · dayjs

Infrastructure: Docker Compose · PostgreSQL 16 · Meilisearch v1.11 · Temporal v1.25 · Caddy (reverse proxy)

AI: Gemma 4 multimodal (e4b ~9.6GB dev / 26B MoE ~18GB prod) qua Ollama hoặc LM Studio

License

Private — Internal use only.