Bỏ qua điều hướng
CÔNG TY CỔ PHẦN GIẢI PHÁP CÔNG NGHỆ HQG
Trung tâm AI · Hướng dẫn thực hành

Chuẩn bị dữ liệu huấn luyện AI

Phần lớn dự án AI doanh nghiệp đổ ở đây, không đổ ở phần cứng. Trang này là checklist theo đúng loại dữ liệu bạn có, kèm mẫu dữ liệu sao chép được và các đoạn mã để tự đo thay vì đoán.

Checklist theo loại dữ liệu

Chọn đúng loại dữ liệu bạn đang có. Mỗi việc đi kèm lý do — nếu lý do không áp dụng với bạn thì bỏ việc đó, đừng làm máy móc.

Hội thoại chăm sóc khách hàng

Lịch sử chat website, Zalo OA, Facebook, ticket email — có cả câu hỏi của khách và câu trả lời của nhân viên.

Dùng cho: Phù hợp nhất để fine-tune giọng và cách xử lý tình huống. Chính sách, giá, tồn kho thì để RAG tra lúc trả lời.

  1. 1Xuất dữ liệu kèm mốc thời gian, kênh và mã hội thoại.Để tách train/validation theo thời gian và truy lại được nguồn khi có tranh chấp nội dung.
  2. 2Chỉ giữ hội thoại đã kết thúc và khách hài lòng (hoặc được nhân viên giỏi duyệt).Mô hình học cả cái sai: giữ hội thoại xử lý tệ là dạy nó xử lý tệ.
  3. 3Gộp các tin nhắn liên tiếp của cùng một bên thành một lượt.Khách thường gửi 4–5 tin ngắn liền nhau; để nguyên sẽ thành nhiều lượt rỗng nghĩa.
  4. 4Bỏ câu chào, câu ký tên, chữ ký email, cảnh báo tự động.Mô hình sẽ bắt chước phần lặp vô nghĩa thay vì phần nội dung.
  5. 5Ẩn danh: tên, số điện thoại, email, địa chỉ, số đơn, số tài khoản.Dữ liệu cá nhân của khách không được nằm trong trọng số mô hình.
  6. 6Viết câu hệ thống (system prompt) cố định mô tả vai trò và giới hạn.Lúc huấn luyện và lúc chạy thật phải dùng cùng một câu hệ thống, nếu không chất lượng tụt.
  7. 7Giữ lại 200–500 hội thoại khó làm bộ đánh giá, KHÔNG đưa vào tập huấn luyện.Chấm trên dữ liệu đã học thì điểm nào cũng cao mà vô nghĩa.

Cạm bẫy hay gặp

  • Nhân viên trả lời bằng ảnh, file đính kèm: phần nội dung nằm ngoài văn bản, mô hình học được câu trả lời vô nghĩa.
  • Nhiều hội thoại là trùng lặp gần như hoàn toàn (cùng một câu hỏi phổ biến); không lọc trùng thì mô hình chỉ học một dạng câu.
  • Câu trả lời đúng tại thời điểm cũ nhưng nay đã sai chính sách: phải chốt ngày hiệu lực của dữ liệu.

Tài liệu nội bộ

Quy trình, chính sách, sổ tay, biên bản, slide đào tạo — phần lớn là PDF, Word, bản scan.

Dùng cho: Dùng cho RAG trước. Chỉ huấn luyện tiếp trên kho này khi mô hình không quen thuật ngữ của ngành.

  1. 1Lập danh mục tài liệu: tên, phòng ban sở hữu, mức bảo mật, phiên bản, ngày hiệu lực.Không có danh mục thì không phân quyền được và không biết bản nào là bản đang có hiệu lực.
  2. 2Bóc chữ từ PDF; bản scan thì OCR và kiểm tra lại dấu tiếng Việt.OCR sai dấu làm cả câu sai nghĩa, mà lỗi này rất khó phát hiện về sau.
  3. 3Bỏ đầu trang, chân trang, số trang, mục lục tự động.Phần lặp lại chen vào mọi đoạn, làm nhiễu cả tìm kiếm lẫn huấn luyện.
  4. 4Giữ cấu trúc tiêu đề (chương, mục) kèm theo mỗi đoạn.Một đoạn tách khỏi tiêu đề thường mất ngữ cảnh, dẫn đến trả lời sai ý.
  5. 5Xử lý bảng biểu riêng (xuất sang Markdown hoặc CSV) thay vì dán thẳng văn bản.Bảng bị dàn phẳng thành dòng chữ là nguồn sai số liệu kinh điển.
  6. 6Loại bản nháp, bản đã hết hiệu lực, bản trùng khác phiên bản.Hai phiên bản cùng tồn tại thì trợ lý sẽ trả lời theo bản sai mà vẫn tự tin.

