Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 4 — Thiết kế API cho tính năng không tất định (non-deterministic)

Đã đọc 0/9 mục · còn khoảng 4 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Vấn đề cốt lõi: developer ghét sự bất định họ không kiểm soát được

Lập trình viên xây hệ thống dựa trên giả định "input này → output kia". AI tooling phá vỡ giả định đó: cùng prompt cho kết quả khác nhau, độ trễ dao động, đôi khi mô hình "bịa" (hallucinate). DX PM không thể xóa bỏ tính bất định — nó là bản chất — nhưng có thể thiết kế API để dev kiểm soát, dự đoán và xử lý được sự bất định đó. Đây là kỹ năng đặc trưng nhất của DX PM mảng AI.

Nguyên tắc 1: Cho dev đòn bẩy kiểm soát

Mọi API AI nên phơi ra các tham số giúp dev điều chỉnh mức độ bất định:

  • temperature / top_p: điều khiển độ ngẫu nhiên. Đặt mặc định hợp lý và giải thích rõ.
  • seed: nếu backend hỗ trợ, cho phép tái lập kết quả — cực kỳ quý cho testing.
  • max_tokens: chặn trên độ dài, tránh phản hồi tràn và chi phí bất ngờ.
  • response_format / structured output: cho phép ép output theo JSON schema, biến thứ khó đoán thành thứ máy đọc được.
Quy tắc: structured output là người bạn tốt nhất của DX cho AI API. Khi dev khai báo schema và bạn đảm bảo output khớp schema, phần lớn nỗi đau bất định biến mất.

Nguyên tắc 2: Làm sự bất định trở nên minh bạch, không im lặng

  • Trả về metadata: usage (token in/out), model (phiên bản mô hình đã dùng), finish_reason (kết thúc do đủ, do max_tokens, hay do content filter). Dev cần biết tại sao output ra như vậy.
  • Phân biệt rõ các trạng thái kết thúc: một phản hồi bị cắt vì max_tokens khác hoàn toàn một phản hồi hoàn chỉnh — dev phải phân biệt được để retry đúng.
  • Confidence / safety signals nếu có: giúp dev quyết định có nên tin output không.

Nguyên tắc 3: Thiết kế lỗi như một tính năng

Với AI API, lỗi đa dạng và cần xử lý khác nhau. Một taxonomy lỗi tốt:

LoạiÝ nghĩaDev nên làm gì
rate_limit (429)Vượt giới hạnRetry với backoff, đọc header Retry-After
context_lengthPrompt quá dàiCắt bớt input
content_filterBị chặn nội dungĐổi prompt, không retry mù
timeout (504)Quá lâuRetry hoặc giảm kích thước
invalid_request (400)Sai tham sốSửa code — không retry
Mỗi lỗi cần mã ổn định (code), thông điệp người-đọc-được, và gợi ý hành động. Đừng gộp tất cả thành 500 Internal Error.

Nguyên tắc 4: Idempotency và streaming

  • Idempotency key: vì AI call đắt và có thể timeout giữa chừng, cho phép dev gửi idempotency_key để retry an toàn không bị tính phí/tạo kết quả hai lần.
  • Streaming (SSE): với LLM, trả token dần dần cải thiện cảm nhận độ trễ rất nhiều. Nhưng phải thiết kế rõ: định dạng event, cách báo kết thúc, cách trả lỗi giữa dòng stream.

Ví dụ cụ thể

Một API đổi từ trả về text thô sang cho phép response_format: json_schema. Trước đó dev phải viết regex mong manh để parse output LLM và thường xuyên vỡ khi mô hình đổi cách diễn đạt. Sau khi có structured output khớp schema, tỉ lệ lỗi parse phía dev giảm mạnh và số ticket support về "output không đúng định dạng" gần như biến mất — dù mô hình bên dưới vẫn non-deterministic.

Khung tư duy: "Contract ổn định bọc quanh lõi biến thiên"

Dev không cần lõi tất định; họ cần một hợp đồng (contract) ổn định: schema cố định, taxonomy lỗi cố định, metadata nhất quán, hành vi versioning rõ ràng. Bên trong lõi có thể biến thiên bao nhiêu tùy ý, miễn là lớp vỏ hợp đồng không đổi bất ngờ.

Checklist thiết kế API AI

  • [ ] Có tham số kiểm soát bất định (temperature, seed, max_tokens) với mặc định hợp lý chưa?
  • [ ] Có structured output / JSON schema chưa?
  • [ ] Response có finish_reason, usage, model chưa?
  • [ ] Taxonomy lỗi có mã ổn định + gợi ý hành động chưa?
  • [ ] Có idempotency key cho retry an toàn chưa?
  • [ ] Streaming (nếu có) đã định nghĩa rõ event và cách báo lỗi giữa dòng chưa?

Sai lầm thường gặp

  • Ẩn phiên bản mô hình, khiến dev không hiểu vì sao output đổi sau một đợt cập nhật thầm lặng.
  • Gộp mọi lỗi thành 500, buộc dev đoán mò và retry mù cả những lỗi không nên retry.
  • Không có structured output, đẩy gánh nặng parse text bấp bênh sang dev.
  • Bỏ qua idempotency, khiến retry sau timeout tạo double-charge hoặc kết quả trùng.
  • Đặt temperature mặc định cao rồi để dev bối rối vì output "lúc nào cũng khác".
Một API tốt cho dev cảm giác kiểm soát ngay cả khi lõi bất định. Bài sau bàn cách giữ hợp đồng đó ổn định qua thời gian: versioning và deprecation.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi