Rollout AI theo uplift, đừng rải đều

Rollout AI theo uplift, đừng rải đều

A/B test dương chưa đủ để bật AI cho tất cả. Playbook này giúp team chọn ai nên nhận feature, khi nào dừng, và đo rollout như người vận hành.

Có một khoảnh khắc rất dễ làm tech lead mềm lòng: dashboard A/B test xanh lè, metric chính nhảy lên, Slack bắt đầu có emoji pháo giấy. Feature LLM summary tăng completion thêm 8 điểm phần trăm? Ngon. Bật cho toàn bộ user thôi.

Ba tháng sau, hóa đơn inference phình ra, support hỏi vì sao vài khách lớn than bị phiền, còn core metric thì nhích như người tập metronome lần đầu: có nhịp, nhưng chưa thành bài.

Vấn đề không nằm ở A/B test sai. Vấn đề là team đã hỏi sai câu sau khi test thắng.

Câu cần hỏi không phải: feature AI này có tốt trung bình không?
Câu đáng tiền hơn là: ai thật sự hưởng lợi đủ nhiều để xứng đáng nhận feature này?

Đây là lúc uplift modeling đáng được kéo vào phòng họp rollout, không phải như món ML trang trí, mà như một quyết định vận hành.

Sơ đồ minh họa cho bài Rollout AI theo uplift, đừng rải đều

Sơ đồ tóm tắt ý chính của bài viết.

Mục tiêu: rollout theo người hưởng lợi, không theo tiếng vỗ tay

Trong nhiều team, đặc biệt team sản phẩm AI ở Việt Nam, rollout thường đi theo ba nấc:

  1. Offline eval ổn.
  2. A/B test có lift.
  3. Bật dần 10% → 50% → 100%.

Cách này không sai, nhưng thiếu một lớp phân đoạn. Average treatment effect là hiệu ứng trung bình của feature trên toàn bộ nhóm thử nghiệm. Nó hữu ích để quyết định có nên làm feature hay không. Nhưng khi đã quyết định làm, con số trung bình bắt đầu che mất chi tiết quan trọng.

Ví dụ cụ thể: feature recap bằng LLM có thể giúp user ít dùng sản phẩm vì họ hay mất ngữ cảnh. Nhưng với power user, recap lại thành tiếng đàn phụ chen sai nhịp: họ đã có workflow riêng, thêm summary chỉ làm màn hình rối hơn.

Uplift modeling là cách ước lượng ai sẽ cải thiện nhờ feature. Thuật ngữ kỹ thuật là CATE — conditional average treatment effect, tức hiệu ứng trung bình có điều kiện theo đặc điểm của từng user hoặc từng session. Nói thẳng ra thì: thay vì hỏi feature có tốt không, bạn hỏi feature tốt với ai.

Sau bài này, mình muốn bạn đổi một thói quen: đừng xem rollout 100% là đích mặc định sau A/B test thắng; hãy xem targeted rollout là phương án gốc, còn rollout toàn bộ phải được chứng minh thêm.

Checklist trước khi đụng vào model uplift

Trước khi mở notebook, team nên trả lời 6 câu này. Không trả lời được thì uplift model dễ biến thành một cây đàn chỉnh sai dây: nhìn có vẻ chuyên nghiệp, nhưng âm ra lệch.

Điểm nhiều team hiểu sai: uplift modeling không thay thế product judgment. Nó chỉ giúp bạn phân biệt người nên nhận feature, người nên được bỏ qua, và người cần guardrail riêng.

Làm thử trong một buổi: pipeline tối giản

Nếu bạn có log A/B test đủ sạch, một buổi chiều là đủ để dựng bản đầu tiên. Chưa cần production hóa. Mục tiêu là xem dữ liệu có tín hiệu phân đoạn hay không.

Bước 1: Chuẩn hóa bảng experiment

Bạn cần một bảng ở mức user hoặc session:

user_id | treatment | outcome | usage_7d | plan | task_type | avg_latency | region
u_001   | 1         | 1       | 3        | pro  | summary   | 1.8         | vn
u_002   | 0         | 0       | 22       | team | summary   | 1.1         | vn

Trong đó:

Bước 2: Train hai model đơn giản

Cách dễ hiểu nhất là T-learner: train một model dự đoán outcome cho nhóm treatment, một model cho nhóm control. Sau đó lấy chênh lệch dự đoán làm uplift score.

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split

features = ["usage_7d", "avg_latency"]  # thêm one-hot cho plan, task_type nếu cần
X = df[features]
y = df["outcome"]
t = df["treatment"]

X_train, X_test, y_train, y_test, t_train, t_test = train_test_split(
    X, y, t, test_size=0.3, random_state=42, stratify=t
)

model_t = RandomForestClassifier(random_state=42)
model_c = RandomForestClassifier(random_state=42)

model_t.fit(X_train[t_train == 1], y_train[t_train == 1])
model_c.fit(X_train[t_train == 0], y_train[t_train == 0])

p_t = model_t.predict_proba(X_test)[:, 1]
p_c = model_c.predict_proba(X_test)[:, 1]
uplift_score = p_t - p_c

Đây chưa phải setup hoàn hảo. Nhưng nó đủ để trả lời câu hỏi vận hành đầu tiên: có nhóm nào được dự đoán hưởng lợi rõ hơn nhóm khác không?

Bước 3: Chia band để ra quyết định

