MLOps 4 — ML Pipelines & CI/CD

13 thg 7, 2026 6 lượt xem
#ai
#mlops
#orchestration
#pipeline
#ci-cd

MLOps 4 — ML Pipelines & CI/CD

bài experiment tracking ta đã ghim lại được từng lần chạy, và ở bài feature store ta có nguồn feature nhất quán train–serve. Nhưng nếu quy trình train vẫn là "mở notebook, chạy từng cell, xuất file model, kéo lên server" thì mọi thứ vẫn phụ thuộc vào một con người nhớ đúng thứ tự và không bấm nhầm. Bài này nói về mắt xích biến vòng đời mô hình thành tự động hoá lặp lại được: ML pipelineCI/CD cho ML.

ML pipeline là gì

ML pipeline là một chuỗi các bước được định nghĩa sẵn, chạy tự động và theo đúng thứ tự, để đi từ dữ liệu thô ra một mô hình đã sẵn sàng phục vụ. Thay vì "notebook thủ công", ta mô tả toàn bộ quy trình thành code, mỗi bước là một task có đầu vào/đầu ra rõ ràng, và một orchestrator (bộ điều phối) chịu trách nhiệm chạy chúng.

Một pipeline train điển hình gồm các bước:

  1. Ingest data — lấy dữ liệu (query warehouse, đọc feature store, tải file). Ghim lại khoảng thời gian dữ liệu.
  2. Validate data — kiểm tra schema, kiểu dữ liệu, tỷ lệ null, phân phối. Dữ liệu bẩn thì dừng ngay, đừng để "rác vào, mô hình rác ra".
  3. Feature engineering — sinh feature (tốt nhất là đọc từ feature store để tránh lệch train–serve).
  4. Train — huấn luyện mô hình, log params/metrics/artifacts (nối vào experiment tracking).
  5. Evaluate — đo chất lượng trên tập holdout: AUC, KS, precision/recall...
  6. Gate (cổng kiểm định) — quyết định có được đi tiếp không: model mới phải vượt ngưỡng tối thiểu VÀ tốt hơn (hoặc không kém hơn) mô hình đang chạy. Không đạt thì pipeline dừng, model bị vứt.
  7. Register — nếu qua cổng, đăng ký model vào model registry với version và metadata.
  8. Deploy — triển khai model (thường là bước riêng, có phê duyệt của người).

Vì sao cần pipeline thay vì notebook

  • Tái lập (reproducibility). Pipeline là code có version. Chạy lại đúng revision → ra đúng kết quả. Notebook thì thứ tự cell và state ẩn khiến "chạy lại" không đảm bảo giống lần trước.
  • Tự động retrain. Cần train lại hàng tuần với dữ liệu mới? Đặt lịch cho pipeline, không cần ai ngồi bấm.
  • Giảm lỗi tay. Không còn "quên chạy bước chuẩn hoá", "xuất nhầm file model cũ", "deploy nhầm model chưa đánh giá". Mỗi bước có đầu vào/đầu ra rõ, có kiểm định tự động chặn lỗi.
  • Quan sát được (observability). Orchestrator cho biết bước nào chạy, mất bao lâu, thất bại ở đâu, retry ra sao — thay vì một notebook chạy 40 phút rồi treo im lặng.
  • Cộng tác & bàn giao. Người mới đọc DAG hiểu quy trình; không phụ thuộc vào "chỉ anh A biết chạy".

Orchestration: chọn công cụ nào

Orchestrator là bộ điều phối định nghĩa các task, quan hệ phụ thuộc (DAG — đồ thị có hướng không chu trình), lịch chạy, retry và giám sát. Vài công cụ phổ biến:

Công cụĐiểm mạnhPhù hợp khi
Apache AirflowChuẩn de-facto cho data orchestration, cộng đồng lớn, nhiều operator sẵn, lịch/backfill mạnhĐã có Airflow chạy ETL; muốn dùng lại hạ tầng cho ML
Kubeflow PipelinesChạy native trên Kubernetes, mỗi bước là 1 container, hợp với train nặng cần scale GPUTeam đã dùng K8s, muốn pipeline container hoá triệt để
DagsterCoi trọng data asset & kiểu dữ liệu I/O, test dễ, dev-experience tốt, phân biệt rõ định nghĩa và thực thiCần pipeline dễ test, quản lý theo asset/lineage
MetaflowAPI Python thuần, ergonomics cho data scientist, versioning & resume built-in (gốc từ Netflix)Muốn DS viết pipeline mà ít lo hạ tầng
TFX (TensorFlow Extended)Bộ component ML chuẩn của Google (ExampleGen, StatisticsGen, SchemaGen, Trainer, Evaluator, Pusher), tích hợp data/model validation sẵnStack TensorFlow, muốn khuôn ML pipeline theo best practice

