AI có trách nhiệm không phải khẩu hiệu đạo đức đặt cuối slide, mà là một tập việc kỹ thuật cụ thể: biết mình dùng dữ liệu cá nhân nào, có quyền dùng không, mô hình có đối xử khác nhau giữa các nhóm khách hàng không, và có bằng chứng để trả lời khi bị hỏi. Bài này làm ba việc bằng code chạy thật: che dữ liệu cá nhân trước khi vào log hoặc LLM, kiểm toán thiên lệch mô hình duyệt đơn trả góp bằng Fairlearn, và đối chiếu khung pháp lý Việt Nam. Khung pháp lý đã đổi, nên tên Nghị định 13 trong tiêu đề cần đặt đúng chỗ, như phần dưới giải thích.

Bài nối tiếp Giám sát mô hình sau triển khai và Đánh giá LLM và guardrails. Hai bài đó trả lời "mô hình có còn đúng và còn an toàn không"; bài này trả lời "mô hình có được phép dùng và có công bằng không". Output là kết quả thật trên Apple M4, Python 3.12, fairlearn==0.13.0, scikit-learn==1.9.0; mã ở code/s7-52. Dữ liệu là mô phỏng tự sinh, số điện thoại và CCCD là số bịa. Đây là bài kỹ thuật, không phải tư vấn pháp lý; hãy đối chiếu văn bản gốc và hỏi pháp chế trước khi áp dụng.

AI có trách nhiệm gồm những gì trong một dự án thật

Trong thực tế doanh nghiệp, AI có trách nhiệm quy về bốn câu hỏi mà một khách hàng hay cơ quan quản lý có thể hỏi bất cứ lúc nào:

  1. Dữ liệu nào: hệ thống AI có trách nhiệm phải biết mô hình và log chứa dữ liệu cá nhân nào, có cơ sở pháp lý nào, giữ bao lâu?
  2. Công bằng: AI có trách nhiệm phải trả lời được: tỷ lệ duyệt và tỷ lệ sai có chênh lệch lớn giữa các nhóm không, và chênh lệch đó do đâu?
  3. Giải thích và khiếu nại: trong AI có trách nhiệm, khi một đơn bị từ chối, ai giải thích được lý do và ai xem xét lại?
  4. Bằng chứng: có hồ sơ ghi lại phiên bản dữ liệu, mô hình, kết quả kiểm toán không?

Các bài trước đã cho mảnh ghép kỹ thuật: SHAP giải thích quyết định, MLflow lưu phiên bản. Bài này thêm bảo vệ dữ liệu cá nhân và đo thiên lệch.

Khung pháp lý cho AI có trách nhiệm ở Việt Nam: cái gì thay Nghị định 13

Nhiều tài liệu về AI có trách nhiệm và bài viết cũ vẫn gọi "Nghị định 13" là quy định bảo vệ dữ liệu cá nhân. Tình hình đã đổi. Theo bản tóm tắt của LexData: Luật Bảo vệ dữ liệu cá nhân số 91/2025/QH15 được Quốc hội thông qua ngày 26/6/2025 và có hiệu lực từ 01/01/2026; Nghị định 356/2025/NĐ-CP quy định chi tiết thi hành; Nghị định 13/2023/NĐ-CP hết hiệu lực từ 01/01/2026 theo khoản 2 Điều 42 của Nghị định 356. Một số bài thương mại diễn giải khác về giai đoạn chuyển tiếp, nên hãy đối chiếu văn bản gốc thay vì tin một bài tóm tắt, kể cả bài này: Luật 91/2025/QH15 và Nghị định 356/2025/NĐ-CP trên Công báo.

