SIPTech

Cấp 3 (C3): Tra cứu đơn qua công cụ chỉ đọc

Cách đọc các nhãn nhỏ trong bài: Có nguồn điều được nêu trong tài liệu gốc; Đề xuất ý kiến hoặc thiết kế của SIPTech; Minh họa ví dụ giả định. Gặp từ lạ? Rê chuột lên từ có gạch chấm, hoặc mở Từ điển thuật ngữ.

Trước khi học

Nên xem trước: cơ chế function calling, mô tả công cụ, hạng công cụ A-D, prompt injection, MCP ở Tra cứu tài liệu nội bộ · Cấp 7 — Công cụ. Riêng bài này tập trung vào: kiểm danh tính khách, trả ít trường, kiểm số trong nháp, các trạng thái đơn lạ.

Tóm tắt nhanh

Khách hỏi "đơn của tôi tới đâu rồi?" thì AI phải tra dữ liệu thật, không được đoán. Bài này chỉ cách cho AI một công cụ chỉ được đọc (không sửa, không hủy), kiểm tra khách đang chat đúng là chủ đơn, chỉ trả về vài thông tin cần thiết, và chặn mọi nháp trả lời có số tiền hay ngày không có trong dữ liệu. Sau bài, bạn có một hàm tra đơn an toàn, một hàm kiểm nháp, và bộ ca thử các trạng thái đơn lạ.

1. Bài này dành cho ai và bạn sẽ làm được gì

Bài này dành cho ai: người làm kỹ thuật nhẹ ở SME (doanh nghiệp vừa và nhỏ), biết Python hoặc Apps Script (ngôn ngữ viết đoạn mã ngắn gắn với Google Sheet), và đã học xong cấp C2. Nếu bạn không code, vẫn đọc được phần lớn bài: mỗi bài thực hành có "đường không code" (xem mục 5), và các đoạn mã đều có lời giải thích bằng lời thường.

Bạn cần chuẩn bị:

  • Nơi đang lưu đơn hàng của bạn: phần mềm bán hàng hoặc Google Sheet đơn hàng.
  • Kết quả của C2 (phân loại yêu cầu khách).
  • Với đường không code: một Project (Claude) hoặc Gem (Gemini). Đây là tính năng cho bạn lưu sẵn chỉ dẫn để dùng lại nhiều lần.

Sau bài này bạn sẽ có:

  1. Một hàm tra_don(ma_don, danh_tinh_kenh) chỉ đọc, gọi phần mềm bán hàng hoặc Google Sheet đơn hàng. ("Hàm" là một đoạn chương trình nhỏ nhận thông tin vào, trả kết quả ra. "Chỉ đọc" nghĩa là nó chỉ xem được, không sửa hay xóa được đơn.)
  2. Kiểm danh tính bằng code: chỉ trả đơn của đúng khách đang chat.
  3. Hàm kiem_nhap() chặn nháp có số tiền, ngày không có trong dữ liệu đã tra.
  4. Bộ ca thử gồm các trạng thái đơn lạ (không có trạng thái, giao thất bại, hoàn hàng).

Thứ bạn cầm đi được sau bài: bảng trường "trả / không trả" cho AI; bảng trạng thái đơn kèm câu nói với khách; hàm tra_don và hàm kiem_nhap(); bộ ca thử; và danh sách tiêu chí ở mục 6 để biết khi nào đủ điều kiện sang cấp tiếp theo.

2. Vấn đề bài này giải quyết

Câu hỏi: "Đơn của tôi tới đâu rồi?" là ý định (điều khách muốn hỏi) nhiều nhất ở nhiều shop Đề xuất. Nubank (một ngân hàng số, có bài báo mô tả việc triển khai AI thật) cũng chọn "Thẻ của tôi đâu?" làm ca đầu vì là một trong các ý định nhiều nhất của họ Nguồn: 2606.08867, mục 5.

Lỗi ở C2: AI phân loại đúng nhưng không biết đơn ở đâu. Nhân viên vẫn phải mở phần mềm, chép trạng thái vào. Hoặc tệ hơn, AI đoán ("đơn sẽ tới trong 2-3 ngày").

Nói đơn giản

Ở C2, AI mới chỉ biết khách đang hỏi chuyện gì. Ở C3, AI được phép tự tra thông tin thật trong phần mềm, nhưng chỉ tra đúng đơn của đúng khách, và chỉ nhìn thấy những gì cần thiết.

3. Kiến thức nền

3.1 Bằng chứng về lỗi khi agent tra dữ liệu

