AI feature cần đường băng, không chỉ prompt

AI feature cần đường băng, không chỉ prompt

Một playbook mổ xẻ AI feature theo lớp: chọn đúng việc, khóa output, đo chất lượng, xử lý lỗi và quyết định khi nào cần cloud, local hay fine-tune.

Có một kiểu demo làm mình vừa thương vừa buồn cười: developer gọi API, model trả về một đoạn chữ trông ổn, cả team nhìn nhau như vừa thấy máy bay cất cánh. Rồi tuần sau user nhập câu hơi lệch, response bịa thêm dữ kiện, JSON bị bọc trong markdown fence, frontend parse nổ, log thì lộ stack trace ra màn hình.

Chuyến bay chưa cất cánh đâu bạn. Đó mới là lúc máy bay vừa lăn ra đường băng.

Luận điểm của mình hôm nay rất gọn: triển khai AI feature không phải là tối ưu prompt trước, mà là thiết kế hệ thống chịu được prompt hỏng. Prompt quan trọng, nhưng nó chỉ là một lớp trong toàn bộ luồng: chọn use case, cấu hình model, ràng buộc output, đánh giá chất lượng, fallback, privacy, và vận hành.

Sau bài này, thứ mình muốn bạn nghĩ khác là: đừng hỏi “prompt nào hay nhất?”, hãy hỏi “feature này có đủ lớp kiểm soát để user tin được không?”.

Sơ đồ minh họa cho bài AI feature cần đường băng, không chỉ prompt

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

Mục tiêu: biến demo thành tính năng có người dùng thật

Một AI feature đáng ship thường phải vượt qua 5 câu hỏi:

  1. Có cần AI không? Hay regex, search, rule-based logic đã đủ?
  2. Model được phép làm gì? Trả lời tự do, phân loại, tóm tắt, trích xuất JSON, hay gọi tool?
  3. Output có dùng được bằng code không? Hay chỉ đẹp khi đọc bằng mắt?
  4. Sai thì rơi về đâu? Retry, fallback model, trả lỗi nhẹ nhàng, hay chặn luôn?
  5. Team đo chất lượng bằng gì? Không chỉ “đúng/sai”, mà còn tone, độ bịa, độ ổn định, và chi phí vận hành.

Dịch sang tiếng người: nếu API call là động cơ, thì production feature cần cả tháp không lưu, lịch bay, quy trình hủy chuyến và đội xử lý hành lý thất lạc. Không ai mua vé chỉ vì động cơ kêu êm.

Checklist trước khi viết prompt đầu tiên

Trước khi mở editor và gõ prompt dài như hợp đồng thuê nhà, mình sẽ khóa 4 quyết định này.

| Quyết định | Chọn khi nào | Dấu hiệu chọn sai |
|---|---|---|
| Cloud model | Cần chất lượng tổng quát tốt, cập nhật nhanh, ít tự vận hành | Chi phí token tăng khó kiểm soát, dữ liệu nhạy cảm đi qua mạng |
| On-device model | Cần riêng tư, offline-friendly, latency ổn trong máy người dùng | Thiết bị không đồng nhất, khó đảm bảo model availability |
| Fine-tuning | Có style/domain lặp lại, dữ liệu đủ sạch, prompt không còn kéo nổi | Dùng để chữa một workflow chưa được định nghĩa rõ |
| Prompt + validation | Use case mới, dữ liệu ít, cần iterate nhanh | Không có schema, không có eval, mỗi lần sửa prompt là đo bằng cảm giác |

Ở đây có vài thuật ngữ cần neo nhanh:

Với nhiều team Việt Nam, lựa chọn thực tế nhất để bắt đầu vẫn là prompt + validation + fallback. Nó rẻ về mặt tổ chức: chưa cần pipeline training, chưa cần đội ML riêng, nhưng vẫn buộc bạn thiết kế feature như hệ thống thật.

Mổ theo lớp: một AI feature nên có gì?

Thay vì nhìn feature AI như một prompt khổng lồ, mình thích bóc nó thành 6 lớp.