Những điểm của luật mà đội làm AI có trách nhiệm cần biết, theo tóm tắt trên:

  • Đồng ý (Điều 9): phải tự nguyện, rõ ràng, theo từng mục đích; im lặng hoặc không phản hồi không phải là đồng ý. Dữ liệu khách hàng thu cho mục đích giao hàng không tự động được dùng để huấn luyện mô hình chấm điểm.
  • Dữ liệu nhạy cảm: có yêu cầu cao hơn, ví dụ sức khoẻ, tài chính, tín dụng, vị trí, sinh trắc học (các Điều 26, 27, 31). Điều 27 nêu không dùng thông tin tín dụng để chấm điểm, xếp hạng khi chưa có đồng ý.
  • Đánh giá tác động xử lý dữ liệu (Điều 21): lập hồ sơ và gửi cơ quan chuyên trách trong 60 ngày kể từ ngày đầu xử lý, sau đó cập nhật khi có thay đổi.
  • Quyền của chủ thể dữ liệu: được biết, rút lại đồng ý (không hồi tố), chỉnh sửa, yêu cầu xoá hoặc hạn chế xử lý, khiếu nại.
  • Xử lý bằng AI (Điều 30): phải phân loại theo mức độ rủi ro, Chính phủ quy định chi tiết.

Ngoài luật dữ liệu, còn có Luật Trí tuệ nhân tạo số 134/2025/QH15, ban hành ngày 10/12/2025 và có hiệu lực từ 01/03/2026 (theo cổng văn bản của Chính phủ). Theo bài tổng hợp trên VTV, luật chia hệ thống AI thành ba mức rủi ro (cao, trung bình, thấp) dựa trên tác động tới quyền con người, an ninh quốc gia và trật tự công cộng, với nghĩa vụ và mức giám sát khác nhau theo từng mức.

Một mô hình duyệt trả góp hay chấm điểm tín dụng chạm vào quyền lợi tài chính của khách nên cần đánh giá xem nó rơi vào mức nào; việc xếp mức phải theo danh mục và hướng dẫn chính thức. Thời hạn chuyển tiếp cho hệ thống đã chạy trước ngày luật có hiệu lực cũng cần đọc trong văn bản gốc.

Với đội kỹ thuật làm AI có trách nhiệm: hỏi pháp chế ba việc (cơ sở pháp lý và mục đích, có cần hồ sơ đánh giá tác động không, mô hình thuộc mức rủi ro nào) và ghi câu trả lời vào cùng repo. Hai phần dưới là việc nhóm làm được ngay.

AI có trách nhiệm bắt đầu từ giảm thiểu dữ liệu cá nhân

Nguyên tắc đầu tiên của AI có trách nhiệm: cách an toàn nhất với dữ liệu cá nhân là không giữ nó. Log ứng dụng, ticket chăm sóc khách hàng, văn bản gửi vào LLM thường chứa số điện thoại, email, CCCD mà không ai chủ ý lưu. Bước đầu tiên của AI có trách nhiệm là một lớp che dữ liệu đặt ở mọi cổng ra: ghi log, xuất dữ liệu huấn luyện, gọi LLM bên ngoài. Đoạn dưới dùng biểu thức chính quy cho ba loại định dạng cố định, và thay giá trị bằng một mã giả danh (pseudonym) tính bằng HMAC-SHA256 với khoá bí mật:

PATTERNS = {
    "CCCD": re.compile(r"(?<!\d)\d{12}(?!\d)"),
    "DIEN_THOAI": re.compile(r"(?<!\d)(?:\+84|0)(?:3|5|7|8|9)\d{8}(?!\d)"),
    "EMAIL": re.compile(r"[\w.+-]+@[\w-]+(?:\.[\w-]+)+"),
}
KEY = os.environ.get("PSEUDO_KEY", "khoa-demo-khong-dung-that").encode()

def pseudonym(kind, value):
    digest = hmac.new(KEY, f"{kind}:{value}".encode(), hashlib.sha256).hexdigest()[:8]
    return f"<{kind}_{digest}>"

Hai chi tiết đáng chú ý. Thứ nhất, (?<!\d) và (?!\d) bắt buộc có mặt để một dãy 15 chữ số, ví dụ mã vận đơn, không bị nhận nhầm là CCCD 12 số. Thứ hai, dùng HMAC có khoá thay vì băm trơn: số điện thoại di động Việt Nam chỉ có cỡ vài trăm triệu khả năng nên băm SHA-256 không khoá có thể bị dò ngược bằng cách thử hết. Chạy demo_pii.py:

GOC : Khach Nguyen Van A goi 0912345678 hoi doi tra, CCCD 012345678901.
MASK: Khach Nguyen Van A goi <DIEN_THOAI_d79dab78> hoi doi tra, CCCD <CCCD_4aaa4512>. ['CCCD', 'DIEN_THOAI']