Cạm bẫy hay gặp

  • Tài liệu mật lẫn vào kho dùng chung: lỗi phân quyền ở đây là lỗi nặng nhất của cả dự án.
  • Ảnh sơ đồ, bản vẽ chứa thông tin quan trọng mà văn bản không có — cần ghi chú bằng chữ hoặc dùng mô hình đọc ảnh.
  • Tài liệu quá dài không cắt đoạn hợp lý: đoạn cắt giữa câu làm câu trả lời bị đứt ý.

Hợp đồng, văn bản pháp lý

Hợp đồng, phụ lục, đơn hàng, biên bản nghiệm thu — văn bản có giá trị ràng buộc và nhiều thông tin đối tác.

Dùng cho: Dùng cho RAG và trích xuất thông tin có cấu trúc. Rất hiếm khi nên đưa vào tập huấn luyện.

  1. 1Hỏi pháp chế trước: tài liệu nào được phép đưa vào hệ thống AI, điều khoản bảo mật với đối tác nói gì.Nghĩa vụ bảo mật với đối tác không mất đi vì mục đích là nội bộ.
  2. 2Thay tên đối tác, số tài khoản, giá trị hợp đồng bằng mã giả lập nhất quán.Giữ được cấu trúc câu để mô hình học, mà không rò thông tin thương mại.
  3. 3Trích xuất thành trường có cấu trúc (bên A, bên B, thời hạn, giá trị, điều khoản phạt) thay vì để văn bản thô.Việc thực tế của doanh nghiệp là tra trường dữ liệu, không phải tán gẫu với hợp đồng.
  4. 4Luôn giữ liên kết tới bản gốc và số trang cho mỗi đoạn.Mọi câu trả lời về hợp đồng phải dẫn được về bản gốc để người có thẩm quyền tự đọc.
  5. 5Đánh dấu rõ bản đã hết hiệu lực, bản bị thay thế bởi phụ lục.Phụ lục mới ghi đè điều khoản cũ; trộn lẫn là trả lời sai nghĩa vụ.

Cạm bẫy hay gặp

  • Trợ lý AI tóm tắt điều khoản rồi người dùng coi đó là kết luận pháp lý — phải hiện cảnh báo và trích dẫn nguyên văn.
  • Chữ ký, con dấu, bản scan mờ: OCR hỏng đúng ở chỗ quan trọng nhất (số tiền, ngày).
  • Dữ liệu hợp đồng đưa ra mô hình bên ngoài là rủi ro hợp đồng, không chỉ rủi ro kỹ thuật.

Phiếu kỹ thuật, nhật ký bảo hành

Phiếu tiếp nhận, mô tả lỗi, thao tác đã làm, linh kiện thay, kết quả — thường nằm trong phần mềm quản lý hoặc Excel.

Dùng cho: Rất tốt cho cả hai: RAG để tra ca tương tự, và fine-tune để mô hình học cách chẩn đoán theo quy trình của công ty.

  1. 1Chuẩn hoá tên thiết bị, mã linh kiện, tên lỗi về một bộ từ vựng dùng chung.Cùng một lỗi được 5 kỹ thuật viên ghi 5 cách thì không mô hình nào học được.
  2. 2Ghép bộ ba: hiện tượng → việc đã làm → kết quả.Thiếu kết quả thì mô hình học cả những cách xử lý không hiệu quả.
  3. 3Bỏ các phiếu không có kết luận hoặc bị bỏ dở.Phiếu dở dang dạy mô hình trả lời lửng lơ.
  4. 4Bỏ tên khách, số điện thoại, địa chỉ lắp đặt; giữ model thiết bị và điều kiện môi trường.Thông tin kỹ thuật mới là thứ cần học, thông tin cá nhân là rủi ro không cần thiết.
  5. 5Gắn mốc thời gian và phiên bản firmware/phần mềm nếu có.Cách xử lý đúng với bản cũ có thể sai với bản mới.

Cạm bẫy hay gặp

  • Ô mô tả lỗi trong Excel chỉ ghi vài chữ viết tắt riêng của tổ: người ngoài đọc không hiểu thì mô hình cũng vậy.
  • Số liệu đo (điện áp, nhiệt độ) ghi lẫn đơn vị hoặc để trống — đừng để mô hình đoán đơn vị.
  • Một số ca xử lý sai nhưng vẫn ghi là xong: cần người có kinh nghiệm soát mẫu trước khi huấn luyện.

Mẫu dữ liệu và đoạn mã sao chép được

Mỗi dòng JSONL là một bản ghi JSON độc lập: không dấu phẩy cuối dòng, không bọc trong dấu ngoặc vuông, lưu bằng UTF-8.

Cấu trúc messages dưới đây là dạng các thư viện huấn luyện phổ biến nhận. Chuỗi ký tự đặc biệt của từng mô hình (chat template) do tokenizer của chính mô hình sinh ra — hãy dùng hàm áp chat template của tokenizer thay vì tự ghép chuỗi.

mau-hoi-thoai.jsonl — fine-tune theo giọng công ty

Mỗi dòng là một hội thoại hoàn chỉnh. Câu hệ thống (system) phải GIỐNG HỆT câu dùng khi chạy thật.

mau-hoi-thoai.jsonl
{"messages":[{"role":"system","content":"Bạn là trợ lý CSKH của công ty. Chỉ trả lời theo chính sách đã duyệt. Việc hoàn tiền, khiếu nại thì chuyển cho nhân viên."},{"role":"user","content":"Máy em mua tháng trước còn bảo hành không ạ?"},{"role":"assistant","content":"Dạ, em kiểm tra giúp mình nhé. Mình cho em xin số serial trên tem ở mặt sau máy ạ. Thông thường sản phẩm còn trong thời hạn bảo hành thì mình được hỗ trợ miễn phí phần lỗi do nhà sản xuất."}]}
{"messages":[{"role":"system","content":"Bạn là trợ lý CSKH của công ty. Chỉ trả lời theo chính sách đã duyệt. Việc hoàn tiền, khiếu nại thì chuyển cho nhân viên."},{"role":"user","content":"Cho mình xin giá tốt nhất của con server này"},{"role":"assistant","content":"Dạ về giá thì em xin phép chuyển anh/chị sang bộ phận kinh doanh để báo giá chính xác theo cấu hình và số lượng ạ. Anh/chị để lại số điện thoại giúp em nhé."}]}

mau-trich-xuat.jsonl — dạy mô hình trả về JSON có cấu trúc

Dùng cho việc trích xuất thông tin (phiếu kỹ thuật, hoá đơn). Câu trả lời mẫu phải là JSON hợp lệ, không thêm lời dẫn.

mau-trich-xuat.jsonl
{"messages":[{"role":"system","content":"Trích xuất thông tin phiếu kỹ thuật. Chỉ trả về JSON đúng khoá, không thêm chữ nào khác. Không biết thì để null."},{"role":"user","content":"Phiếu 2024-1180: máy chủ R740, khách báo không lên nguồn sau mất điện. Đã thay bộ nguồn 750W, test 2 giờ OK."},{"role":"assistant","content":"{\"ma_phieu\":\"2024-1180\",\"thiet_bi\":\"R740\",\"hien_tuong\":\"không lên nguồn sau mất điện\",\"xu_ly\":\"thay bộ nguồn 750W\",\"ket_qua\":\"OK\",\"thoi_gian_test_gio\":2}"}]}

doan-tai-lieu.jsonl — bản ghi đoạn cho kho vector (RAG)

Dùng cho RAG, KHÔNG phải để huấn luyện. Mỗi đoạn mang theo nguồn và mức bảo mật để lọc phân quyền ngay ở bước tìm kiếm.

doan-tai-lieu.jsonl
{"id":"qt-nhan-su-v3#12","text":"Nhân viên nghỉ phép từ 3 ngày liên tục trở lên phải có đơn được trưởng phòng phê duyệt trước ít nhất 5 ngày làm việc.","tieu_de":"Quy trình nhân sự > Nghỉ phép > Phép dài ngày","nguon":"QT-NS-03 v3.0","trang":12,"hieu_luc_tu":"2026-01-01","muc_bao_mat":"noi-bo","phong_ban":"nhan-su"}
{"id":"qt-nhan-su-v3#13","text":"Trường hợp nghỉ đột xuất vì lý do sức khoẻ, nhân viên thông báo cho trưởng phòng trong ngày và bổ sung đơn trong 3 ngày làm việc kế tiếp.","tieu_de":"Quy trình nhân sự > Nghỉ phép > Nghỉ đột xuất","nguon":"QT-NS-03 v3.0","trang":12,"hieu_luc_tu":"2026-01-01","muc_bao_mat":"noi-bo","phong_ban":"nhan-su"}

dem_token.py — đo số token THẬT bằng tokenizer của mô hình

Đây là cách duy nhất cho con số đúng. Mọi quy đổi “ký tự ÷ 3” chỉ là ước lượng để lên kế hoạch sơ bộ.

dem_token.py
# pip install transformers
import json, sys
from transformers import AutoTokenizer

MODEL = sys.argv[1] if len(sys.argv) > 1 else "Qwen/Qwen3-8B"
PATH = sys.argv[2] if len(sys.argv) > 2 else "mau-hoi-thoai.jsonl"

tok = AutoTokenizer.from_pretrained(MODEL)
tong, so_dong, dai_nhat = 0, 0, 0
chars = 0

with open(PATH, encoding="utf-8") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        rec = json.loads(line)
        # Dùng đúng chat template của mô hình -> số token sát thực tế huấn luyện nhất
        text = tok.apply_chat_template(rec["messages"], tokenize=False)
        n = len(tok(text)["input_ids"])
        tong += n
        chars += len(text)
        so_dong += 1
        dai_nhat = max(dai_nhat, n)

print(f"So mau:            {so_dong}")
print(f"Tong token:        {tong}")
print(f"Token/mau (TB):    {tong / max(1, so_dong):.0f}")
print(f"Mau dai nhat:      {dai_nhat} token")
print(f"Ky tu/token (do):  {chars / max(1, tong):.2f}")

tach_tap.py — tách train/validation theo thời gian

Tách theo thời gian (không trộn ngẫu nhiên) để điểm validation phản ánh việc dùng thật: học quá khứ, trả lời tương lai.

tach_tap.py
import json, random

NGUON = "mau-hoi-thoai.jsonl"
MOC = "2026-07-01"   # tất cả bản ghi từ ngày này trở đi làm validation
random.seed(42)       # cố định hạt giống để lần sau tách lại y nguyên

train, val, thieu_ngay = [], [], 0
with open(NGUON, encoding="utf-8") as f:
    for line in f:
        line = line.strip()
        if not line:
            continue
        rec = json.loads(line)
        ngay = rec.get("ngay")
        if not ngay:
            thieu_ngay += 1
            train.append(rec)          # không có ngày -> để vào train, đừng đoán
        elif ngay >= MOC:
            val.append(rec)
        else:
            train.append(rec)

for ten, data in (("train.jsonl", train), ("val.jsonl", val)):
    with open(ten, "w", encoding="utf-8") as f:
        for rec in data:
            f.write(json.dumps(rec, ensure_ascii=False) + "\n")

print(f"train={len(train)}  val={len(val)}  thieu_ngay={thieu_ngay}")
print("Kiem tra bat buoc: khong ban ghi nao xuat hien o ca hai tap.")

an_danh.py — ẩn danh thông tin cá nhân (bước bắt buộc)

Mẫu tối thiểu cho số điện thoại, email, số thẻ/tài khoản. Tên người và địa chỉ cần công cụ nhận dạng thực thể hoặc người soát — biểu thức chính quy không bắt được.

an_danh.py
import re, json, hashlib

# Giữ tính nhất quán: cùng một giá trị -> cùng một mã giả lập, để mô hình vẫn học được quan hệ.
def ma_gia(prefix: str, value: str) -> str:
    h = hashlib.sha256(value.encode("utf-8")).hexdigest()[:8]
    return f"<{prefix}_{h}>"

