Kiến trúc Module, REST API & Hướng dẫn Mở rộng
Cấu trúc tầng dịch vụ FastAPI, cơ chế quản lý trạng thái lượt chạy đa người dùng và hướng dẫn mở rộng thêm mô hình hoặc cấu trúc Parquet mới.
Kiến trúc Module Dịch vụ (forecast_demo / Core Service Layer)
Để phục vụ nhiều người dùng truy cập đồng thời mà không phải tính toán lại mô hình trên từng request, tầng dịch vụ (forecast_demo/src/forecast_demo/) được tổ chức thành 6 phân hệ:
Phân hệ (package) | Đường dẫn | Chức năng chính |
|---|---|---|
core | src/forecast_demo/core/ | Định nghĩa đường dẫn dữ liệu (paths.py), cấu hình tham số hệ thống, độ nhạy khuyến mãi và các quy tắc dựng khung dòng tương lai (settings.py). |
store | src/forecast_demo/store/ | Tầng lưu trữ trạng thái bằng SQLite: quản lý danh mục CTKM đã nạp, lịch sử lượt chạy, các hệ số $K$ người dùng đã chỉnh sửa kèm lý do, và trạng thái khóa sổ (DRAFT vs LOCKED). |
ingest | src/forecast_demo/ingest/ | Đọc tệp Excel CTKM của Trade, kiểm tra hợp lệ từng dòng theo danh mục đóng (mã SKU, tên chuỗi, cơ chế KM, cửa sổ thời gian NTD) và ghi vào kho. |
engine | src/forecast_demo/engine/ | Chứa skeleton.py (dựng khung dòng cho tháng tương lai $M+1..M+3$), catalog.py (định tuyến mô hình theo cấp gộp model_for_grain), grain.py (gộp nhanh 16 cấp hạt từ Parquet cache) và forecast.py (hợp nhất $\text{Base} \times (1 + \sum K)$). |
api | src/forecast_demo/api/ | Cung cấp các REST API endpoints qua FastAPI cho giao diện web hoặc hệ thống bên ngoài tích hợp. |
cli | src/forecast_demo/cli/ | Cung cấp công cụ dòng lệnh forecast-demo để vận hành tự động qua cronjob/pipeline. |
Cơ chế Bộ nhớ đệm Parquet (Decomposed Parquet Cache) Cho Đa Người Dùng
Một thách thức lớn của hệ thống dự báo đa người dùng là phép phân rã Shapley và suy luận Foundation Model tốn nhiều thời gian tính toán nếu chạy trực tiếp trên mỗi thao tác lọc của người dùng. Module giải quyết triệt để bằng Bộ nhớ đệm Hạt Dòng Đã Phân Rã:
- Ở bước
warm/train, hệ thống tính sẵn dự báo và đóng góp của từng khe hệ số cho mọi mô hình và lưu xuống:data/cache/h{horizon}/decomposed_{model_slug}.parquet - Mỗi dòng trong tệp Parquet này mang đầy đủ các khóa định danh chưa mã hóa (
store_code,product_code,warehouse_key,subinv_key,chain_v1,brand_name,supplier_name,area2,area3,channel_l1,channel_l2) cùng giá trị dự báo và 6 thành phần phân rã. - Khi nhiều người dùng cùng lúc chuyển đổi qua lại giữa 16 cấp gộp hoặc 8 mô hình, hoặc sửa một hệ số $K$ trên màn hình, tầng
engine/grain.pychỉ thực hiện một phépgroup_by().agg(pl.sum())của Polars trên tệp Parquet trong bộ nhớ — thời gian phản hồi chỉ mất vài chục mili-giây.
Đặc tả REST API Endpoints (FastAPI) & Giao diện Dòng lệnh (CLI)
Danh mục REST API Endpoints (forecast_demo/src/forecast_demo/api/app.py)
Máy chủ dịch vụ khởi chạy mặc định tại http://127.0.0.1:8000 (qua lệnh make serve hoặc uv run forecast-demo serve). Toàn bộ tính toán suy luận nặng đã được chuẩn bị sẵn trong Parquet cache (make warm), do đó các API đều phản hồi đồng bộ với độ trễ thấp:
| Phương thức & Đường dẫn | Tham số (Query / Body) | Chức năng & Cấu trúc Phản hồi |
|---|---|---|
GET /api/meta | (Không) | Trả về cấu hình khởi tạo giao diện: version, kỳ gốc origin_ym, danh sách tầm dự báo horizons (M+1..M+3), mô hình mặc định model_default, độ nhạy khuyến mãi sensitivity, danh sách cơ chế KM mechanics và bộ quy tắc vận hành rules. |
GET /api/forecast | horizon: int = 1sensitivity: float | nullmodel: str | null | Trả về kết quả dự báo tổng hợp tại tầm horizon: mức nền base_carton (base_source), dự báo mô hình raw_carton, dự báo chốt final_carton, thực tế actual_carton (nếu có), mảng 6 hệ số coefficients, cờ kiểm chứng cộng tính contract_ok (residual_pct) và hiệu ứng khuyến mãi promo. |
GET /api/grains | horizon: int = 1model: str | null | Liệt kê danh sách 16 cấp gộp khả dụng từ mịn tới thô kèm số nhóm thực tế (so_nhom) và mô hình định tuyến tối ưu mặc định (model_for_grain) cho từng cấp gộp. |
GET /api/breakdown | horizon: int = 1grain: str = "sku"limit: int = 200model: str | null | Chẻ nhỏ số dự báo theo cấp gộp grain (pair, store, sku_subinv, sku_warehouse, sku_chain, sku, brand, subinv, chain, supplier, warehouse, channel_l2, area3, area2, channel_l1, channel), kèm phép kiểm bảo toàn tổng kiem_qd08_thung. |
GET /api/model-report | horizon: int = 1grain: str = "sku"group: str | nullmodel: str | null | Trả về báo cáo giải thích mô hình chuyên sâu: độ quan trọng đặc trưng (Feature Importance theo Gain), phân nhóm nhân tố và chiều tác động cụ thể lên nhóm group đang chọn. |
GET /api/catalog | (Không) | Trả về danh mục các mô hình đang được phục vụ (slug, label, note, cờ mac_dinh). |
POST /api/runs | Body RunIn: {horizon, coefficients[], note} | Lưu một kịch bản điều chỉnh hệ số $K$ của người dùng vào SQLite ở trạng thái bản nháp (DRAFT), trả về {run_id, trang_thai}. |
POST /api/runs/{run_id}/lock | Body LockIn: {who: str} | Khóa sổ bản dự báo (LOCKED) cho kỳ S&OP kèm tên người phê duyệt; trả mã lỗi 409 nếu kỳ dự báo đã có bản khóa trước đó. |
GET /api/runs | (Không) | Liệt kê lịch sử các lượt lưu và khóa sổ dự báo của các người dùng. |
POST /api/imports | Multipart file: UploadFile | Tải tệp Excel CTKM lên bàn chờ (staging), kiểm tra hợp lệ từng dòng và trả về danh sách lỗi xem trước mà chưa ghi đè vào kho chính. |
POST /api/imports/{batch_id}/commit | Path batch_id: int | Xác nhận ghi lô CTKM hợp lệ từ bàn chờ vào bảng promo_line chính thức. |
POST /api/imports/{batch_id}/cancel | Path batch_id: int | Hủy bỏ lô CTKM đang ở bàn chờ. |
GET /api/imports & GET /api/promo | limit: int = 200 | Tra cứu lịch sử các lô nạp CTKM và danh sách các dòng khuyến mãi đang có hiệu lực (is_active = 1). |
GET /api/models & POST /api/models/backup | (Không) | Đối chiếu mã băm SHA-256 của các tệp .joblib trên đĩa với bản lưu trong SQLite và sao lưu mô hình. |
Giao diện Dòng lệnh (forecast-demo CLI)
Mọi chức năng của tầng dịch vụ đều có thể gọi trực tiếp qua CLI (forecast_demo/src/forecast_demo/cli/__init__.py) để tích hợp vào pipeline tự động mà không cần mở trình duyệt:
| Lệnh CLI | Ý nghĩa thực thi |
|---|---|
uv run forecast-demo train-models [--rebuild] | Đọc tệp Parquet trong data/panel/ và huấn luyện lại các tệp mô hình .joblib cho đủ 3 tầm M+1..M+3 thẳng vào data/models/. |
uv run forecast-demo warm [--rebuild] | Dựng sẵn khung đặc trưng tương lai và tính trước bộ nhớ đệm phân rã 6 khe (data/cache/h*/decomposed_{model}.parquet) cho mọi mô hình. |
uv run forecast-demo forecast --horizon 1 [--model <slug>] | In bảng dự báo tổng hợp kèm 6 hệ số $K$ và kết quả kiểm tra cộng tính ra terminal. |
uv run forecast-demo breakdown --horizon 1 --grain <slug> [--limit 15] | Chẻ dự báo theo cấp gộp bất kỳ (đặt --grain '?' để in danh sách 16 cấp gộp) và kiểm tra độ lệch tổng. |
uv run forecast-demo ingest <path.xlsx> [--write] | Kiểm tra hợp lệ tệp Excel CTKM (thêm --write để ghi thẳng vào SQLite). |
uv run forecast-demo backup / uv run forecast-demo check | Sao lưu tệp .joblib kèm SHA-256 vào SQLite và kiểm tra tính toàn vẹn. |
uv run forecast-demo serve --host 127.0.0.1 --port 8000 | Khởi chạy máy chủ web FastAPI. |
Hướng dẫn Mở rộng Dành cho Developers
Thêm một Mô hình Dự báo Mới vào Hệ thống
- Triển khai thuật toán tại
model_lab:- Nếu là mô hình chuỗi thời gian / Empirical-Bayes cấp SKU: thêm hàm dự báo vào
model_lab/src/model_lab/models/frontier.pyhoặcchronos2_exp.py. - Đăng ký khóa định danh (
slug) và tên hiển thị đầy đủ vàoFULL_NAMEStrongmodel_lab/src/model_lab/models/catalog.py.
- Nếu là mô hình chuỗi thời gian / Empirical-Bayes cấp SKU: thêm hàm dự báo vào
- Định tuyến Cấp gộp (tùy chọn):
- Cập nhật ánh xạ
model_for_graintrongforecast_demo/src/forecast_demo/engine/catalog.pynếu mô hình mới đạt WMAPE tốt nhất ở một cấp gộp cụ thể.
- Cập nhật ánh xạ
- Kiểm định:
- Chạy kiểm thử cuốn chiếu và holdout trong
model_lab, sau đó chạyuv run pytestđể đảm bảo mô hình tuân thủ hợp đồng đầu ra.
- Chạy kiểm thử cuốn chiếu và holdout trong
Thêm Cột Đặc trưng Mới vào Hợp đồng Parquet DWH
Khi DWH bổ sung bảng hoặc cột mới cần đưa vào tệp Parquet chuẩn:
- Cập nhật câu truy vấn
forecast_pipeline/sql/full_dwh.sql. - Khai báo tên cột, nhóm (
group), cấp hạt (grain), quy tắc cộng (aggregation), kiểu dữ liệu Polars (dtype) và mô tả vào đúng vị trí tương ứng trongforecast_pipeline/src/forecast_pipeline/export/columns.py(build_full_dwh.pysẽ tự động kiểm tra đối xứng thứ tự cột và dừng ngay nếu lệch). - Chạy lại
make parquet-ml-full-downloadvàmake parquet-ml-processing.
Lộ trình Tách Cấu hình Schema Parquet Động (Dynamic Parquet Adapter — Phiên bản tiếp theo)
- Ở Version 1 (hiện tại): Schema Parquet đầu vào được cố định theo DWH Đại Thuận (
build_full_dwh_columns.py). - Ở Version 2 (lộ trình mở rộng): Tầng đọc Parquet sẽ bổ sung một tệp cấu hình ánh xạ cột (
schema_mapping.yaml) cho phép gắn bất kỳ tệp Parquet của doanh nghiệp/kho dữ liệu khác vào bằng cách khai báo cột nào đóng vai trò làentity_id,item_id,date_key,target_qty, và danh sách các cộtexogenous_features.