GOC : Gui hoa don cho an.tran@example.com, so dien thoai +84987654321.
MASK: Gui hoa don cho <EMAIL_14777fe8>, so dien thoai <DIEN_THOAI_6bad0203>. ['DIEN_THOAI', 'EMAIL']

GOC : Don 123456789012345 tre 3 ngay
MASK: Don 123456789012345 tre 3 ngay []

nhat quan: <DIEN_THOAI_d79dab78> | lien he <DIEN_THOAI_d79dab78> nhe

Cùng một số điện thoại luôn ra cùng một mã, nên phân tích vẫn đếm được "khách này liên hệ mấy lần" mà không lộ số thật.

Lưu ý về độ dài mã: hàm pseudonym chỉ giữ 8 ký tự hex (32 bit) cho gọn; với vài chục nghìn giá trị khác nhau đã có thể xảy ra va chạm, tức hai số khác nhau cùng một mã và làm sai phép đếm. Bản demo chấp nhận điều đó, còn khi sản xuất nên giữ từ 16 ký tự hex trở lên. Về giới hạn của cách làm: tên người (Nguyen Van A vẫn còn nguyên), địa chỉ và mô tả gián tiếp không bị biểu thức chính quy bắt; cần mô hình nhận dạng thực thể (NER) và vẫn phải chấp nhận sót. Giả danh hoá chưa phải ẩn danh hoá: còn giữ khoá thì vẫn đối chiếu lại được về cá nhân, nên coi đó là dữ liệu cá nhân và bảo vệ khoá như bí mật.

Đưa dữ liệu đã che vào LLM trong AI có trách nhiệm

Khi gọi LLM bên ngoài, mọi văn bản rời khỏi hệ thống là một lần chuyển dữ liệu cho bên thứ ba. Che trước khi gửi là biện pháp rẻ nhất. Script demo_llm_mask.py che ticket rồi gọi mô hình qwen2.5:1.5b chạy bằng Ollama qua endpoint tương thích OpenAI http://localhost:11434/v1, nên không cần khoá API thật; với dịch vụ thương mại chỉ cần đổi base_url và khoá lấy từ biến môi trường:

Gui vao LLM: Khách gọi <DIEN_THOAI_d79dab78>, CCCD <CCCD_4aaa4512>, email <EMAIL_14777fe8>, báo đơn DH-1042 giao chậm 5 ngày, đòi hoàn tiền.
Loai du lieu da che: ['CCCD', 'DIEN_THOAI', 'EMAIL']
LLM tra ve: Mã khách hàng: <DIEN_THOAI_d79dab78>  
Mã CCCD: <CCCD_4aaa4512>  
Email: <EMAIL_14777fe8>  
Báo đơn: DH-1042  
Giá trị: Giao chậm 5 ngày  
Quyết định: Đã

Output này cho thấy hai điều thật thà về AI có trách nhiệm trên mô hình nhỏ. Mô hình 1,5 tỉ tham số tóm tắt kém: nó gán nhãn "Mã khách hàng" cho số điện thoại và tự thêm dòng "Quyết định", bị cắt giữa chừng vì giới hạn 80 token. Đó là chất lượng của mô hình tí hon, không phải của kỹ thuật che; điều cần kiểm chứng là các mã giả danh đi qua LLM còn nguyên và không có số thật nào lọt vào. Ở lần chạy đầu, khi lời nhắc không có hướng dẫn, mô hình còn từ chối vì thấy chuỗi <...>; thêm một câu system giải thích đó là mã ẩn danh thì khắc phục được.

Thiên lệch trong AI có trách nhiệm: dữ liệu mô phỏng có chủ ý

Để kiểm toán thiên lệch theo tinh thần AI có trách nhiệm, ta cần biết "sự thật". Với dữ liệu thật thì không bao giờ biết đầy đủ, nên bài dựng dữ liệu mô phỏng trong data.py với ba cơ chế có chủ ý, đều là cơ chế có thật ngoài đời. Một cửa hàng duyệt đơn trả góp, nhóm nhạy cảm là khu vực (thành thị 65%, nông thôn 35%):

  • Khả năng trả nợ thật không phụ thuộc khu vực: nó phụ thuộc thu nhập, số lần trễ hạn và giá trị đơn.
  • Nhãn lịch sử bị méo (selection bias): trong quá khứ, đơn nông thôn bị từ chối nhiều hơn nên thiếu nhãn "trả đủ". Mô phỏng bằng cách xoá ngẫu nhiên 25% nhãn tốt ở nhóm này.
  • Biến đại diện (proxy): khoảng cách tới kho tương quan rất mạnh với khu vực, dù khu vực không được đưa vào mô hình.