RE_EMAIL = re.compile(r"[\w.+-]+@[\w-]+\.[\w.-]+")
RE_PHONE = re.compile(r"(?<!\d)(?:\+?84|0)(?:\d[ .-]?){8,10}\d(?!\d)")
RE_SOTK  = re.compile(r"(?<!\d)\d{9,19}(?!\d)")

def an_danh(text: str) -> str:
    text = RE_EMAIL.sub(lambda m: ma_gia("EMAIL", m.group()), text)
    text = RE_PHONE.sub(lambda m: ma_gia("SDT", m.group()), text)
    text = RE_SOTK.sub(lambda m: ma_gia("STK", m.group()), text)
    return text

with open("tho.jsonl", encoding="utf-8") as fi, open("an-danh.jsonl", "w", encoding="utf-8") as fo:
    for line in fi:
        line = line.strip()
        if not line:
            continue
        rec = json.loads(line)
        for m in rec.get("messages", []):
            m["content"] = an_danh(m["content"])
        fo.write(json.dumps(rec, ensure_ascii=False) + "\n")

print("Xong. BAT BUOC: nguoi that doc mau it nhat 100 ban ghi truoc khi dung.")

Quy tắc làm sạch dữ liệu tiếng Việt

Chuẩn hoá Unicode về một dạng duy nhất
Tiếng Việt có dấu viết được bằng nhiều cách mã hoá khác nhau (tổ hợp hoặc dựng sẵn). Chữ nhìn giống nhau nhưng máy coi là hai chuỗi khác nhau, làm lọc trùng và tìm kiếm sai. Chạy chuẩn hoá NFC cho toàn bộ dữ liệu ngay bước đầu.
Thống nhất vị trí dấu thanh
“hoà” và “hòa” đều đúng chính tả nhưng là hai chuỗi khác nhau. Chọn một kiểu cho cả tập dữ liệu và ghi vào tài liệu quy ước.
Giữ nguyên dấu, không bỏ dấu để cho gọn
Bỏ dấu làm mất nghĩa và dạy mô hình trả lời không dấu. Nếu dữ liệu gốc không dấu, hãy xử lý thành một nhánh riêng, đừng trộn.
Sửa lỗi OCR theo danh sách lỗi hay gặp
Bản scan hay nhầm chữ có dấu và chữ số (ví dụ số 0 và chữ O, số 1 và chữ l). Lập danh sách lỗi riêng cho máy quét của bạn rồi sửa theo lô, và kiểm tra tay trên mẫu ngẫu nhiên.
Bỏ khoảng trắng rác, ký tự điều khiển, emoji lặp
Chat khách hàng đầy khoảng trắng kép, ký tự xuống dòng giữa câu và emoji lặp hàng chục lần. Gom khoảng trắng, giữ tối đa 1–2 emoji liền nhau.
Chuẩn hoá cách viết số, đơn vị, ngày tháng
Dấu chấm và dấu phẩy trong số tiền bị dùng lẫn lộn. Chọn một quy ước, ghi vào tài liệu, và đặc biệt cẩn thận với số tiền và số đo kỹ thuật.
Lọc trùng ở mức gần giống, không chỉ trùng tuyệt đối
Hội thoại CSKH lặp rất nhiều. So khớp tuyệt đối chỉ bắt được phần nhỏ; nên lọc theo độ tương đồng (ví dụ MinHash/SimHash) với ngưỡng bạn tự chọn và ghi lại ngưỡng đó.
Bỏ mẫu quá dài hoặc quá ngắn theo ngưỡng ghi rõ
Mẫu dài hơn độ dài chuỗi huấn luyện sẽ bị cắt mất phần trả lời; mẫu chỉ vài từ thì không dạy được gì. Ghi ngưỡng đã dùng vào tài liệu dữ liệu.
Rà câu trả lời có hại, có cam kết, có số liệu chưa kiểm
Mô hình học y nguyên những lời hứa chắc chắn và những con số trong dữ liệu. Nếu không muốn trợ lý hứa thay công ty, hãy bỏ các mẫu đó.

Tách train / validation / bộ đánh giá