1. Lớp chọn việc: AI chỉ nên xử lý phần mơ hồ

Đừng đưa AI vào chỗ câu trả lời đã có quy tắc rõ.

Ví dụ cụ thể: app của bạn nhận ticket hỗ trợ khách hàng. AI có thể tóm tắt vấn đề, phân loại mức độ khẩn cấp, đề xuất nhóm xử lý. Nhưng việc kiểm tra khách có gói subscription nào thì nên gọi database, không nên hỏi model “khách này có premium không?”. Model không phải nhân viên lễ tân biết mọi thứ trong hệ thống.

Một heuristic mình dùng: nếu kết quả cần đúng tuyệt đối và dữ liệu nằm trong hệ thống của bạn, hãy ưu tiên tool/API; nếu kết quả cần diễn giải ngôn ngữ, AI mới đáng vào sân.

2. Lớp prompt: viết ràng buộc, không viết lời cầu nguyện

Prompt đầu tiên thường kiểu:

Summarize this support ticket and suggest next steps.

Chạy được. Nhưng dễ sinh output mỗi lần một kiểu.

Bản tốt hơn nên có:

You are helping a support agent triage a customer ticket.

Return only valid JSON with this shape:
{
  "summary": "one sentence",
  "urgency": "low | medium | high",
  "reason": "short explanation",
  "next_action": "one concrete action"
}

Rules:
- Do not invent product details not present in the ticket.
- If the ticket lacks enough information, set urgency to "medium" and explain what is missing.
- Do not include markdown fences.

Điểm quan trọng không phải prompt dài hơn. Điểm quan trọng là prompt có negative examples — ví dụ điều không được làm — và có hợp đồng output rõ.

3. Lớp structured output: JSON không đáng tin cho tới khi parse qua cửa kiểm soát

AI rất hay trả về JSON “gần đúng”: thừa dấu phẩy, bọc trong ```json, thêm lời dẫn “Sure, here is…”. Với mắt người thì ổn. Với backend thì nổ.

Đừng parse kiểu lạc quan:

const data = JSON.parse(modelText);

Hãy parse phòng thủ:

function extractJson(text: string) {
  const cleaned = text
    .replace(/^```json\s*/i, "")
    .replace(/^```\s*/i, "")
    .replace(/```$/i, "")
    .trim();

  const parsed = JSON.parse(cleaned);

  if (!parsed.summary || !parsed.urgency || !parsed.next_action) {
    throw new Error("AI_OUTPUT_SCHEMA_INVALID");
  }

  return parsed;
}

Trong production, bạn nên dùng validator như Zod, Pydantic, hoặc schema validation tương đương. Tên tool không quan trọng bằng nguyên tắc: model nói gì cũng phải qua cửa an ninh trước khi vào app.

4. Lớp eval: kiểm chất lượng, không chỉ kiểm câu đúng

Với feature AI, correctness chỉ là một phần. Bạn còn cần kiểm:

Hình dung thế này: bạn build tính năng tạo phản hồi cho nhân viên support. Một output “đúng” nhưng nói giọng lạnh tanh với khách đang bực có thể vẫn là output tệ. Ngược lại, một output hơi ngắn nhưng an toàn, không bịa, đúng workflow lại đáng dùng hơn.

Một bộ eval tối thiểu cho một buổi chiều có thể gồm 20 case thủ công:

- name: missing_order_id
  input: "Tôi chờ đơn 5 ngày rồi chưa thấy ai liên hệ"
  expected:
    urgency: medium
    must_not_contain:
      - "đơn hàng #"
      - "đã hoàn tiền"

- name: angry_customer
  input: "Dịch vụ quá tệ, tôi muốn hủy ngay"
  expected:
    urgency: high
    tone: empathetic

Bạn chưa cần hệ thống eval hoành tráng. Nhưng nếu không có bộ case cố định, mỗi lần sửa prompt là bạn đang lái trong nhiễu động mà không nhìn bảng điều khiển.

Quy trình triển khai trong một buổi chiều

