Vấn đề: Đừng gửi thẳng dữ liệu khách hàng lên OpenAI
Cách đây 6 tháng, mình triển khai hệ thống RAG Chatbot cho một ngân hàng lớn. Thách thức lớn nhất lúc đó không phải là prompt engineering hay chọn model, mà là Data Privacy (Bảo mật dữ liệu). Khách hàng hỏi mình một câu rất thực tế: ‘Làm sao để chắc chắn số thẻ, số điện thoại hay địa chỉ nhà của user không bị đẩy thẳng lên server của OpenAI hay Claude?’.
Với dự án cá nhân, rủi ro có thể thấp. Nhưng trong môi trường doanh nghiệp, để lộ PII (Thông tin định danh cá nhân) là một rắc rối pháp lý cực lớn. Các quy định như GDPR hay Nghị định 13/2023/NĐ-CP của Việt Nam đều có chế tài rất nặng. Sau khi thử nghiệm nhiều phương án, mình chọn Microsoft Presidio. Đây là bộ công cụ giúp ‘lọc’ sạch dữ liệu cực kỳ ổn định trước khi nó rời khỏi server nội bộ.
Presidio hoạt động như thế nào?
Hãy coi Microsoft Presidio là một ‘máy lọc nước’ cho dữ liệu văn bản. Bạn đổ văn bản thô vào, nó soi tìm tên người, email, số căn cước… rồi thay thế chúng bằng nhãn giả hoặc mã hóa đi. Hệ thống này gồm hai bộ phận chính:
- Presidio Analyzer: Đóng vai trò ‘thám tử’. Nó kết hợp Regex, mô hình NLP (Spacy, Transformers) và logic checksum (như thuật toán Luhn cho số thẻ tín dụng) để truy tìm thực thể nhạy cảm.
- Presidio Anonymizer: Đóng vai trò ‘thợ sửa’. Dựa trên kết quả từ Analyzer, nó sẽ thực hiện: Thay thế (Replace), Xóa (Redact), Băm (Hash) hoặc Mã hóa (Encrypt).
Điểm cộng lớn nhất là khả năng hiểu ngữ cảnh. Presidio không chỉ dựa vào Regex khô khan. Nó phân biệt được khi nào ‘Washington’ là tên người, khi nào là địa điểm, giúp giảm tỷ lệ nhận diện sai (False Positive) xuống đáng kể.
Cùng bắt tay vào triển khai
Mình đang sử dụng Python 3.10 cho dự án này. Việc cài đặt Presidio cùng model ngôn ngữ của Spacy chỉ mất vài phút:
pip install presidio-analyzer presidio-anonymizer spacy
python -m spacy download en_core_web_lg
1. Phân tích dữ liệu với Analyzer
Đoạn code dưới đây sẽ giúp bạn ‘soi’ xem trong câu chat của người dùng chứa những gì nhạy cảm:
from presidio_analyzer import AnalyzerEngine
analyzer = AnalyzerEngine()
text_to_analyze = "Chào admin, tôi là Nguyễn Văn A, số điện thoại là 0901234567. Tôi muốn hỏi về đơn hàng gửi tới 123 Đường Lê Lợi."
# Chỉ định các thực thể cần tìm
results = analyzer.analyze(text=text_to_analyze, entities=["PERSON", "PHONE_NUMBER", "LOCATION"], language='en')
for res in results:
print(res)
Kinh nghiệm thực tế cho thấy model en_core_web_lg của Spacy nhận diện tên người Việt khá ổn dù đang để language='en'. Tuy nhiên, để đạt độ chính xác trên 95% cho tiếng Việt, bạn sẽ cần tinh chỉnh thêm ở bước sau.
2. Ẩn danh dữ liệu với Anonymizer
Sau khi thám tử Analyzer đã báo cáo, chúng ta tiến hành ‘che’ dữ liệu trước khi đẩy lên AI API.
from presidio_anonymizer import AnonymizerEngine
from presidio_anonymizer.entities import OperatorConfig
anonymizer = AnonymizerEngine()
# Cấu hình: Tên thì thay thế, số điện thoại thì che bớt, địa chỉ thì xóa hẳn
operators = {
"PERSON": OperatorConfig("replace", {"new_value": "[NAME]"}),
"PHONE_NUMBER": OperatorConfig("mask", {"type": "mask", "masking_char": "*", "chars_to_mask": 6, "from_end": True}),
"LOCATION": OperatorConfig("redact", {})
}
anonymized_result = anonymizer.anonymize(
text=text_to_analyze,
analyzer_results=results,
operators=operators
)
print(anonymized_result.text)
Kết quả trả về: “Chào admin, tôi là [NAME], số điện thoại là 0901******. Tôi muốn hỏi về đơn hàng gửi tới .”. Chuỗi này đã đủ an toàn để gửi tới GPT-4 mà không lo vi phạm chính sách bảo mật.
3. Tùy biến cho dữ liệu Việt Nam (Số CCCD, Biển số xe)
Presidio không mặc định hỗ trợ số Căn cước công dân (CCCD) 12 chữ số của Việt Nam. Bạn cần định nghĩa thêm một Custom Recognizer bằng Regex như sau:
from presidio_analyzer import PatternRecognizer, Pattern
# Định nghĩa pattern cho CCCD (12 chữ số liên tiếp)
cccd_pattern = Pattern(name="cccd_pattern", regex=r"\b\d{12}\b", score=0.5)
cccd_recognizer = PatternRecognizer(
supported_entity="VN_CCCD",
patterns=[cccd_pattern],
context=["số căn cước", "cccd", "định danh", "số định danh"]
)
analyzer.registry.add_recognizer(cccd_recognizer)
Kinh nghiệm thực chiến trên Production
Sau nửa năm vận hành, mình rút ra 3 bài học mấu chốt để hệ thống không bị ‘nghẽn’:
- Tốc độ xử lý: Đừng dùng model Transformer (BERT/RoBERTa) nếu ứng dụng yêu cầu real-time. Spacy model
lgkết hợp Regex cho độ trễ chỉ khoảng 50-100ms, nhanh hơn gấp 10 lần so với Transformer mà vẫn đảm bảo độ chính xác. - Kiểm soát nhận diện nhầm: Đừng dùng
score_thresholdmặc định. Hãy điều chỉnh con số này về khoảng 0.35 sau khi test với dữ liệu mẫu để cân bằng giữa việc bỏ sót và nhận diện nhầm. - Cơ chế hoàn tác (De-anonymization): Đôi khi AI cần trả lời đích danh tên khách hàng. Bạn nên lưu mapping giữa giá trị gốc và giá trị ẩn danh vào Redis theo session. Khi AI trả về kết quả chứa [NAME], bạn chỉ việc map ngược lại để phản hồi cho user.
Lời kết
Bảo mật dữ liệu không phải là việc ‘phó mặc’ cho các ông lớn như OpenAI hay Microsoft. Chủ động lọc PII bằng Presidio giúp bạn xây dựng uy tín với khách hàng, đặc biệt trong mảng FinTech và Healthcare. Chỉ với vài dòng code, bạn đã tạo ra một lớp giáp bảo vệ vững chắc cho hệ thống AI của mình.