Trong kiểm toán AI có trách nhiệm, nhãn méo là rủi ro lớn nhất; output của demo_bias.py cho thấy nhãn đã méo như thế nào:

Ty le nhan 'tra du' theo khu vuc (nhan quan sat) / (nhan that, chi co trong mo phong):
           paid_ok_observed  paid_ok_true
region                                   
nong_thon             0.396         0.538
thanh_thi             0.593         0.593
Khoang cach trung binh theo khu vuc: {'nong_thon': 37.4, 'thanh_thi': 9.2}

Muốn biết thiên lệch của AI có trách nhiệm, cần so với sự thật: khách nông thôn thật ra trả đủ 53,8% (thấp hơn thành thị do thu nhập thấp hơn, đúng với công thức), nhưng trong dữ liệu quan sát chỉ còn 39,6%. Mô hình học từ nhãn quan sát nên sẽ học luôn phần méo này. Đây là kiểu thiên lệch phổ biến nhất trong dữ liệu quá khứ của doanh nghiệp: quyết định cũ của con người trở thành "sự thật" cho mô hình mới.

Đo thiên lệch bằng Fairlearn cho AI có trách nhiệm

Fairlearn cung cấp MetricFrame để tính một chỉ số theo từng nhóm, cùng các hàm tổng hợp như demographic_parity_difference (chênh lệch tỷ lệ được duyệt) và equalized_odds_difference (chênh lệch lớn nhất của tỷ lệ dương tính thật và dương tính giả giữa các nhóm). Ta huấn luyện hồi quy logistic trên nhãn quan sát và đánh giá trên nhãn thật, hai lần: có và không có cột khoảng cách.

mf = MetricFrame(
    metrics={"ty_le_duyet": selection_rate, "TPR": true_positive_rate, "FPR": false_positive_rate},
    y_true=y_true_test, y_pred=pred, sensitive_features=region_test)
print(mf.by_group.round(3))
print(demographic_parity_difference(y_true_test, pred, sensitive_features=region_test))
== A. day du dac trung (ke ca khoang cach) | do chinh xac 0.661
           ty_le_duyet    TPR    FPR
region                              
nong_thon        0.279  0.390  0.141
thanh_thi        0.678  0.808  0.479
chenh lech ty le duyet (demographic parity): 0.399
chenh lech equalized odds: 0.418

== B. bo khoang cach (proxy) | do chinh xac 0.676
           ty_le_duyet    TPR    FPR
region                              
nong_thon        0.425  0.573  0.242
thanh_thi        0.605  0.742  0.396
chenh lech ty le duyet (demographic parity): 0.18
chenh lech equalized odds: 0.169

Đọc kết quả kiểm toán AI có trách nhiệm. Ở cấu hình A, mô hình không hề nhận cột khu vực nhưng vẫn duyệt 67,8% đơn thành thị so với 27,9% đơn nông thôn. Cột khoảng cách đã làm thay việc của cột khu vực, và mô hình còn học luôn thiên lệch trong nhãn. Đáng chú ý là TPR: trong nhóm khách nông thôn thật sự trả đủ, mô hình chỉ nhận ra 39,0%, nhóm thành thị là 80,8%. Đó là thiệt hại "phân bổ" (allocation harm) theo tài liệu Fairlearn: hệ thống giữ lại cơ hội của một nhóm.

Bỏ cột khoảng cách ở cấu hình B giảm chênh lệch từ 0,399 xuống 0,180 mà độ chính xác còn tăng nhẹ (0,661 lên 0,676, đo trên nhãn thật). Đây là một dữ liệu mô phỏng và một lần chia tập; điều đáng mang theo là cách đo, không phải con số.