Tách theo thời gian là mặc định
Dữ liệu cũ để học, dữ liệu mới nhất để chấm. Đây là cách sát nhất với việc dùng thật và dễ giải thích cho lãnh đạo.
Tách theo nhóm khi có bản ghi liên quan
Nhiều lượt chat của cùng một khách, nhiều phiếu của cùng một thiết bị phải nằm trọn trong một tập. Trộn chúng ra cả hai tập là rò dữ liệu, điểm cao giả.
Tỷ lệ thường dùng và cách chọn
Dữ liệu nhỏ (dưới 5.000 mẫu) nên để 10–20% cho validation; dữ liệu lớn thì vài nghìn mẫu validation là đủ. Quan trọng hơn tỷ lệ là validation phải đủ đa dạng tình huống.
Bộ đánh giá (test) tách riêng và khoá lại
Ngoài validation dùng để dò tham số, cần một bộ test do người trong công ty duyệt, chỉ mở ra chấm lần cuối. Đừng dùng nó để chọn tham số, nếu không nó mất tác dụng.
Kiểm tra giao nhau trước mỗi lần chạy
Viết kiểm tra tự động: không có mã bản ghi nào xuất hiện ở hai tập, không có đoạn văn bản giống nhau trên ngưỡng đã chọn.
Cố định hạt giống ngẫu nhiên và ghi lại
Không cố định thì lần sau tách ra tập khác, mọi so sánh giữa các lần chạy đều mất ý nghĩa.

Ẩn danh dữ liệu cá nhân

Liệt kê trước loại thông tin cá nhân có trong dữ liệu
Tên, số điện thoại, email, địa chỉ, số căn cước, số tài khoản, biển số, ảnh chứng từ. Không liệt kê trước thì chắc chắn bỏ sót.
Thay bằng mã giả lập nhất quán, không xoá trắng
Cùng một số điện thoại luôn thành cùng một mã: mô hình vẫn học được quan hệ trong hội thoại mà không giữ thông tin thật.
Biểu thức chính quy chỉ bắt được dạng có khuôn
Số điện thoại, email, số tài khoản thì bắt được. Tên người và địa chỉ tiếng Việt cần công cụ nhận dạng thực thể hoặc người soát.
Người thật đọc mẫu ngẫu nhiên sau khi chạy
Chọn ít nhất 100 bản ghi, đọc kỹ xem còn thông tin cá nhân nào sót. Ghi lại kết quả kiểm tra này.
Giữ bảng tra ngược ở nơi riêng, quyền riêng
Nếu cần tra lại bản gốc, bảng ánh xạ mã ↔ giá trị thật phải nằm ngoài tập huấn luyện, mã hoá, và chỉ vài người có quyền.
Chỉ thu đúng thứ cần cho bài toán
Cách giảm rủi ro rẻ nhất là không đưa dữ liệu không cần thiết vào hệ thống AI ngay từ đầu.

Trước khi đưa dữ liệu vào hệ thống AI

Nhắc nhở thực hành — không phải tư vấn pháp lý
  • Dữ liệu khách hàng, nhân viên, đối tác là dữ liệu cá nhân. Trước khi đưa vào hệ thống AI, hãy hỏi bộ phận pháp chế xem mục đích sử dụng này có nằm trong phạm vi đã thông báo và đã được đồng ý hay không.
  • Nghĩa vụ bảo mật trong hợp đồng với đối tác vẫn áp dụng khi dữ liệu chỉ dùng nội bộ. Kiểm tra điều khoản bảo mật trước, đừng kiểm tra sau.
  • Dữ liệu mua, thu thập từ Internet hoặc lấy từ sản phẩm của bên khác có điều khoản riêng về việc dùng để huấn luyện. Phải đọc điều khoản của đúng nguồn đó.
  • Trọng số mô hình sau khi huấn luyện có thể còn nhớ dữ liệu đã học. Dữ liệu đã nhồi vào trọng số rất khó lấy ra: hãy coi tập huấn luyện là thứ không gỡ lại được.
  • Ghi lại được xuất xứ từng tập dữ liệu (lấy ở đâu, ai cho phép, ngày nào) là việc tốn công nhưng là thứ duy nhất cứu bạn khi có người hỏi.
  • Những dòng trên là nhắc nhở thực hành, không phải tư vấn pháp lý và không trích dẫn văn bản cụ thể. Quyết định cuối cùng phải do bộ phận pháp chế hoặc luật sư của doanh nghiệp đưa ra.