- Python 62.8%
- TypeScript 36.6%
- Makefile 0.3%
- Dockerfile 0.2%
- Mako 0.1%
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>
|
||
|---|---|---|
| api | ||
| docs | ||
| scripts | ||
| web | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| Makefile | ||
| README.md | ||
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
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 PDF + form |
![]() Tra cứu full-text với highlight |
![]() Quản lý kiểu văn bản |
![]() 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
- Dev: Ollama +
- 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 rebuilddocker 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
- Upload — PDF hoặc ảnh (PNG/JPG/TIFF), tự gộp nhiều ảnh thành 1 PDF
- Phân loại — AI đọc tiêu đề + fuzzy match (
pg_trgm) với kiểu đã có - Trích xuất — Gemma 4 multimodal extract theo schema (structured JSON)
- Review — Side-by-side PDF + form, chỉnh sửa trước khi duyệt
- 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 .env và rebuild 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.