("Agent" ở đây là chương trình AI có thể tự gọi công cụ để lấy dữ liệu hoặc làm việc, không chỉ trả lời bằng chữ. "Tham số" là các thông tin ta đưa vào cho công cụ, ví dụ mã đơn.)

  • Có nguồn τ-bench (arXiv 2406.12045; "benchmark" là bộ bài thi dùng để chấm AI): ở miền bán lẻ, gpt-4o gọi công cụ đúng loại nhưng điền sai tham số hoặc đưa thông tin sai/thiếu chiếm khoảng 55% lỗi; gpt-4o gọi trung bình 0,46 lần mỗi tác vụ với mã người dùng/sản phẩm/đơn không tồn tại, gpt-3.5-turbo 2,08 lần. Số này của mô hình năm 2024; mô hình mới khác, nhưng loại lỗi vẫn là thứ cần thử.
  • Có nguồn Nubank: công cụ chỉ trả trường cần thiết; get_customer_profile lấy thông tin của khách đã xác thực (2606.08867, mục 5.1; Nền tảng bằng chứng).
  • Có nguồn Nubank (arXiv 2609.30137, Hình 1): ca kiểm thử viết tay thường giả định công cụ trả "đã giao"; khách thật gặp "không tìm thấy trạng thái", và agent trả lời lạc ("Không có thẻ nào"). Họ dựng mô phỏng tại ranh giới công cụ để thử các trạng thái này trước khi khách gặp.

Nói đơn giản

Hai bài học: (1) AI hay điền sai mã hoặc gọi mã không có thật, nên phải thử kỹ; (2) khi thử, đừng chỉ thử trường hợp đẹp ("đã giao"). Khách thật hay gặp những trạng thái lạ, và AI cần được thử trước với đúng những trạng thái đó.

3.2 Danh tính lấy từ kênh, không từ lời khách

Đề xuất

Khách gõ "đơn DH1002 của em" có thể là mã đơn của người khác. Nếu công cụ trả thẳng, AI sẽ đọc tên, địa chỉ người khác cho khách. Quy tắc:

  1. Danh tính (SĐT, mã khách) lấy từ hệ thống kênh: tài khoản Zalo OA/Messenger đã liên kết, email gửi đến. Không lấy từ nội dung tin. ("Kênh" là nơi khách nhắn tới bạn, ví dụ Zalo OA hoặc Messenger.)
  2. Code so mã đơn với danh tính. Không khớp → trả cùng một thông báo như "không có đơn", để không lộ đơn có tồn tại.
  3. Prompt không được là nơi kiểm quyền. OWASP LLM06 yêu cầu kiểm quyền ở hệ thống hạ nguồn "thay vì dựa vào LLM" (xem Tra cứu tài liệu nội bộ · Cấp 7 — Công cụ › Đọc vs ghi, quyền tối thiểu, xác nhận của người). (Prompt là đoạn chỉ dẫn bạn viết cho AI. OWASP là tổ chức công bố các hướng dẫn bảo mật; LLM là mô hình ngôn ngữ lớn, tức loại AI đứng sau các chatbot.)

Nói đơn giản

Đừng nhờ AI "tự cân nhắc xem khách này có được xem đơn không". Việc đó phải do phần mềm quyết định, theo một quy tắc cứng: số điện thoại của tài khoản đang chat phải trùng với số điện thoại trên đơn. Nếu không trùng, câu trả lời luôn giống hệt như khi đơn không tồn tại, để người xấu không dò được mã nào có thật.

3.3 Chỉ đọc, phạm vi nhỏ nhất

  • Nguồn: docs.haravan.com, đọc 2026-11-11 API đơn hàng của Haravan có hai phạm vi quyền tách riêng: com.read_orders và com.write_orders. Có lệnh lấy một đơn GET /com/orders/{order_id}.json và lệnh hủy đơn POST .../cancel.json. Đề xuất Khóa dùng cho AI chỉ cấp quyền đọc. Lệnh hủy thuộc C4, qua người duyệt. (API là "cửa" để chương trình này nói chuyện với phần mềm khác. Khóa API giống như chìa khóa, và "phạm vi quyền" quy định chìa đó mở được những cửa nào.)
  • KiotViet, Sapo, MISA: chưa đọc tài liệu API chính thức (mục 9). Shop nhỏ không có API: dùng Google Sheet xuất từ phần mềm mỗi giờ làm "bản sao chỉ đọc".

Nói đơn giản

