Viết yêu cầu cho AI sao cho nó làm đúng và không bịa

Cùng một AI nhưng hỏi khác nhau thì kết quả khác hẳn. Cách viết yêu cầu theo năm phần, ba lớp chặn bịa và một bộ kiểm bằng code chạy được.

Phát LâmĐăng Cập nhật 7 phút đọcTrung cấp
Viết yêu cầu cho AI sao cho nó làm đúng và không bịa
Mục lục
  1. Viết yêu cầu giống như giao việc cho nhân viên mới
  2. Một yêu cầu tốt gồm những gì
  3. Làm sao để AI đừng bịa
  4. Cho bạn nào viết code
  5. Lỗi hay gặp
  6. Làm gì tiếp theo

Bạn nhờ AI xem giúp một đoạn code. Nó trả về ba đoạn khen chê chung chung, và một lỗi ở dòng 48 trong khi file chỉ có 30 dòng. Bạn thử lại với cùng câu hỏi, lần này nó bảo code ổn. Cùng một AI, hai người hỏi hai kiểu có thể nhận về hai chất lượng khác hẳn.

Chuyện này sửa được, và không cần mẹo thần kỳ nào. Bài này nói cách mình viết yêu cầu cho AI trong việc xem code, viết test và làm tài liệu, cùng một cách đơn giản để bắt AI khi nó bịa.

Viết yêu cầu giống như giao việc cho nhân viên mới

Chữ bạn gõ cho AI gọi là prompt. Hãy tưởng tượng bạn giao việc cho một bạn mới vào công ty hôm nay. Bạn ấy giỏi, nhưng không biết gì về dự án của bạn. Nếu bạn ấy đọc yêu cầu mà rối, AI cũng sẽ rối. Tài liệu của Anthropic cũng nói gần như vậy: đưa prompt cho một đồng nghiệp ít ngữ cảnh, họ không hiểu thì mô hình cũng không hiểu.

Trước khi chỉnh câu chữ, hãy có hai thứ. Thứ nhất là tiêu chí thế nào là làm tốt, đo được. Thứ hai là vài tình huống thử cố định để so trước và sau. Thiếu hai thứ này, bạn chỉ đang đoán.

Bốn lớp xếp chồng nhau thể hiện vai trò, luật, ví dụ và yêu cầu, đổ xuống một phễu cho ra một khối đầu ra có cấu trúc
Các lớp của một prompt tốt dẫn tới một đầu ra có cấu trúc.

Một yêu cầu tốt gồm những gì

Mình thường viết theo năm phần.

Phần đầu là vai trò và hoàn cảnh, kèm lý do. "Bạn xem thay đổi code cho một API Node.js. Kết quả sẽ do máy đọc, nên chỉ trả JSON" tốt hơn nhiều so với "đừng viết gì khác". Phần hai là luật, nói điều cần làm thay vì chỉ cấm. Phần ba là ví dụ. Ví dụ là cách chắc nhất để chốt định dạng, nhưng chọn ví dụ sát thực tế và có cả ca "không có lỗi", kẻo AI luôn tìm ra đúng một lỗi.

Phần bốn là hình dạng câu trả lời: cho sẵn khung JSON mẫu. Nếu gọi qua API, hãy dùng tính năng đầu ra có cấu trúc để ép đúng khuôn. Phần cuối là dữ liệu cần xử lý, bọc trong thẻ riêng như <diff> hay <code>, tách khỏi lời dặn. Cách này còn giúp AI không nhầm một câu nằm trong dữ liệu thành mệnh lệnh.

Làm sao để AI đừng bịa

AI bây giờ bịa ít hơn trước, nhưng vẫn bịa, nhất là khi bạn hỏi về thứ nó không nhìn thấy. Mình dùng ba lớp chặn.

Lớp đầu là cho phép nó nói "không chắc". Thêm một ô riêng cho nghi vấn và luật "không chắc thì ghi vào đó". Lớp hai là bắt nó trích nguyên văn: mỗi phát hiện phải kèm một dòng copy y nguyên từ dữ liệu. Lớp ba là lớp đáng tin nhất: chính code của bạn kiểm lại. Dòng trích có thật nằm trong dữ liệu không, mức độ có hợp lệ không, kết quả có đọc được không. Hai lớp đầu giảm bịa, lớp ba bắt được phần còn lọt.

Cho bạn nào viết code

Đây là mẫu xem code mình dùng, rút gọn, cùng hàm kiểm. Chỉ cần Python.