Ở NCB, Airflow thường đã hiện diện để điều phối ETL vào warehouse, nên tái sử dụng nó cho ML pipeline là lựa chọn ít ma sát nhất. Không cần "đúng công cụ nhất" — cần công cụ team vận hành được.

Continuous Training (CT): tự động train lại

Mô hình không đứng yên: dữ liệu thay đổi theo thời gian (concept drift), thủ đoạn gian lận biến hoá, hành vi khách dịch chuyển. Continuous Training là việc train lại mô hình một cách có hệ thống, được kích hoạt tự động bởi một trong ba loại trigger:

  • Theo lịch (scheduled). Đơn giản nhất: retrain định kỳ — hằng ngày/tuần/tháng. Ví dụ mô hình gian lận train lại mỗi tối Chủ nhật.
  • Theo drift. Hệ thống giám sát phát hiện phân phối feature hoặc chất lượng dự đoán trôi vượt ngưỡng → phát tín hiệu retrain. Tiết kiệm hơn scheduled vì chỉ train khi thật sự cần.
  • Theo dữ liệu mới. Có đủ lượng nhãn/dữ liệu mới (ví dụ đủ số giao dịch được cán bộ xác nhận nhãn gian lận) → kích hoạt train lại để mô hình học điều mới.

CT chính là "vòng lặp" khép kín trong sơ đồ ở trên: deploy → giám sát → phát hiện cần train lại → chạy lại pipeline → (qua gate) → deploy phiên bản mới. Điểm mấu chốt: CT không có nghĩa là mọi model train ra đều tự động lên prod. Nó tự động tạo ra ứng viên; còn model gate mới là thứ quyết định ứng viên có xứng đáng thay thế model đang chạy.

CI/CD cho ML khác gì CI/CD phần mềm

CI/CD phần mềm truyền thống: commit code → CI chạy build + unit/integration test → nếu xanh thì CD deploy artefact (binary/container). ML kế thừa toàn bộ điều đó, nhưng thêm hai loại kiểm định đặc thù vì sản phẩm không chỉ là code mà là code + dữ liệu + model.

1. Validate data (kiểm định dữ liệu)

Trước khi train, phải kiểm tra chính dữ liệu — thứ mà CI phần mềm không bao giờ quan tâm:

  • Schema. Đúng cột, đúng kiểu, không thiếu cột bắt buộc. Ví dụ amount phải là số, kind phải thuộc tập giá trị hợp lệ.
  • Phân phối (distribution). So phân phối lô dữ liệu mới với baseline: tỷ lệ null nhảy vọt? amount trung bình gấp đôi tháng trước? Tỷ lệ nhãn gian lận rơi về 0 (dấu hiệu đứt nguồn nhãn)? Các bất thường này phải chặn pipeline, không thì mô hình học phải rác.

2. Validate model (kiểm định mô hình) — "model gate"

Đây là điểm khác biệt cốt lõi. Trong phần mềm, test pass/fail là nhị phân và tất định. Với ML, "model tốt" là ngưỡng thống kê:

  • Vượt ngưỡng tuyệt đối. Ví dụ AUC ≥ 0.80, precision@1% ≥ 0.6. Không đạt → không deploy.
  • Tốt hơn (hoặc không kém hơn) baseline / model đang chạy. So model ứng viên với champion hiện tại trên cùng tập đánh giá. Chỉ promote nếu tốt hơn có ý nghĩa, hoặc ít nhất không tệ đi. Đây chính là model gate — cái cổng ngăn một model "chạy được nhưng kém hơn" âm thầm thay thế model tốt đang phục vụ.

Ranh giới quan trọng: CI/CD deploy pipeline, không deploy model. Khi merge code, CI kiểm tra code pipeline đúng; còn model cụ thể lên prod hay không do CT + model gate quyết định ở runtime với dữ liệu thực. Đừng nhầm "test code xanh" với "model đủ tốt".

Các loại test trong ML pipeline

Loại testKiểm tra gìVí dụ
Unit test (feature logic)Hàm biến đổi feature cho ra đúng giá trịdays_since_last_txn(x) với input mẫu trả về đúng số ngày; xử lý null đúng
Data validationSchema & phân phối dữ liệu đầu vàoKhông cột lạ, null < 5%, amount không âm
Model qualityChất lượng vượt ngưỡng & so baselineAUC ≥ 0.80 và ≥ AUC champion
Integration testCả pipeline chạy end-to-end trên dữ liệu nhỏIngest→train→register không lỗi, artefact xuất đúng