Hãy đưa cho AI chiếc chìa khóa "chỉ xem", không đưa chìa "xem và sửa". Như vậy dù AI hiểu nhầm hay bị lừa, nó cũng không thể hủy hay sửa đơn của khách.

3.4 Kiểm số trong nháp bằng code

Mọi số tiền và ngày trong nháp phải có trong kết quả công cụ. Đây là bản rút gọn của ý "kiểm trích nguyên văn" (Airbnb, Tra cứu tài liệu nội bộ · Cấp 5 — Trả lời có trích dẫn) cho dữ liệu có cấu trúc. ("Nháp" là câu trả lời AI soạn sẵn cho khách, trước khi gửi đi. "Dữ liệu có cấu trúc" là dữ liệu xếp theo trường rõ ràng như bảng tính: trạng thái, ngày, tổng tiền.)

Nói đơn giản

Máy đối chiếu từng con số và từng ngày trong câu AI viết với dữ liệu vừa tra được. Con số nào không có trong dữ liệu thì chặn lại, không gửi cho khách.

4. Các bài thực hành

Sáu bài thực hành dưới đây làm theo thứ tự.

Bài 3.1: Bản đồ dữ liệu đơn

  • Việc cần làm: liệt kê đơn nằm ở đâu (KiotViet, Sapo, Haravan, sàn, Sheet), trường nào khách cần biết (trạng thái, ngày giao dự kiến, mã vận đơn, tổng tiền), trường nào không bao giờ trả cho AI (địa chỉ đầy đủ, SĐT người nhận khác, ghi chú nội bộ, giá vốn). ("Trường" là một cột thông tin của đơn, ví dụ "tổng tiền".)
  • Bạn có sau bài: bảng trường "trả / không trả".

Bài 3.2: Bảng trạng thái và câu nói tương ứng

  • Việc cần làm: liệt kê mọi trạng thái đơn có thật trong phần mềm (kể cả lạ: "giao thất bại", "đang hoàn", trống). Mỗi trạng thái: câu nói với khách (mẫu câu C1) và có phải chuyển người không.
  • Lỗi hay gặp: chỉ viết cho "đang giao" và "đã giao".

Bài 3.3: Hàm tra_don với kiểm danh tính

  • Việc cần làm: viết hàm theo mục 5. Thử 4 ca: đơn đúng khách; đơn của người khác; mã không tồn tại; SĐT viết dạng +84.
  • Không code: nhân viên tra trong phần mềm và dán chỉ các trường cho phép vào Project/Gem; không dán cả màn hình.

Bài 3.4: Đưa công cụ cho AI

  • Việc cần làm: khai báo công cụ (tên, mô tả, lược đồ tham số) theo Tra cứu tài liệu nội bộ · Cấp 7 — Công cụ › Bài 7.3 — Viết mô tả công cụ và lược đồ. Tham số danh_tinh_kenh không cho AI điền; code tự gắn từ phiên chat. ("Khai báo công cụ" là viết cho AI biết có công cụ nào, dùng để làm gì, cần điền những thông tin gì. "Lược đồ tham số" là bản mô tả các thông tin đó. "Phiên chat" là cuộc trò chuyện đang diễn ra với khách.)
  • Bạn có sau bài: vòng lặp gọi công cụ với 1 công cụ đọc. (Vòng lặp: AI xin gọi công cụ, code chạy công cụ, đưa kết quả lại cho AI, AI soạn câu trả lời.)

Bài 3.5: Kiểm số và ngày trong nháp

  • Việc cần làm: chạy kiem_nhap() trên mọi nháp có dữ liệu đơn. Lỗi → soạn lại một lần, vẫn lỗi → người.
  • Thử: nháp cố ý sai tổng tiền, sai ngày; nháp có mã vận đơn (không được báo nhầm là số tiền).

Bài 3.6: Thử trạng thái lạ và tin có lệnh ẩn

Nói đơn giản

Bài 3.6 là bài "thử phá". Bạn cố tình cho AI gặp tình huống xấu (công cụ lỗi, khách đòi xem đơn của người khác) và xem hệ thống có giữ được hai điều: không lộ đơn, và chuyển cho người khi có sự cố.

5. Hai cách làm: không cần code và có code

Bài này có hai cách làm. Cách không code dùng người làm hàng rào. Cách code nhẹ để máy làm hàng rào thay người.

Không code Code nhẹ
Tra đơn Nhân viên tra, dán trường cho phép vào Project/Gem Hàm tra_don gọi API chỉ đọc hoặc Sheet
Danh tính Nhân viên tự so SĐT Code so danh tính kênh với đơn
Kiểm số Người duyệt đối chiếu bằng mắt kiem_nhap() tự động