Đừng bật feature theo từng user riêng lẻ ngay. Hãy chia thành band để dễ kiểm soát:

| Band | Điều kiện minh họa | Quyết định |
|---|---:|---|
| High uplift | score cao hơn ngưỡng nội bộ | Bật mặc định |
| Neutral | score gần 0 | Giữ off hoặc cho opt-in |
| Negative | score âm | Không bật, điều tra thêm |

Nếu là mình, mình sẽ bắt đầu bằng top band nhỏ nhất đủ để quan sát, thay vì phấn khích bật cho toàn bộ nhóm score dương. Rollout AI giống chỉ huy dàn nhạc: không phải nhạc cụ nào cũng cần chơi to cùng lúc.

Bước 4: Đo lại bằng holdout

Giữ một phần user high-uplift làm holdout, tức vẫn chưa bật feature, để so sánh tiếp. Nếu bạn bật hết nhóm tốt nhất ngay, bạn sẽ mất đối chứng và bắt đầu lái bằng cảm giác.

Metric nên có ít nhất ba lớp:

Một feature có uplift tốt nhưng cost tăng quá mạnh vẫn có thể không đáng scale. AI product không chỉ cần đúng nốt, nó cần giữ được nhịp phách của hệ thống.

Guardrail: khi user randomization làm hỏng sân chơi

Có một trường hợp bạn không nên dùng A/B test theo user một cách ngây thơ: khi feature dùng chung tài nguyên khan hiếm.

Giả sử team bạn có query router quyết định request nào được đưa sang model premium. Offline eval cho thấy completion tăng 6 điểm phần trăm. Nếu bạn randomize theo user, nhóm treatment có router sẽ lấy premium capacity trước, còn nhóm control có thể bị ảnh hưởng vì tài nguyên còn lại ít hơn. Khi đó bạn không còn đo riêng tác động của router; bạn đo cả tác động của việc phân phối tài nguyên bị lệch.

Với kiểu bài toán này, hãy cân nhắc switchback experiment — thử nghiệm đảo trạng thái theo khung thời gian. Ví dụ hệ thống bật router trong một slot thời gian, tắt trong slot kế tiếp, rồi lặp lại. Cách này hợp với nền tảng LLM có shared capacity, marketplace, ranking, hoặc bất kỳ nơi nào hành vi của một nhóm làm đổi môi trường của nhóm khác.

Quy tắc ngắn:

Pitfall hay gặp: model uplift đẹp nhưng rollout vẫn dở

Uplift score không phải vé miễn kiểm soát. Có vài bẫy mình thấy rất thực tế:

1. Dùng feature sau treatment để dự đoán uplift
Ví dụ lấy số lần user bấm vào summary sau khi được bật summary để dự đoán ai nên được bật summary. Đây là rò rỉ dữ liệu. Model sẽ rất tự tin, và rất vô dụng khi deploy.

2. Chỉ tối ưu value, quên serving fairness
Nếu luôn ưu tiên nhóm có uplift cao nhưng họ cũng dùng nhiều compute nhất, nhóm còn lại có thể bị latency tệ hơn. Với sản phẩm multi-tenant, fairness trong serving không phải đạo đức treo tường; nó là SLO sống còn.

3. Không đặt tiêu chí dừng
Trước khi rollout, viết sẵn điều kiện rollback. Ví dụ: nếu latency p95 vượt ngưỡng nội bộ trong hai slot liên tiếp, nếu opt-out tăng rõ rệt, nếu nhóm enterprise có uplift âm, dừng lại và phân tích.

4. Tin một lần experiment mãi mãi
User học cách dùng sản phẩm. Model đổi. Prompt đổi. Giá inference đổi. Uplift hôm nay có thể không còn đúng sau vài tuần. Hãy xem score như bản phối đang được cập nhật, không phải bản thu đóng dấu vĩnh viễn.

Dấu hiệu nên scale, nên giữ nhỏ, hoặc nên dừng

Bạn có thể dùng khung quyết định này cho review rollout hằng tuần:

| Tín hiệu | Hành động |
|---|---|
| High-uplift band cải thiện value, cost trong ngưỡng, friction thấp | Mở rộng sang band kế tiếp |
| Value tăng nhưng cost tăng mạnh | Tối ưu routing, cache, prompt, hoặc giới hạn quota |
| Uplift chỉ xuất hiện ở một task type | Rollout theo task, không theo toàn bộ user |
| Neutral band không đổi, nhưng complaint tăng | Giữ off mặc định, cho opt-in nếu cần |
| Negative band có dấu hiệu bị gián đoạn workflow | Dừng rollout cho nhóm đó, thiết kế lại UX |

Điều quan trọng: targeted rollout không phải làm chậm shipping. Nó làm shipping bớt mù. Thay vì tranh luận cảm tính giữa product, data và infra, bạn có một nhịp quyết định chung: ai hưởng lợi, tốn bao nhiêu, rủi ro nằm ở đâu, khi nào dừng.

Kết lại gọn: A/B test cho bạn biết feature có đáng xây; uplift modeling giúp bạn biết nên bật cho ai. Bật AI cho tất cả chỉ vì trung bình đẹp thì giống bắt cả dàn nhạc chơi cùng một hợp âm từ đầu đến cuối — to đấy, nhưng chưa chắc thành nhạc.

---
Bụi Wire — nghiện đọc release notes lúc 2 giờ sáng

Nguồn tham khảo