Thêm nữa nên có: kiểm tra train–serve skew (feature lúc serve khớp lúc train), và test behavioral (model không phân biệt đối xử theo thuộc tính nhạy cảm — xem governance).

Pipeline as code & versioning

Nguyên tắc: toàn bộ pipeline phải nằm trong git — định nghĩa DAG, code từng bước, config, ngưỡng gate, môi trường (dependency được pin). Nhờ đó pipeline có version như phần mềm: review qua pull request, rollback về revision cũ, và mọi thay đổi quy trình đều để lại dấu vết kiểm toán. Một model chạy trên prod cần truy được: pipeline revision nào, dữ liệu khoảng nào, feature version nào đã tạo ra nó.

Môi trường & promote artefact

Giống phần mềm, ML có nhiều môi trường và ta thăng cấp cùng một artefact qua chúng thay vì build lại mỗi nơi (build lại dễ sinh khác biệt):

  • dev — data scientist thử nghiệm, dữ liệu mẫu, có thể bẩn.
  • staging — chạy full pipeline trên dữ liệu giống prod (thường ẩn danh/masked), là nơi model gate quyết định chính.
  • prod — phục vụ giao dịch thật, giám sát chặt, mọi deploy có phê duyệt.

Promote artefact: model đã đăng ký ở registry được gắn stage (Staging → Production) và chính binary/container đó được đẩy lên, chứ không train lại ở prod. Đóng gói bằng container (Docker) để môi trường train và serve nhất quán từ dev tới prod — tránh cảnh "trên máy tôi chạy được". Điều này cũng khớp với thực hành ở triển khai API/modelđưa mô hình lên production.

Ví dụ minh hoạ

Dưới đây là minh hoạ (không phải code chạy sẵn) một DAG Airflow đơn giản cho pipeline retrain:

# MINH HOẠ — Airflow DAG retrain mô hình gian lận (đơn giản hoá)
from airflow import DAG
from airflow.operators.python import PythonOperator, BranchPythonOperator
import pendulum

def ingest(**ctx): ...          # query giao dịch tuần qua + nhãn đã xác nhận
def validate_data(**ctx): ...   # schema + phân phối; raise nếu lệch -> pipeline fail
def build_features(**ctx): ...  # đọc feature store, tránh train-serve skew
def train(**ctx): ...           # train + log MLflow, trả AUC
def evaluate(**ctx): ...        # đo trên holdout, so champion hiện tại

def model_gate(**ctx):          # CỔNG KIỂM ĐỊNH
    m = ctx["ti"].xcom_pull(task_ids="evaluate")
    if m["auc"] >= 0.80 and m["auc"] >= m["champion_auc"]:
        return "register_model"
    return "reject_model"       # giữ nguyên model cũ

with DAG(
    dag_id="fraud_retrain_weekly",
    schedule="0 2 * * 1",       # 02:00 sáng thứ Hai hằng tuần (Continuous Training theo lịch)
    start_date=pendulum.datetime(2026, 1, 1, tz="Asia/Ho_Chi_Minh"),
    catchup=False,
) as dag:
    t1 = PythonOperator(task_id="ingest", python_callable=ingest)
    t2 = PythonOperator(task_id="validate_data", python_callable=validate_data)
    t3 = PythonOperator(task_id="build_features", python_callable=build_features)
    t4 = PythonOperator(task_id="train", python_callable=train)
    t5 = PythonOperator(task_id="evaluate", python_callable=evaluate)
    gate = BranchPythonOperator(task_id="model_gate", python_callable=model_gate)
    reg = PythonOperator(task_id="register_model", python_callable=lambda **c: ...)
    rej = PythonOperator(task_id="reject_model", python_callable=lambda **c: ...)

    t1 >> t2 >> t3 >> t4 >> t5 >> gate >> [reg, rej]

Và ngưỡng gate tách ra thành config (versioned trong git) — minh hoạ, không phải file chạy được:

# MINH HOẠ — config/gate.yaml
model_gate:
  min_auc: 0.80
  min_precision_at_1pct: 0.60
  must_beat_champion: true        # phải >= AUC model đang chạy
  max_worse_delta: 0.0
data_validation:
  max_null_ratio: 0.05
  expected_columns: [account_id, amount, kind, hour, days_since_last_txn]
  label_positive_rate_min: 0.001  # cảnh báo nếu tỷ lệ nhãn gian lận rơi về 0