Đoạn mã dưới đây làm gì? Nó gồm ba việc. Thứ nhất, hàm tra_don tìm đơn theo mã và kiểm tra số điện thoại của khách đang chat có trùng với số trên đơn không (số viết 0901... hay +84 901... đều được hiểu là một). Nếu trùng, nó chỉ trả về vài trường cho phép (trạng thái, ngày, tổng tiền, mã vận đơn), không trả tên và địa chỉ. Nếu không trùng hoặc không có đơn, nó trả một thông báo chung và dặn chuyển người. Thứ hai, hàm so_va_ngay nhặt các số tiền và ngày có trong một đoạn văn. Thứ ba, hàm kiem_nhap so các số tiền và ngày trong nháp với dữ liệu vừa tra, và báo lỗi nếu có số hoặc ngày không có trong dữ liệu. Bạn không cần đọc hiểu từng dòng; chỉ cần nắm ý nghĩa, rồi nhờ người biết lập trình (hoặc nhờ AI) chạy giúp khi bạn cần đến cấp độ này.

Mã mẫu (đã chạy thử bằng python -I -X utf8, 2026-11-11; dữ liệu đơn là giả, không gọi API thật):

import re
DON = {"DH1001": {"sdt": "0901234567", "ten": "Nguyen Van A", "dia_chi": "12 Le Loi, Q1",
                  "trang_thai": "dang_giao", "ngay_dat": "2026-11-05", "du_kien_giao": "2026-11-12",
                  "tong_tien": 459000, "ma_van_don": "GHN-88812"}}
TRUONG_TRA_VE = ("trang_thai", "ngay_dat", "du_kien_giao", "ngay_giao", "tong_tien", "ma_van_don")

def chuan_sdt(s):
    s = re.sub(r"\D", "", s)
    return "0" + s[2:] if s.startswith("84") else s

def tra_don(ma_don, sdt_kenh_chat):
    d = DON.get(ma_don.strip().upper())
    if d is None or chuan_sdt(d["sdt"]) != chuan_sdt(sdt_kenh_chat):
        return {"loi": True, "thong_diep": "Khong tim thay don khop voi khach. Hay chuyen nguoi."}
    return {k: d[k] for k in TRUONG_TRA_VE if k in d}      # khong tra ten, dia chi, sdt

def so_va_ngay(text):
    so = {int(x.replace(".", "").replace(",", ""))
          for x in re.findall(r"(?<![A-Za-z\d-])(?:\d{1,3}(?:[.,]\d{3})+|\d{4,})", text)}
    ngay = set(re.findall(r"\d{4}-\d{2}-\d{2}|\d{1,2}/\d{1,2}(?:/\d{4})?", text))
    return so, ngay

def kiem_nhap(nhap, kq):
    so_nhap, ngay_nhap = so_va_ngay(nhap)
    so_ok = {v for v in kq.values() if isinstance(v, int)}
    ngay_ok = set()
    for v in kq.values():
        if isinstance(v, str) and re.fullmatch(r"\d{4}-\d{2}-\d{2}", v):
            y, m, dd = v.split("-")
            ngay_ok |= {v, f"{int(dd)}/{int(m)}", f"{int(dd)}/{int(m)}/{y}", f"{dd}/{m}", f"{dd}/{m}/{y}"}
    return ([f"so {s} khong co trong du lieu" for s in so_nhap - so_ok] +
            [f"ngay {n} khong co trong du lieu" for n in ngay_nhap - ngay_ok])

Kết quả chạy thử:

  • tra_don("DH1001", "+84 901 234 567") → chỉ trạng thái, ngày, tổng tiền, mã vận đơn; không có tên, địa chỉ.
  • tra_don("DH1002", "0901234567") (đơn của người khác) → thông báo chung, chuyển người.
  • kiem_nhap("Don tong 495.000d, du kien 10/11 a.", kq) → 2 lỗi (sai tiền, sai ngày).
  • Lần đầu viết regex (cách mô tả mẫu chữ để máy tự tìm trong văn bản), mã đơn "DH1001" bị đọc nhầm thành số 1001 và báo lỗi giả. Đã sửa bằng điều kiện "không đứng sau chữ hoặc dấu gạch". Bài học: hàm kiểm cũng phải có ca thử.

Nói đơn giản

