Sổ tay prompt engineering dành cho lập trình viên
(addyo.substack.com)- Trợ lý lập trình AI giúp nâng cao năng suất của nhà phát triển, nhưng chất lượng đầu ra phụ thuộc rất lớn vào prompt engineering
- Để có được kết quả hiệu quả, cần tuân thủ các nguyên tắc như ngữ cảnh phong phú, mục tiêu cụ thể, ví dụ minh họa, gán vai trò, cải tiến lặp lại
- Bài viết cung cấp các mẫu thiết kế prompt và ví dụ theo từng tác vụ phát triển chính như debug, refactor, triển khai tính năng mới
- Prompt tốt cần chứa thông tin cụ thể như mục tiêu, ngôn ngữ, môi trường, thông báo lỗi, ví dụ đầu vào/đầu ra
- Đây là phương pháp thiết kế prompt mà cả kỹ sư mới cũng có thể làm theo, kèm so sánh phản hồi AI thực tế và nhận xét
Tổng quan: Tầm quan trọng của prompt engineering thành công
- Gần đây, các nhà phát triển dùng AI coding assistant để tăng tốc quy trình làm việc, từ tự động hoàn thành hàm, sửa lỗi cho đến viết cả module
- Tuy nhiên, chất lượng phản hồi của AI bị chi phối quyết định bởi chất lượng của prompt
- Prompt tốt sẽ dẫn dắt tới các giải pháp mã rõ ràng và sáng tạo, còn prompt mơ hồ hoặc sơ sài sẽ dẫn tới những câu trả lời hạn chế và vô nghĩa
- Playbook này tổng hợp theo hướng thực tiễn cách thiết kế prompt hiệu quả có thể áp dụng cho các tác vụ phát triển hằng ngày
Các nguyên tắc cơ bản của prompt code hiệu quả
- Cung cấp ngữ cảnh phong phú: AI không biết trước dự án hay ý đồ của bạn, vì vậy hãy nêu rõ mọi thông tin liên quan như ngôn ngữ sử dụng, framework, thư viện, thông báo lỗi, mục đích của đoạn mã
- Đưa ra mục tiêu hoặc câu hỏi rõ ràng: Thay vì hỏi mơ hồ như “Tại sao code không chạy?”, hãy mô tả rõ kết quả mong muốn và tình trạng hiện tại
- Chia nhỏ tác vụ phức tạp: Với các công việc như phát triển tính năng lớn, đừng yêu cầu tất cả cùng lúc mà hãy tách thành các bước nhỏ và yêu cầu dần dần
- Bao gồm ví dụ đầu vào/đầu ra hoặc hành vi mong đợi: Nếu đưa ví dụ đầu vào, đầu ra hoặc hành vi thực tế, mức độ hiểu của AI sẽ tăng lên đáng kể (“few-shot prompting”)
- Tận dụng vai trò (persona): Gán vai trò có trách nhiệm như “review code như một senior React developer” hoặc “tối ưu như một chuyên gia hiệu năng” để nâng cao chất lượng phản hồi của AI
- Cải tiến lặp lại theo hội thoại: Dựa trên câu trả lời đầu tiên của AI, tiếp tục yêu cầu bổ sung hoặc chỉnh sửa để dần đạt kết quả mong muốn
- Giữ tính nhất quán của code: AI sẽ tham chiếu style code, cách đặt tên và chú thích, nên hãy luôn duy trì code rõ ràng và nhất quán
Mẫu prompt cho debug
Cách thiết kế prompt debug có hệ thống
- Mô tả rõ vấn đề và triệu chứng: Cung cấp đầy đủ thông tin như ngôn ngữ, mục đích của chức năng, hành vi mong đợi, thông báo lỗi thực tế và đoạn code
- Yêu cầu phân tích theo từng bước hoặc từng dòng: Với lỗi logic hoặc bug khó thấy, hãy yêu cầu “theo dõi biến từng dòng” hoặc giải thích từng phần code để xác định nguyên nhân
- Dùng code tái hiện tối thiểu: Thay vì đưa cả codebase phức tạp, hãy trích xuất phần code nhỏ nhất có thể gây lỗi để tập trung chẩn đoán vấn đề
- Đặt câu hỏi trực tiếp và yêu cầu tiếp nối: Hãy yêu cầu rõ ràng và lặp lại được như “Bug xảy ra ở đâu?” hoặc “Hãy đưa ra code đã sửa”
Ví dụ: prompt tệ vs. prompt cải thiện
Ví dụ code có vấn đề
function mapUsersById(users) {
const userMap = {};
for (let i = 0; i <= users.length; i++) {
const user = users[i];
userMap[user.id] = user;
}
return userMap;
}
const result = mapUsersById([{ id: 1, name: "Alice" }]);
Prompt tệ:
“Vì sao hàm mapUsersById không hoạt động?”
- Phản hồi của AI: đưa ra các suy đoán mơ hồ như “Mảng có thể rỗng” hoặc “user có thể không có id”
- Chỉ nhận được lời khuyên chung chung do thiếu ngữ cảnh và thiếu rõ ràng
Prompt cải thiện:
“Hàm mapUsersById cần ánh xạ mảng người dùng theo id, nhưng khi nhập [ {id: 1, name: "Alice"} ] thì xảy ra lỗi TypeError: Cannot read property 'id' of undefined. Code như sau: [kèm code]. Kết quả mong đợi là { "1": ... }. Nguyên nhân của hiện tượng này là gì và cách khắc phục ra sao?”
- Phản hồi của AI: chỉ ra điều kiện vòng lặp (i <= users.length) vượt phạm vi nên ở lần lặp cuối phát sinh undefined, và đề xuất sửa thành i < users.length
- Đưa ra lời giải chính xác nhờ có ngữ cảnh cụ thể, thông báo lỗi và hành vi mong đợi
Chiến lược prompt debug bổ sung
- Yêu cầu liệt kê các nguyên nhân có thể gây bug (“Các nguyên nhân có thể gây TypeError là gì?”)
- Tự giải thích logic hoạt động của code rồi yêu cầu kiểm tra (“Giải thích của tôi có đúng không, hãy tìm vấn đề giúp tôi”)
- Yêu cầu test case cho tình huống bất thường (“Chỉ đề xuất 2 đầu vào có thể khiến hàm này thất bại”)
- Gán vai trò người review code kỹ tính (“Hãy review đoạn code này và giải thích các vấn đề cùng điểm cần cải thiện”)
Mẫu prompt cho refactor/tối ưu hóa
Nêu rõ mục tiêu cải thiện
- “Hãy refactor” là quá mơ hồ, vì vậy hãy nêu mục tiêu cụ thể như tăng khả năng đọc, hiệu năng, khả năng bảo trì, loại bỏ trùng lặp code
- Cung cấp đầy đủ toàn bộ code (hoặc ngữ cảnh cần thiết), môi trường, ngôn ngữ và phiên bản framework
- Đồng thời yêu cầu giải thích các thay đổi (“Hãy cho tôi code và các điểm đã cải thiện”)
- Dùng gán vai trò như “với tư cách chuyên gia TypeScript, hãy làm theo best practice hiện đại” để nâng chất lượng kỳ vọng
Ví dụ: so sánh prompt refactor
Code gốc
(có các vấn đề như fetch trùng lặp, cấu trúc dữ liệu kém hiệu quả, v.v.)
async function getCombinedData(apiClient) {
// Fetch list of users
const usersResponse = await apiClient.fetch('/users');
if (!usersResponse.ok) {
throw new Error('Failed to fetch users');
}
// ... (phần sau lược bỏ)
}
Prompt mơ hồ
“Hãy refactor hàm getCombinedData”
- AI có thể tự ý thay đổi như fetch song song, gộp thông báo lỗi, v.v. (vì không có yêu cầu nên hành vi khó dự đoán)
Prompt nêu rõ mục tiêu
“Hãy loại bỏ trùng lặp, cải thiện hiệu năng, chạy song song hai lần fetch, tách riêng thông báo lỗi và cải thiện cách kết hợp dữ liệu theo hướng hiệu quả. Kèm cả chú thích và giải thích các điểm đã cải thiện.”
- Phản hồi của AI: refactor rõ ràng theo mục tiêu, gồm fetch song song, phân biệt lỗi, áp dụng cấu trúc map hiệu quả cùng phần giải thích chi tiết
Mẹo refactor bổ sung
- Yêu cầu theo từng bước (“cải thiện độ dễ đọc → tối ưu thuật toán” theo thứ tự)
- Yêu cầu cách tiếp cận khác (“Hãy triển khai lại theo phong cách functional”)
- Yêu cầu theo kiểu code + giải thích để học và dùng như tutorial
- Yêu cầu bổ sung test cho đoạn code kết quả
Mẫu prompt cho triển khai tính năng mới
Dẫn dắt tạo code theo từng bước
- Trước hết hãy đưa mô tả ở mức cao (bạn muốn tạo tính năng gì), sau đó chia nhỏ dần theo từng bước
- Truyền đạt ngữ cảnh môi trường làm việc như code tương tự đã có, pattern của dự án, thư viện đang dùng
- Có thể dùng chú thích hoặc TODO như một phần của prompt để dẫn luồng viết code của AI trực tiếp trong IDE
- Cung cấp ví dụ đầu vào/đầu ra hoặc test case để đặt kỳ vọng kết quả rõ ràng
- Nếu kết quả đầu tiên chưa tốt, hãy ngay lập tức bổ sung những điểm cần cải thiện cụ thể hoặc style code mong muốn rồi yêu cầu lại theo vòng lặp
Ví dụ: tạo component React ProductList
“Hãy tạo một React functional component tên là ProductList. Component này lấy mảng sản phẩm từ /api/products và hiển thị thành danh sách; khi nhập tên sản phẩm vào ô input thì lọc không phân biệt hoa thường. Đồng thời cần có xử lý loading và error trong quá trình fetch.”
- Phản hồi của AI: bao gồm fetch dữ liệu bằng useState, useEffect, xử lý input, lọc dữ liệu, cùng UI cho lỗi và trạng thái loading
- Nếu dự án dùng custom hook, có thể tiếp tục ra lệnh như “Hãy refactor để dùng hook useProducts()”
Ví dụ nâng cao prompt trong thực tế
- Có thể yêu cầu mở rộng tính năng dần dần như “Thêm chức năng sắp xếp: cần có dropdown A-Z, Z-A”
- Chia luồng triển khai thành từng bước và dùng prompt khác nhau cho từng bước để duy trì chất lượng và tính nhất quán của code
Kết luận
- Để khai thác tối đa tiềm năng của AI coding assistant, thiết kế prompt là năng lực cốt lõi
- Để viết prompt thành công, cần luôn ghi nhớ ngữ cảnh cụ thể, mục tiêu, ví dụ, phản hồi lặp lại và gán vai trò nhằm tạo ra kết quả hiệu quả
- Hãy xem AI như một lập trình viên mới hoặc người review code, hướng dẫn thật chi tiết theo đúng định hướng mong muốn và nâng dần chất lượng là chìa khóa thành công
1 bình luận
Ý kiến trên Hacker News
Theo kinh nghiệm của tôi thì thực ra chỉ có ba kỹ thuật prompt engineering thật sự
In Context Learning (đưa ví dụ trong ngữ cảnh, tức kiểu one-shot hoặc few-shot, đối lập với zero-shot)
Chain of Thought (chỉ dẫn để suy nghĩ theo từng bước)
Structured output (ví dụ chỉ định rõ định dạng đầu ra như JSON)
Có lẽ cũng có thể thêm Role Prompting mà bài này nhắc tới vào đây
Còn RAG thì tôi xếp riêng vì đó là cách mô hình tóm tắt ngữ cảnh được cung cấp
Cuối cùng thì phần còn lại chỉ là tóm lược cách yêu cầu điều mình muốn bằng ngôn ngữ rõ ràng và đơn giản
Trong prompt, ngữ cảnh là yếu tố quan trọng nhất
Ví dụ bắt đầu bằng Typescript rồi hỏi một câu về data science thì nó trả lời không tốt
Nhưng hỏi y hệt bằng Python thì kết quả tốt hơn hẳn
Vì LLM vẫn chưa giỏi chuyển giao kiến thức giữa các domain, nên việc thiết lập ngữ cảnh đúng mục đích là rất quan trọng
Cá nhân tôi cũng thấy role prompting là cách làm không có nhiều ý nghĩa
Có thể thời GPT-3 là vậy, nhưng đa số LLM giờ đã hiểu vai trò "chuyên gia" rồi
Tôi nghĩ việc quá sa đà vào "prompt engineering" chỉ là đang tự đánh lừa mình
Cứ truyền đạt yêu cầu thật rõ, thêm ví dụ nếu cần, kiểm tra kết quả hoặc reasoning trace, rồi nếu chưa ra đúng ý thì chỉnh lại và thử tiếp
Nếu thử vài lần vẫn không có câu trả lời thì chọn cách tự reasoning bằng đầu óc của mình thay vì AI
Có ý kiến cho rằng vấn đề là nhiều người "cố nhồi mọi thứ vào một prompt duy nhất"
Thay vì ném một yêu cầu khổng lồ vào một lần, họ đề xuất chia thành nhiều prompt với ngữ cảnh nhỏ hơn, mỗi cái có đầu ra có cấu trúc rõ ràng rồi nối chúng lại với nhau
Mỗi prompt tập trung vào mục tiêu và ví dụ riêng, tránh quá tải ngữ cảnh
Như vậy thì 3 phương pháp cốt lõi nói trên cũng được áp dụng một cách tự nhiên
Liên quan đến cách thứ ba (Structured output), tôi và đồng nghiệp đã có nghiên cứu trường hợp áp dụng trong lĩnh vực khoa học
Liên kết bài báo
Nhân tiện, đội chúng tôi dựa vào fine-tuning nhiều hơn là prompt engineering
Cách few-shot prompt không hiệu quả trong trường hợp của chúng tôi
Tôi thường có cảm giác khi prompt quá dài hoặc quá phức tạp thì năng lực nhận thức của mô hình lại giảm đi
Prompt phức tạp có thể tạo cảm giác đang kiểm soát tốt hơn, nhưng trên thực tế chưa chắc đó là lợi thế
Vì vậy kiểu sử dụng của tôi tự nhiên hội tụ về hướng dùng prompt rất đơn giản, tối giản rồi lặp lại chỉnh sửa vài lần
Tôi cũng bắt đầu tiếp cận hoàn toàn theo cách đó
Cách này cũng tốt về mặt chi phí
Tôi đã quá nhiều lần dùng agent rồi đốt $30 mà codebase bị rối tung hoặc quay về đúng như code cũ
Tôi cũng muốn cảnh báo rằng nếu để AI viết quá nhiều code cho dự án của mình thì về sau phần code đó sẽ không đọng lại tốt trong đầu mình và cũng khó bảo trì hơn
Cũng có cơ sở cho thấy nếu nhập prompt bằng thuật ngữ chuyên môn thì hiệu năng tốt hơn
Nhìn chung, trong môi trường nơi người ta nói bằng ngôn ngữ đời thường thì độ chính xác giảm, còn từ vựng của lĩnh vực chuyên biệt lại dẫn tới câu trả lời đáng tin cậy hơn
Dữ liệu huấn luyện cũng phản ánh phân bố như vậy
Tôi cũng có trải nghiệm tương tự
Nhưng nhìn các system prompt của agent thì nhiều cái dài và phức tạp khủng khiếp, nên tôi thấy khá thắc mắc
Tôi tò mò không biết những prompt như vậy thực sự hoạt động thế nào
Liên kết ví dụ system prompt
Với một số tác vụ, đồng nghiệp của tôi đã dùng prompt rất dài dòng
Trong lúc tích hợp, tôi thêm CRUD operation và thử rút ngắn nó xuống kiểu "phân tích việc này từ góc nhìn của <chức danh>"
Kết quả là hai bên gần như giống nhau, thậm chí prompt dài còn có hiện tượng lặp lại nguyên một số câu trong đầu ra
Bản thân kết quả thì ổn, nhưng rốt cuộc mô hình (gemini 2.5) chỉ rút ra thông tin quan trọng rồi lại hòa cả phần không cần thiết vào kết quả
Nghĩa là, ít nhất với bài toán này, tôi không thấy sự dài dòng tạo ra ảnh hưởng thú vị nào lên "cách suy nghĩ" của mô hình
Tôi cũng đi đến kết luận tương tự, nhưng vẫn thắc mắc nên hiểu thế nào về các ví dụ dùng prompt dài mà các AI lab cung cấp
Ví dụ system prompt của Anthropic
Tôi nghĩ cái gọi là "prompt engineering" thực ra không tồn tại như một thứ riêng biệt
Từ bao giờ việc viết câu có ý nghĩa đàng hoàng lại được gọi là engineering nhỉ
Tôi thấy nó còn quá tay hơn cả "software engineering"
Nhưng điều đáng tiếc là về sau thứ này có thể vẫn nổi lên thành một nghề (prompt engineer), như thể một loại năng lực đặc biệt trong việc viết câu
Thực ra "viết câu có ý nghĩa đàng hoàng" là chuyện thay đổi theo vô số biến số
Trong thực tế, nếu bao gồm cả testing, quản lý, logging và version control thì nó không còn là cảm tính đơn thuần mà trở thành engineering
Những yếu tố có cấu trúc như thứ tự nhất định/phong cách/diễn giải lại vấn đề là rất quan trọng
Khi làm việc với các family model có nhiều tham số, các mô hình API mỗi lần nâng version đều cần kiểm tra tương thích với prompt cũ
Những việc kiểm tra và test đó cũng là một phần của quy trình prompt engineering
Có ý kiến cho rằng nhiều người vì ác cảm với xu hướng/hype nên lại bỏ sót bản chất vấn đề
Nếu anh barista ở quán gần nhà tôi tự thêm vào tên mình là coffee engineer thì nghe có khi còn đáng tin hơn
Có lẽ vì nghiện thuật toán mà người tiêu dùng dạo này còn đang suy giảm cả khả năng đọc hết một câu
Tôi nghĩ cũng không cần lo chuyện tuyển dụng "prompt engineer"
Đám AI sloperators đang rất cố làm cho công việc của mình trông oách hơn thôi
Theo kinh nghiệm của tôi, với những vấn đề LLM không giải được thì có "engineering" prompt đến đâu cũng thường vô ích
Thường chỉ còn cách tách thành các bài toán con rồi để nó làm dần từng phần
Nếu ai có trải nghiệm ngược lại thì tôi muốn nghe ví dụ
Một phần quan trọng của việc dùng LLM là cảm nhận được nên chia bài toán như thế nào
Cần khả năng nhận biết khi nào nên chia nhỏ, chia như thế nào, và khi nào nên cứ giao thẳng cho nó
Như bài viết cũng nói, loại bí quyết này rất quan trọng
Sau này có lẽ cũng sẽ có nhiều cách tổ chức code/comment tốt hơn để cải thiện tương tác với LLM
Bản thân LLM cũng sẽ dần tiến hóa theo hướng này, thậm chí có thể đề xuất cả cách chia nhỏ vấn đề
Mục tiêu của prompt engineering là để nhận được lời giải tốt hơn, nhanh hơn, dưới đúng định dạng mong muốn
Xét cho cùng thì ta vẫn muốn mô hình tự biết trả lời, nhưng thực tế là ngay cả câu hỏi cũng cần được tối ưu hóa
Khi viết prompt, do thói quen lâu năm nên tôi vẫn thấy hơi lạ khi phải ra lệnh bằng ngôn ngữ tự nhiên
Cảm giác như lẽ ra phải viết nó kiểu tham số chính xác hoặc như một câu SQL query
Việc chỉ dẫn cho công cụ như đang trò chuyện cũng thấy khá lạ
Dù vậy, việc nó trở thành một công cụ hiểu chỉ dẫn bằng ngôn ngữ tự nhiên đúng là đã nâng mức độ tiếp cận lên đáng kể
Nhưng dù thế, tôi vẫn thấy hơi buồn cười khi bản thân lại đang viết prompt như thể đang nói chuyện với con người
Dạo này có rất nhiều thứ như guide về prompt
Nhưng tôi nghĩ thực ra cũng không cần thiết lắm
Chỉ cần tự dùng công cụ, trở nên quen thuộc và học cách dùng nó thì tự nhiên sẽ biết prompt nào là tốt
Nó khá giống thời xưa Google nổi như cồn và ai cũng FOMO
Người ta bảo không mua sách liên quan thì sẽ tụt hậu như người nguyên thủy, nhưng thực tế đây là lĩnh vực đơn giản đến mức có thể nắm trong một ngày nên không cần suy nghĩ quá phức tạp
Dĩ nhiên vẫn có những người thật sự được guide hoặc video mẹo vặt giúp đỡ nhiều
Nhiều người không chủ động tự cải thiện, nhưng chỉ cần xem guide hoặc video của cao thủ một lần thôi cũng có thể lên tay
Bản thân tôi cũng thường xuyên học được mẹo từ cách người khác dùng hoặc từ trải nghiệm của cộng đồng
Chỉ tự luyện một mình thì có giới hạn trong việc học được những mẹo như vậy
Hồi trước cũng có công thức kiểu “As a [role], I want to [task] so I can [objective]” như trong “hướng dẫn viết user story”
Dù là người giỏi hay người mới thì đa số vẫn cần hỗ trợ để truyền đạt yêu cầu cho rõ ràng
Dù là developer rất giỏi thì với yêu cầu phi cấu trúc vẫn có thể mắc lỗi hoặc hiểu sai
Việc tham khảo cách người khác tạo ra năng suất với công cụ này cũng khá hữu ích
Nhờ đó có thể phát hiện những ý tưởng mà mình đã bỏ lỡ
Học được dù chỉ một chút từ trải nghiệm người khác trước khi tự mình thử hết bằng trial-and-error vẫn hiệu quả hơn
Với cá nhân tôi, người không có thời gian tự thử mọi thứ, thì những chia sẻ trải nghiệm như vậy thực sự là thông tin rất đáng quý
Chắc chắn có những mẹo không dễ nhận ra
Ví dụ như kinh nghiệm rằng trong prompt có thể bỏ hết các từ lịch sự như “please”
Hồi học cao học ngành khoa học máy tính khá lâu trước đây, tôi đã áp dụng rất tốt quy trình kiểm chứng học trong môn Science of programming vào việc viết prompt cho data engineering
Ví dụ: “cho input(…) và giả định(…), hãy viết mã spark thỏa mãn post-condition(…)”
Khi ghi rõ đầu vào, giả định và điều kiện kết quả thì có thể tạo ra code tốt
Tài liệu tham khảo
Tôi thấy việc quá hăng với prompt engineering là hơi quá đà
Giờ chỉ cần copy-paste code hay lỗi rồi ném một plain question là phần lớn model hiện nay cũng tự xử lý khá tốt
Tôi không thấy cần phải viết vòng vo quá mức
Vài ngày trước Sergey Brin nói rằng một sự thật không hay được nhắc trong cộng đồng AI là "đe dọa về mặt thể chất sẽ khiến hiệu năng mô hình tốt hơn"
Bài viết liên quan
Điều đó làm tôi nhớ đến câu đùa của một lập trình viên vibe pro trên YouTube “Programmers are also human”, người luôn kết thúc lệnh cho LLM bằng câu “.. nếu không thì vào tù”
Thế nên mới tự hỏi phải chăng Google đã lặng lẽ bỏ khẩu hiệu "Don't Be Evil"
Gọi việc viết prompt là "engineering" nghe có cảm giác rất thiếu nghiêm túc
Có một phép so sánh vui tôi từng nghe hồi trào lưu prompt "engineering" nổi lên
Rốt cuộc tranh cãi này cứ lặp đi lặp lại mỗi lần người ta nói về software engineering
Có lẽ vì trí tưởng tượng chỉ dừng ở mức dùng giao diện chat để xin ảnh mèo
Trong thực tế còn có prompt dùng cho API và workflow tự động hóa, nên nó nhiều hơn thế
Ở Mỹ cũng có chức danh "sales engineer", mà theo trải nghiệm của tôi thì nhiều người trong số đó hoàn toàn không biết sản phẩm họ bán hoạt động ra sao
IT là nơi mà từ ngữ và ý nghĩa của chúng tan biến
Đến mức đôi khi phải tự hỏi liệu từ ngữ có nhất thiết phải giữ ý nghĩa gốc của nó hay không