Việc lấy dữ liệu cho bước ingest có thể là một truy vấn tổng hợp trên warehouse. Ví dụ đếm giao dịch và tổng tiền theo tài khoản trong sandbox PostgreSQL:

-- ▶ Chạy được
SELECT account_id, COUNT(*) AS n_txn, SUM(amount) AS total_amount
FROM transactions
WHERE created_at >= NOW() - INTERVAL '7 days'
GROUP BY account_id
ORDER BY n_txn DESC;

Use case thực tế

Bối cảnh. Đội chống gian lận NCB có mô hình phát hiện giao dịch thẻ bất thường. Thủ đoạn gian lận thay đổi liên tục, mô hình cũ mất nhạy sau vài tuần. Mục tiêu: retrain hàng tuần, tự động, nhưng chỉ lên prod khi thật sự tốt hơn.

Thiết kế pipeline (fraud_retrain_weekly, chạy 02:00 sáng thứ Hai trên Airflow):

  1. Ingest — lấy ~4 triệu giao dịch 12 tuần gần nhất + ~9.000 nhãn gian lận đã được cán bộ xác nhận trong tuần qua.
  2. Validate data — kiểm schema và phân phối. Một lần thực tế: tỷ lệ null của trường merchant_category nhảy từ 1% lên 34% do đứt nguồn dữ liệu upstream → pipeline fail ngay ở bước 2, gửi cảnh báo, KHÔNG train trên dữ liệu hỏng. Nhờ đó tránh được một model rác âm thầm ra đời.
  3. Feature + train + evaluate — đọc feature từ feature store, train, đo trên holdout tuần liền trước. Champion hiện tại: AUC 0.913.
  4. Model gate — ngưỡng min_auc = 0.90must_beat_champion. Tuần này ứng viên đạt AUC 0.921 > 0.913 → qua cổng, đăng ký fraud_model v37 vào registry ở stage Staging.
  5. Promote — trưởng nhóm review report tự động (AUC, [email protected]%, phân tích theo phân khúc) rồi duyệt promote sang Production; chính container của v37 được deploy, không train lại.

Kết quả sau khi có pipeline. Trước đây một DS mất ~1 ngày/tuần để retrain thủ công, và đã từng có lần deploy nhầm model AUC 0.86 vì bấm nhầm file. Sau khi đưa lên pipeline + model gate: thời gian người bỏ ra còn ~15 phút review/tuần, và không còn sự cố model kém lọt lên prod vì cổng chặn tự động. Trong quý gần nhất, gate đã từ chối 3/13 ứng viên (kém champion) — 3 lần đó nếu làm tay rất dễ bị deploy nhầm.

Ghi nhớ

  • ML pipeline = chuỗi bước tự động ingest→validate→feature→train→evaluate→gate→register→deploy, thay cho notebook thủ công; đem lại tái lập, tự động hoá, giảm lỗi tay và quan sát được.
  • Orchestrator điều phối DAG: Airflow (chuẩn data), Kubeflow (K8s/container), Dagster (asset & test tốt), Metaflow (DS-friendly), TFX (khuôn ML của Google). Chọn cái team vận hành được, thường là Airflow đã có sẵn.
  • Continuous Training kích hoạt retrain theo lịch / drift / dữ liệu mới; nó tạo ứng viên, không tự động đẩy lên prod.
  • CI/CD cho ML = CI/CD phần mềm + validate data (schema, phân phối) + validate model (vượt ngưỡng & tốt hơn baseline = model gate).
  • Bốn nhóm test: unit cho feature logic, data validation, model quality, integration end-to-end; thêm kiểm train–serve skew.
  • Pipeline as code, versioned trong git; promote cùng một artefact qua dev→staging→prod, đóng gói container để nhất quán môi trường — không train lại ở prod.
  • Nguyên tắc vàng: CI/CD deploy pipeline; model gate mới quyết định model nào được lên prod.

Bài viết liên quan

Phân biệt AI/ML/DL, các kiểu học máy, quy trình ML end-to-end và thuật ngữ nền tảng.

13 thg 7, 2026 15

Chất lượng dữ liệu, xử lý thiếu/ngoại lai, mã hoá, chuẩn hoá, tạo đặc trưng và tránh data leakage.

13 thg 7, 2026 13

Mô hình ngôn ngữ lớn hoạt động ra sao, token, context window, tham số sinh, và kỹ thuật viết prompt.

13 thg 7, 2026 13

Retrieval-Augmented Generation, vector database, tool calling, agent và MCP để xây ứng dụng LLM thực tế.

13 thg 7, 2026 11