
Bài 9: Xây Dựng Backend API (FastAPI + Service Layer)
Chào mừng các bạn quay trở lại với series DApp AI + Blockchain!
Trong ba bài trước, chúng ta đã lần lượt xây dựng:
-
Smart Contract on-chain (Bài 6)
-
Mô hình AI (MediaPipe) & IPFS (Bài 7)
-
Scripts Off-chain bằng Python (Bài 8)
Mọi thứ đã hoạt động hoàn hảo, nhưng… tất cả đều đang chạy qua giao diện dòng lệnh (CLI). Đối với người dùng cuối, họ không thể mở Terminal lên để gõ lệnh đăng ký DID được. Do đó, trong Bài 9 này, chúng ta sẽ “đóng gói” toàn bộ logic phức tạp trên thành một REST API chuyên nghiệp bằng FastAPI, làm nền tảng vững chắc để giao diện Frontend (Bài 10) có thể giao tiếp dễ dàng.
Mục Tiêu Bài Học
Sau bài viết này, bạn sẽ nắm được:
-
Xây dựng Backend bằng FastAPI với Kiến trúc phân tầng (Layered Architecture).
-
Thiết kế 7 REST API endpoints để quản lý toàn bộ vòng đời của DID và nhận diện khuôn mặt.
-
Triển khai tính năng Face-based Verify – Điểm giao thoa cốt lõi giữa AI và Blockchain.
-
Áp dụng mô hình Singleton cho các Service để tối ưu hóa hiệu năng.
-
Sử dụng Swagger UI để kiểm thử API trực quan.
Kiến Trúc Backend: Layered Architecture
Để code gọn gàng, dễ bảo trì và mở rộng, chúng ta không nhét tất cả logic vào một file. Thay vào đó, dự án sử dụng kiến trúc phân tầng (Layered Architecture):
FastAPI (:8000)
├── Routers (API endpoints) ← Chỉ làm nhiệm vụ tiếp nhận HTTP requests
│ ├── face.py → /api/v1/face/detect
│ └── did.py → /api/v1/did/create, /register, /verify, /revoke
│
├── Services (Business logic) ← Chứa toàn bộ logic lõi, không biết HTTP là gì
│ ├── FaceTrackerService → Gọi MediaPipe Tasks API
│ ├── IPFSService → Upload/Fetch dữ liệu Pinata
│ └── CardanoService → Xử lý PyCardano, Blockfrost, CKV
│
└── Models (Schemas) ← Định nghĩa cấu trúc dữ liệu (Pydantic)
└── schemas.py
Bí kíp Tối ưu (Singleton Pattern): Khởi tạo ví (Wallet), tải Smart Contract, và kết nối mạng lưới Blockfrost là những tác vụ “nặng” và tốn thời gian. Thay vì khởi tạo lại mỗi lần có request, chúng ta dùng pattern Singleton cho các Service này: Khởi tạo 1 lần duy nhất khi chạy app, và tái sử dụng nó cho mọi request về sau.
🛠️ Thiết Kế REST API Endpoints
Dưới đây là 7 endpoints chính của DApp được thiết kế theo chuẩn RESTful:
|
Endpoint |
Method |
Input |
Output |
Mô tả chức năng |
|---|---|---|---|---|
|
|
|
|
Faces + CID |
Upload ảnh, AI nhận diện và đẩy lên IPFS |
|
|
|
|
TX hash + DID |
Khóa (Lock) 2 ADA vào Smart Contract |
|
|
|
— |
TX hash |
Đăng ký sử dụng DID (CKV Register) |
|
|
|
|
Similarity + TX |
So sánh khuôn mặt để Verify |
|
|
|
— |
TX hash |
Hủy (Burn) DID, lấy lại ADA |
|
|
|
— |
DID info |
Lấy thông tin chi tiết của 1 DID |
|
|
|
— |
All DIDs |
Liệt kê tất cả DID đang có |
Trọng Tâm: Xác Minh Bằng Khuôn Mặt (Face-based Verify)
Đây là tính năng “ăn tiền” nhất của hệ thống. Giao dịch Verify không chỉ là việc người dùng bấm một nút xác nhận, mà hệ thống bắt buộc họ phải chứng minh danh tính bằng khuôn mặt thực.
Luồng hoạt động (Flow):
-
Người dùng tải ảnh khuôn mặt mới lên API.
-
AI (MediaPipe) nhận diện và trích xuất vector 512 chiều.
-
Backend lấy CID từ Blockchain, tải file dữ liệu gốc từ IPFS về.
-
Tính toán khoảng cách toán học (Cosine Similarity) giữa 2 khuôn mặt.
-
Nếu độ tương đồng $\ge 70\%$, cho phép gửi giao dịch đổi trạng thái
verifiedtừ 0 sang 1 on-chain. Ngược lại, từ chối.
Hãy xem đoạn code của Router verify_did:
@router.post("/{did_id}/verify", response_model=FaceVerifyResponse)
async def verify_did(did_id: str, file: UploadFile = File(...)):
# ... (kiểm tra DID tồn tại)
# Bước 1 & 2: Nhận diện ảnh mới upload
image_bytes = await file.read()
tracker = get_face_tracker()
faces = tracker.detect_and_embed(image_bytes)
new_embedding = faces[0]["embedding"]
# Bước 3: Fetch embedding gốc từ IPFS bằng thông tin trên chain
ipfs = get_ipfs_service()
original_data = ipfs.get_json(did_info["ipfs_hash"])
original_embedding = original_data["faces"][0]["embedding"]
# Bước 4: Tính toán Cosine Similarity
vec_new = np.array(new_embedding, dtype=np.float32)
vec_orig = np.array(original_embedding, dtype=np.float32)
dot = np.dot(vec_new, vec_orig)
similarity = float(dot / (np.linalg.norm(vec_new) * np.linalg.norm(vec_orig) + 1e-8))
# Bước 5: Nếu Match (>= 70%) -> Gửi TX Verify lên Blockchain
threshold = 0.7
if similarity >= threshold:
result = svc.perform_action(did_id, "verify") # CKV Logic (Bài 8)
return FaceVerifyResponse(
did_id=did_id, match=True, similarity=similarity,
message="Khuôn mặt khớp! DID đã được xác minh on-chain.",
tx_hash=result["tx_hash"]
)
else:
# Nếu Mismatch (< 70%) -> Từ chối
return FaceVerifyResponse(
did_id=did_id, match=False, similarity=similarity,
message=f"Khuôn mặt không khớp (Độ tương đồng: {similarity:.2%})"
)
Tại đây, AI đóng vai trò là “Người gác cổng” (Gatekeeper) quyết định xem liệu giao dịch Blockchain có được phép diễn ra hay không!
Cardano Service: Đóng gói CKV Logic
Bên trong CardanoService, hàm perform_action() sẽ xử lý toàn bộ các giao dịch CKV. Những kiến thức và cạm bẫy từ Bài 8 đều được áp dụng hoàn chỉnh ở đây:
-
Luôn dùng
builder.add_input_address()để cấp UTxO trả phí mạng. -
Dùng
DIDDatum.from_cbor()để giải mã RawCBOR khi cần đọc dữ liệu cũ. -
Chắc chắn truyền kiểu
intcho trườngverified.
Việc chuyển mã thành Service giúp Router của chúng ta cực kỳ sạch sẽ và dễ đọc.
Chạy Thử & Swagger UI
Hãy khởi động Backend bằng lệnh:
python -m uvicorn app.main:app --reload --port 8000
Bạn sẽ thấy logs khởi tạo các Service (đọc Smart Contract, thiết lập ví,…).
Và đây là điều tuyệt vời nhất của FastAPI: Nó tự động tạo ra một tài liệu API tương tác cực kỳ chuyên nghiệp. Hãy mở trình duyệt và truy cập: http://localhost:8000/docs
Giao diện Swagger UI sẽ hiện ra. Tại đây, bạn có thể:
-
Test thử endpoint
/healthđể xem server đã sống chưa. -
Chọn endpoint
/api/v1/face/detect, bấm “Try it out”, upload một tấm ảnh và xem AI trả về mã CID. -
Trải nghiệm gọi API trực quan mà không cần đến các tool như Postman.
Tổng Kết Bài 9
Vậy là chúng ta đã hoàn thành Backend! Bạn đã:
-
Nắm được Kiến trúc phân tầng (Router $\rightarrow$ Service $\rightarrow$ Model).
-
Tối ưu hiệu năng bằng mô hình Singleton.
-
Hiểu sâu sắc cách kết hợp so sánh toán học (AI) làm điều kiện để kích hoạt hợp đồng thông minh (Blockchain).
-
Sử dụng Swagger UI để debug và tương tác API.
Hệ thống của chúng ta giờ đã là một cỗ máy hoàn chỉnh chạy ngầm. Ở bài viết cuối cùng – Bài 10, chúng ta sẽ “khoác áo mới” cho hệ thống này bằng cách xây dựng một giao diện Frontend React cực kỳ xịn xò, nơi người dùng cuối có thể click, upload ảnh và tận hưởng trải nghiệm Web3 thực thụ!
Hẹn gặp lại các bạn ở Bài 10 – The Grand Finale!
Hẹn gặp lại các bạn trong bài viết tiếp theo! Chúc các bạn code vui vẻ!
Chi tiết về source code toàn bộ bài học các bạn có thể tham khảo tại!!!
Pycardano integration with AI Implementation Example