Bỏ proxy rõ nhất vẫn còn chênh lệch 0,18, vì thu nhập (biến hợp lệ) cũng thấp hơn ở nông thôn và vì nhãn bị méo. Loại cột nhạy cảm không đảm bảo công bằng, và chênh lệch giữa nhóm có thể một phần do khác biệt thật về điều kiện. Phần nào chấp nhận được là quyết định của con người, không phải của thư viện.

Giảm thiểu thiên lệch bằng ThresholdOptimizer: cái giá của AI có trách nhiệm

Fairlearn có kỹ thuật hậu xử lý ThresholdOptimizer: giữ nguyên mô hình, chọn ngưỡng quyết định riêng cho từng nhóm để thoả một ràng buộc như equalized_odds. Với AI có trách nhiệm, đây là bước giảm thiểu; chạy demo_mitigate.py trên cấu hình B:

== truoc giam thieu | do chinh xac (nhan that) 0.676
           ty_le_duyet    TPR    FPR
region                              
nong_thon        0.425  0.573  0.242
thanh_thi        0.605  0.742  0.396
DP diff: 0.18 | EO diff: 0.169

== ThresholdOptimizer equalized_odds | do chinh xac (nhan that) 0.675
           ty_le_duyet    TPR    FPR
region                              
nong_thon        0.590  0.784  0.351
thanh_thi        0.637  0.737  0.485
DP diff: 0.047 | EO diff: 0.134

Chênh lệch tỷ lệ duyệt giảm từ 0,180 xuống 0,047, độ chính xác gần như không đổi (0,676 so với 0,675). Nhưng cần đọc kỹ bốn điều:

  • Equalized odds chỉ giảm từ 0,169 xuống 0,134, không về gần 0 như kỳ vọng. Cột FPR cho thấy lý do: TPR hai nhóm đã sát nhau (0,784 so với 0,737) nhưng FPR vẫn lệch 0,134 (0,351 so với 0,485), và equalized_odds_difference lấy giá trị lớn hơn trong hai chênh lệch TPR và FPR. Một phần vì ràng buộc được giải trên nhãn quan sát (đã méo), và phần ngẫu nhiên hoá nói ở ý kế tiếp cũng làm số đo trên tập kiểm tra không khớp tuyệt đối.
  • Quyết định bị ngẫu nhiên hoá. Để đạt đúng ràng buộc, ThresholdOptimizer có thể chọn giữa hai ngưỡng theo xác suất, nên code phải truyền random_state=0 để tái lập. Hệ quả: hai hồ sơ giống hệt nhau trong cùng một nhóm có thể nhận kết quả khác nhau. Với quyết định tín dụng, đó là vấn đề thật cho việc giải thích lý do và khiếu nại, cần cân nhắc trước khi dùng.
  • Dùng ngưỡng khác nhau theo nhóm nghĩa là cột nhạy cảm phải có mặt lúc suy luận. Đối xử khác nhau theo nhóm có thể là điều bạn không được phép làm dù mục tiêu là công bằng; đây là câu hỏi cho pháp chế, không phải cho kỹ sư.
  • Các chỉ số công bằng có thể mâu thuẫn nhau. Tài liệu Fairlearn nói thẳng rằng parity về tỷ lệ duyệt và equalized odds có thể xung đột và "không có cách giải toán học" cho xung đột đó; công bằng là bài toán xã hội kỹ thuật, các chỉ số chỉ nắm một phần.

ThresholdOptimizer là công cụ để chọn đánh đổi có chi phí rõ ràng, không phải nút "làm công bằng". Giải pháp gốc rễ nằm ở dữ liệu: thu nhãn đúng cho nhóm từng bị loại, rồi đo lại, và theo dõi chỉ số theo nhóm trong giám sát như bài về data drift đã làm với chỉ số tổng.

Ghi hồ sơ cho AI có trách nhiệm: model card