REVIEW_PROMPT = """\
<role>You review pull requests for a Node.js REST API.</role>

<rules>
- Report only problems that are visible in the diff below. If you are not sure, put it in "questions".
- Every finding must quote ONE line copied exactly from the diff in "quote".
- severity is one of: "bug", "security", "style". Ignore formatting.
- If there is nothing to report, return {"findings": [], "questions": []}.
</rules>

<output_format>
Return ONLY JSON, no prose:
{"findings": [{"severity": "bug|security|style", "quote": "...", "why": "...", "fix": "..."}],
 "questions": ["..."]}
</output_format>

<diff>
{diff}
</diff>
"""

def validate(raw: str, diff: str) -> dict:
    data = json.loads(raw)                                   # not JSON -> exception
    for i, f in enumerate(data["findings"]):
        if f.get("severity") not in {"bug", "security", "style"}:
            raise BadAnswer(f"finding {i}: bad severity")
        if not f.get("quote") or f["quote"] not in diff:     # anti-hallucination
            raise BadAnswer(f"finding {i}: quote is not in the diff")
    return data

def review(diff, ask_model, retries=1):
    prompt = REVIEW_PROMPT.replace("{diff}", diff)           # replace, not format(): the diff has braces
    for _ in range(retries + 1):
        raw = ask_model(prompt)
        try:
            return validate(raw, diff)
        except (BadAnswer, ValueError) as err:
            prompt += f"\n<previous_answer>{raw}</previous_answer>\n<problem>{err}. Fix it, return only JSON.</problem>\n"
    raise BadAnswer("model never produced a valid answer")

Mình chạy lại hôm 21/10/2026 với một mô hình giả (hàm trả chuỗi cố định) qua 5 tình huống. Đáp án tốt qua ngay. Đáp án có dòng trích bịa bị từ chối, lỗi được đưa lại cho mô hình và lần hai được nhận. Đáp án có câu dẫn trước JSON bị từ chối rồi sửa. Đáp án sai mãi thì báo lỗi chứ không trả rác. Và diff chứa dấu ngoặc nhọn không làm hỏng mẫu. Cả năm đều qua. Cần nói rõ đây chỉ là thử phần kiểm, chưa đo chất lượng của AI thật.

Hai chi tiết nhỏ hay sai. Dùng .replace thay vì str.format, vì diff của bạn có { và }. Và khi thử lại, đưa cho AI đúng lỗi cụ thể thay vì chỉ nói "làm lại".

Một khối đi dọc theo đường sáng giữa hai thanh chắn, những đám mây mờ bên cạnh bị chặn lại không vào được
Luật và bộ kiểm giữ câu trả lời trên đường đi, chặn các chi tiết bịa.

Với việc viết test, mình thêm vào yêu cầu hai luật: "viết lời giải tổng quát, đừng ghi cứng giá trị để vừa với đúng bản code này" và "nếu hàm trông sai hoặc yêu cầu chưa rõ, ghi vào mục <concerns> chứ đừng viết test khoá luôn cái lỗi". Không có hai luật này, AI hay viết test cho "qua" thay vì để kiểm đúng sai. Với tài liệu, luật quan trọng nhất là "điều gì không suy ra được từ code thì ghi TODO: cần xác nhận, đừng đoán". Hai mẫu này mình chưa chạy với AI thật.

Lỗi hay gặp

Có người cứ phát hiện lỗi thì thêm một luật mới vào prompt. Vài tuần sau prompt dài cả trang, và hai luật đá nhau. Hãy đọc lại định kỳ và gộp.

Một lỗi khác là cấm mà không nói cách làm. "Đừng dùng markdown" kém hơn "viết thành các đoạn văn liền mạch". Và lỗi tốn thời gian nhất là chỉnh prompt theo cảm giác. Giữ vài tình huống thử cố định, chỉnh xong chạy lại, so kết quả.

Làm gì tiếp theo

Chọn một việc bạn nhờ AI hay làm nhất. Viết lại yêu cầu theo năm phần ở trên, thêm một bước kiểm bằng code, rồi so với cách cũ trên cùng vài tình huống. Nếu cách mới không tốt hơn thì bạn biết ngay, đó chính là lợi ích của việc đo.

Khi một AI chưa đủ và bạn cần nhiều AI làm chung, các nguyên tắc này vẫn đúng với từng AI nhỏ; cách điều phối nằm ở Giao việc lớn cho nhiều AI cùng làm: cách chia việc để không hỏng. Phần gọi API thật, gồm đầu ra có cấu trúc, nằm ở Dùng Claude API trong sản phẩm của bạn: gọi hàm, hiện chữ dần và tiết kiệm tiền.

Prompt engineeringPythonprompt-engineeringllmcode-reviewtestinghallucination

Nguồn tham khảo

  1. Anthropic: Prompt engineering overview
  2. Anthropic: Prompting best practices
  3. Python docs: json