Ví dụ chạy thử cho thấy ba điều: khách đúng chủ đơn chỉ nhận vài thông tin cần thiết; khách hỏi đơn của người khác chỉ nhận câu trả lời chung và được chuyển cho nhân viên; còn nháp ghi sai tiền hoặc sai ngày (495.000đ thay vì số đúng, ngày 10/11 không có trong dữ liệu) bị chặn lại. Và bản thân hàm kiểm cũng từng sai, nên cũng phải được thử.

Buộc chuyển sang code khi Đề xuất: nhân viên mất nhiều thời gian tra và dán; cần chặn lộ đơn chéo một cách chắc chắn; cần nhật ký ai tra đơn nào.

6. Khi nào bạn có thể lên cấp tiếp theo

Đề xuất

Bạn có thể sang cấp C4 khi đạt đủ các điều sau:

  1. 0 lần lộ dữ liệu đơn của khách khác trong ≥20 ca thử tấn công (đơn người khác, lệnh ẩn, SĐT biến thể).
  2. 100% nháp có số tiền/ngày đi qua kiem_nhap(); trên bộ thử, mọi nháp sai số bị chặn.
  3. Mọi trạng thái đơn có trong phần mềm đều có mẫu câu; trạng thái lạ và lỗi công cụ → chuyển người.
  4. Khóa API của AI chỉ có quyền đọc (chụp màn hình cấu hình quyền, ghi ngày).
  5. Nhật ký mỗi lần gọi công cụ: thời điểm, mã ca, mã đơn, kết quả (che trường nhạy cảm). Xem Tra cứu tài liệu nội bộ · Cấp 9 — Vận hành cho SME › Bài 9.1: Nhật ký mỗi lần gọi. ("Nhật ký", hay log, là bản ghi lại từng lần hệ thống làm việc gì, để sau này truy lại khi có sự cố.)

7. Ví dụ cho doanh nghiệp nhỏ ở Việt Nam

Minh họa

Ba tình huống giả định để bạn dễ hình dung.

7.a Shop gia dụng bán qua Haravan và Zalo OA

Công cụ tra_don dùng khóa phạm vi com.read_orders. Danh tính: SĐT khách đã chia sẻ khi nhắn OA (cần kiểm cách Zalo cung cấp, mục 9). Trạng thái "giao thất bại" → mẫu câu hẹn giao lại + chuyển nhân viên gọi khách.

7.b Nhà hàng nhận đặt bàn qua Messenger, lịch trong Google Sheet

"Đơn" là lượt đặt bàn. Công cụ đọc Sheet theo mã đặt bàn + SĐT. Không trả tên khách khác cùng giờ. Câu hỏi "còn bàn tối thứ 7 không" là công cụ khác (tra chỗ trống), không cần danh tính.

7.c Xưởng in nhận đơn qua email

Danh tính là địa chỉ email gửi đến. Tra tiến độ đơn trong Sheet sản xuất. Ngày giao dự kiến là cam kết: kiem_nhap() bắt mọi ngày không có trong Sheet.

8. Tài liệu tham khảo

Nguồn Loại Đọc Tin cậy
τ-bench, arXiv 2406.12045 Benchmark Toàn văn phần chính Cao về phương pháp
Nubank, arXiv 2606.08867 Bài báo, triển khai thật Phần lớn toàn văn Cao
Nubank, Screen Before You Serve, arXiv 2609.30137 Bài báo, triển khai thật Phần lớn toàn văn Cao (một tổ chức)
Haravan Omni API, Orders, https://docs.haravan.com/docs/omni-apis/orde… ↗ Tài liệu nhà cung cấp Đọc 2026-11-11 qua công cụ tóm tắt Cao
OWASP LLM06 Hướng dẫn bảo mật Qua Tra cứu tài liệu nội bộ · Cấp 7 — Công cụ Cao
Ghi chú kiểm chứng · những điều chưa chắc chắn, dành cho người soạn tài liệu (người học có thể bỏ qua)
  • API chỉ đọc của KiotViet, Sapo, MISA eShop: chưa đọc tài liệu chính thức; chỉ thấy trang mô tả node n8n của bên thứ ba và blog.
  • Đường dẫn và phạm vi quyền API hoàn tiền của Haravan: trang Orders chỉ dẫn link, chưa đọc.
  • Zalo OA cung cấp SĐT của người dùng cho doanh nghiệp theo cơ chế nào, có cần người dùng đồng ý không: chưa đọc tài liệu Zalo.
  • Messenger: cách ánh xạ người nhắn tin với khách trong phần mềm bán hàng: chưa đọc.
  • Regex kiểm số chỉ phủ định dạng thường gặp ("459.000đ", "12/11"); chưa phủ "459k", "4tr5", "hai trăm nghìn".