Nếu là mình, mình sẽ không bắt đầu bằng việc đổi model liên tục. Mình sẽ chạy playbook này.

Bước 1: Chốt “AI contract” trên một trang

Viết ra:

Ví dụ:

{
  "input": ["ticket_text", "customer_plan", "locale"],
  "output": ["summary", "urgency", "reason", "next_action"],
  "forbidden": ["invent refund status", "invent order ID"],
  "fallback": "return safe triage message"
}

Bước 2: Viết prompt theo hợp đồng, không theo cảm hứng

Prompt nên có role, task, schema, rules, và 2-3 few-shot examples. Few-shot examples là vài ví dụ mẫu để model bắt được style và format.

Đừng đưa 20 ví dụ ngay từ đầu. Nhiều ví dụ quá có thể tạo constraint collision — va chạm ràng buộc — khi rule này bảo ngắn, ví dụ kia lại dài, schema một kiểu nhưng tone một kiểu.

Bước 3: Bọc output bằng parser và validator

Nếu output sai schema, đừng để lỗi tràn lên UI. Trả về trạng thái có kiểm soát:

try {
  const raw = await callModel(prompt);
  return validateAiOutput(extractJson(raw));
} catch (err) {
  logAiFailure(err);
  return {
    summary: "Không thể tạo tóm tắt an toàn lúc này.",
    urgency: "medium",
    reason: "AI output failed validation.",
    next_action: "Chuyển ticket cho nhân viên xử lý."
  };
}

Bước 4: Thêm retry và fallback có giới hạn

Retry không phải cứ lặp lại y chang. Nếu lần đầu fail vì schema, lần hai nên dùng prompt sửa lỗi:

The previous output was invalid JSON. Return only valid JSON matching the schema. Do not include explanations.

Nếu vẫn fail, fallback sang model khác hoặc trả safe response. Quan trọng: giới hạn số lần retry để không biến một ticket khó thành hóa đơn token dài ngoằng.

Bước 5: Ghi log thứ cần debug, không ghi dữ liệu bừa bãi

Log nên có:

Cẩn thận với dữ liệu nhạy cảm. Nếu log toàn bộ input user, bạn có thể tự tạo một kho rủi ro privacy. Với use case nhạy cảm, cân nhắc masking hoặc chạy local/on-device nếu phù hợp.

Ba bẫy hay gặp khi team bắt đầu ship

Bẫy 1: đổi model để chữa prompt mơ hồ. Model mạnh hơn có thể che lỗi tốt hơn, nhưng workflow vẫn lỏng. Hãy sửa contract trước.

Bẫy 2: fine-tune quá sớm. LoRA hay SFT rất hữu ích khi bạn có dữ liệu sạch và hành vi mong muốn ổn định. Nhưng nếu team còn chưa thống nhất output schema, fine-tuning chỉ làm lỗi được đóng gói đẹp hơn.

Bẫy 3: quên đường local. Không phải feature nào cũng cần cloud model. Với tác vụ tóm tắt nhẹ, phân loại, hoặc trích xuất từ dữ liệu nhạy cảm trên máy, kiến trúc web app + companion app local có thể đáng cân nhắc. Tradeoff là bạn phải xử lý môi trường máy người dùng: OS, phần cứng, quyền truy cập, trạng thái model có sẵn hay không.

Nếu là mình, mình sẽ quyết thế này

Với một AI feature mới cho product thật, mình sẽ chọn thứ tự:

  1. Prompt + schema + parser + eval nhỏ để xác nhận use case.
  2. Fallback và error boundary trước khi mở cho user thật.
  3. Quan sát log theo prompt version để biết lỗi đến từ input, model, schema hay latency.
  4. Sau đó mới cân nhắc fine-tune, local model, hoặc đổi provider.

Nói cách khác: đừng để model mới nhất kéo bạn chạy quanh sân bay. Hãy xây đường băng đủ chắc, rồi model nào đáp xuống cũng ít làm cả đội hú vía.

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

Nguồn tham khảo