Hồ sơ của AI có trách nhiệm chỉ có giá trị khi kết quả kiểm toán tái lập và tra cứu được. Mỗi phiên bản mô hình đưa lên registry (xem MLOps với MLflow) nên đi kèm một tệp "model card" ngắn: mục đích và phạm vi dùng, nguồn dữ liệu cùng cơ sở pháp lý, nhóm đã kiểm toán và chỉ số, hạn chế đã biết (nhãn méo, proxy còn lại), người chịu trách nhiệm và kỳ xem xét lại. Tệp này nằm cùng repo và cập nhật mỗi lần huấn luyện lại. Với hệ thống có thể thuộc nhóm rủi ro cao theo Luật Trí tuệ nhân tạo, tệp này là phần lớn "bằng chứng" bạn cần khi được hỏi.

Khi nào AI có trách nhiệm theo cách này chưa đủ

  • Quyết định hậu quả lớn: AI có trách nhiệm cần hơn một bảng chỉ số; vay, bảo hiểm, tuyển dụng, y tế cần con người xem xét lại và kênh khiếu nại; kiểm toán nhóm không thay được từng trường hợp.
  • Không biết nhóm nhạy cảm: trong AI có trách nhiệm, nhiều doanh nghiệp không thu (và không được thu) khu vực, giới tính, dân tộc; khi đó chỉ kiểm toán được qua proxy hoặc khảo sát riêng, kèm rủi ro pháp lý của việc suy đoán thuộc tính nhạy cảm.
  • Nhóm nhỏ: khi kiểm toán AI có trách nhiệm, với vài chục mẫu, chênh lệch 0,1 có thể chỉ là nhiễu; dùng khoảng tin cậy bootstrap trước khi kết luận.

Lỗi thường gặp khi làm AI có trách nhiệm

  • Tin rằng bỏ cột nhạy cảm là xong: proxy như khoảng cách, mã bưu chính vẫn mang thông tin; hãy đo kết quả theo nhóm.
  • Dùng băm trơn làm ẩn danh: SHA-256 không khoá của số điện thoại dò ngược được; dùng HMAC có khoá.
  • Chỉ báo chỉ số tổng: báo cáo không thể dừng ở đó; độ chính xác 0,676 che giấu TPR 0,573 so với 0,742 giữa hai nhóm.

Checklist AI có trách nhiệm trước khi đưa mô hình vào chạy

  • Lập danh sách trường dữ liệu cá nhân, cơ sở pháp lý, mục đích và thời gian lưu; hỏi pháp chế về hồ sơ đánh giá tác động và mức rủi ro AI.
  • Đặt lớp che dữ liệu ở mọi cổng ra (log, xuất dữ liệu, gọi LLM); giữ khoá giả danh hoá trong kho bí mật.
  • Kiểm toán theo nhóm: tỷ lệ duyệt, TPR, FPR cho từng nhóm quan trọng; đo cả khi đã bỏ cột nhạy cảm.
  • Hồ sơ AI có trách nhiệm: lưu model card cùng mỗi phiên bản; theo dõi chỉ số theo nhóm sau triển khai.
  • Có con người xem xét lại và kênh khiếu nại cho quyết định ảnh hưởng lớn; đó là điều kiện tối thiểu để một hệ thống tự gọi mình là AI có trách nhiệm, và là thứ khách hàng thường hỏi đầu tiên khi đánh giá AI có trách nhiệm của nhà cung cấp.

Mã nguồn bài AI có trách nhiệm. Cài đặt: python3.12 -m venv .venv && .venv/bin/pip install -r requirements.txt, rồi chạy demo_pii.py, demo_bias.py, demo_mitigate.py và demo_llm_mask.py trong code/s7-52; các tệp *_output.txt là output đã dán. Mỗi script chạy dưới vài giây, dùng dưới 160 MB RAM; demo_llm_mask.py cần Ollama với qwen2.5:1.5b. Output LLM có thể khác nhau giữa các lần chạy, kể cả với seed=0 (khi chạy lại bản này, mô hình trả về một câu tóm tắt khác và đánh mất mã giả danh); ba script còn lại cho output khớp từng ký tự.

Nguồn tham khảo: tài liệu Fairlearn về công bằng trong học máy, tóm tắt Luật Bảo vệ dữ liệu cá nhân 2025.

Bài tiếp theo

Polars cho dữ liệu lớn: lazy API và so sánh với pandas. Sau hai bài về vận hành và AI có trách nhiệm, bài kế tiếp trở lại với công cụ xử lý dữ liệu: khi bảng vượt quá sức pandas, Polars xử lý ra sao.