Kỹ thuật nâng cao: few-shot, chain-of-thought và đầu ra có cấu trúc
Mục tiêu học tập
Sau bài này, bạn có thể:
- Phân biệt được ba kỹ thuật few-shot, chain-of-thought và đầu ra có cấu trúc (structured output) theo nguyên lý hoạt động, không chỉ theo mẹo dùng.
- Viết được một bộ ví dụ mẫu (few-shot) nhất quán về định dạng và phủ được các trường hợp biên.
- Quyết định đúng khi nào bật suy luận từng bước (chain-of-thought) và khi nào nó chỉ làm nhiễu đầu ra.
- Đặc tả được một lược đồ đầu ra (output schema) đủ chặt để dùng tiếp trong quy trình tự động.
- Chọn đúng kỹ thuật cho từng loại bài toán trong capstone cá nhân của bạn.
Ôn tập nhanh
Bài trước đã chốt một ý: prompt là một bản đặc tả, và năm thành phần (vai trò, ngữ cảnh, nhiệm vụ, định dạng, tiêu chí) là năm khe thông tin tối thiểu để thu hẹp không gian đầu ra. Ba kỹ thuật hôm nay không phải khung mới. Chúng là ba nút vặn gắn vào các khe đã có: ví dụ mẫu nằm ở khe ngữ cảnh, suy luận từng bước nằm ở khe nhiệm vụ, và lược đồ đầu ra nằm ở khe định dạng.
[!NOTE] Nguyên tắc chọn kỹ thuật: chỉ thêm kỹ thuật khi nó giải quyết đúng điểm nghẽn. Thêm cả ba vào một prompt đơn giản thường làm kết quả tệ hơn.
Lý thuyết
1. Few-shot: dạy bằng mẫu thay vì bằng lời
Mô hình ngôn ngữ lớn học bằng cách bắt chước phân phối của những gì nó thấy trong ngữ cảnh. Vì vậy, đưa vài cặp vào-ra mẫu thường hiệu quả hơn mô tả quy ước bằng tính từ ("giọng chuyên nghiệp", "ngắn gọn") vì mô tả bằng lời vẫn còn mơ hồ, còn ví dụ thì không.
Một bộ ví dụ mẫu dùng được cần bốn điều kiện:
- Cùng một định dạng ở mọi ví dụ (cùng thứ tự trường, cùng kiểu đánh dấu).
- Nhãn nhất quán: hai ví dụ giống nhau về bản chất mà khác nhãn sẽ khiến đầu ra dao động.
- Phủ trường hợp biên, không chỉ trường hợp dễ. Ví dụ: một ghi chú vừa là ý tưởng vừa là việc cần làm.
- Số lượng vừa phải: 3 đến 5 ví dụ là điểm cân bằng giữa độ rõ quy ước và chi phí ngữ cảnh.
Few-shot không sửa được lỗ hổng kiến thức. Nếu mô hình không biết một quy tắc nội bộ của tổ chức bạn, ví dụ mẫu chỉ giúp nó đoán đúng hơn, không giúp nó biết.
2. Chain-of-thought: tách suy luận khỏi kết luận
Suy luận từng bước (chain-of-thought, CoT) là yêu cầu mô hình viết ra các bước trung gian trước khi kết luận. Nó có tác dụng khi chất lượng đầu ra phụ thuộc vào một chuỗi ràng buộc: tính toán nhiều bước, so sánh nhiều phương án, kiểm tra một kế hoạch có thỏa mọi điều kiện hay không.
CoT không phù hợp với việc tra cứu, viết lại, đổi giọng văn hay tóm tắt. Ở những việc đó, phần suy luận chỉ là văn bản thừa, làm chậm và tạo cảm giác chắc chắn giả.
Một điểm cần nhớ: CoT tổ chức lại suy luận, nó không bổ sung kiến thức. Một chuỗi lập luận nghe rất hợp lý vẫn có thể dựa trên một giả định sai. Vì vậy, khi dùng CoT, hãy tách trường suy luận khỏi trường kết luận trong đầu ra để bạn kiểm tra được phần nào.
3. Đầu ra có cấu trúc: biến văn bản thành dữ liệu
Đầu ra có cấu trúc nghĩa là bạn buộc mô hình trả về đúng một lược đồ (schema) định trước: tên trường, kiểu dữ liệu, tập giá trị hợp lệ (enum), quy ước cho giá trị thiếu. Đây là kỹ thuật bắt buộc khi đầu ra sẽ được đưa vào bước tiếp theo của quy trình (bảng tính, công cụ, script), thay vì được đọc bởi người.
Ba quy ước nên có trong mọi lược đồ:
- Enum cho trường có tập giá trị hữu hạn, thay vì để mô hình tự do đặt nhãn mới.
- Giá trị
nullkhi không chắc, kèm lý do. Câu "nếu không chắc, ghinullthay vì đoán" là một trong những câu có tỉ lệ lợi ích trên chi phí cao nhất trong toàn bộ prompt. - Một ví dụ về đúng hình dạng đầu ra, đặt trong khối mã, để mô hình thấy cấu trúc chứ không phải suy ra từ mô tả.
4. Chọn kỹ thuật theo loại bài toán
flowchart TD
Task["🎯 Bài toán"] --> Reason{"Phụ thuộc chuỗi suy luận?"}
Reason -->|Có| CoT["🧠 Chain-of-thought"]
Reason -->|Không| Simple["✍️ Prompt trực tiếp"]
Task --> Machine{"Đầu ra cho máy đọc tiếp?"}
Machine -->|Có| Schema["📦 Structured output"]
Task --> Pattern{"Cần bắt chước quy ước riêng?"}
Pattern -->|Có| FS["📚 Few-shot"]
| Dấu hiệu bài toán | Kỹ thuật nên dùng |
|---|---|
| Có quy ước riêng khó diễn đạt bằng lời | Few-shot |
| Cần tính, so sánh, kiểm tra ràng buộc nhiều bước | Chain-of-thought |
| Đầu ra chảy vào bước xử lý tự động | Structured output |
| Việc đơn giản, một bước, đã rõ nghĩa | Prompt trực tiếp |
Ba kỹ thuật này cộng hưởng được: mỗi ví dụ mẫu có thể chứa một trường suy luận ngắn và một trường kết luận JSON. Đó là dạng prompt mạnh nhất cho các tác vụ lặp lại hằng ngày.
Ví dụ có hướng dẫn
Ví dụ 1: phân loại ghi chú nghiên cứu. Điểm nghẽn là quy ước riêng của bạn (một ghi chú có thể là "ý tưởng", "việc cần làm" hoặc "trích dẫn"). Lời mô tả sẽ mơ hồ, nên dùng few-shot kèm lược đồ.
Nhiệm vụ: phân loại mỗi ghi chú và trích xuất trường.
Ví dụ 1:
Vào: "Đọc bài về RAG trước thứ Sáu"
Ra: {"loai": "viec_can_lam", "chu_de": "nghien_cuu", "han": "thu_sau", "do_tin_cay": "cao"}
Ví dụ 2:
Vào: "Nếu giả định người dùng không đọc hết tài liệu thì tóm tắt hai tầng sẽ hữu ích"
Ra: {"loai": "y_tuong", "chu_de": "viet", "han": null, "do_tin_cay": "trung_binh"}
Ví dụ 3 (biên):
Vào: "Ý này hay, mà nhớ hỏi lại anh Minh"
Ra: {"loai": "y_tuong", "chu_de": "khac", "han": null, "do_tin_cay": "thap"}
Quy tắc: "loai" chỉ nhận một trong ["y_tuong", "viec_can_lam", "trich_dan"].
Không chắc thì "do_tin_cay": "thap" và ghi lý do vào trường "ghi_chu".
Vì sao prompt này chạy được: định dạng giống nhau ở cả ba ví dụ, ví dụ thứ ba xử lý đúng ca biên (vừa ý tưởng vừa việc), enum đóng tập nhãn, và có quy ước cho trường hợp không chắc.
Ví dụ 2: lập kế hoạch tuần. Điểm nghẽn là ràng buộc (quỹ thời gian, thứ tự phụ thuộc), nên cần CoT, rồi mới đến lược đồ.
Trước khi trả lời, hãy:
1. Liệt kê các việc và ước lượng giờ cho từng việc.
2. Kiểm tra tổng giờ có vượt quỹ 12 giờ hay không.
3. Chỉ ra việc nào phải xong trước để việc khác chạy được.
Sau đó trả về JSON: {"lich": [{"viec": ..., "gio": ..., "phu_thuoc": [...]}], "tong_gio": ..., "canh_bao": ...}
Bước 2 chính là chỗ CoT tạo giá trị: nếu bỏ đi, mô hình rất dễ trả về một kế hoạch 18 giờ cho quỹ 12 giờ mà không hề nhận ra.
Luyện tập có hướng dẫn
Bài tập neo vào capstone của bạn: quy trình AI cá nhân cho nghiên cứu, lập kế hoạch và viết nội dung.
Bài 1. Chọn kỹ thuật. Với mỗi tác vụ, chọn kỹ thuật chính và giải thích một dòng. a) Đổi giọng một đoạn văn sang giọng trang trọng. b) Kiểm tra một lịch trình có vượt quỹ thời gian hay không. c) Chuyển danh sách tài liệu đọc thành bảng có cột chủ đề, độ ưu tiên, hạn.
Bài 2. Sửa bộ ví dụ mẫu hỏng. Bộ ví dụ của bạn có: ví dụ 1 nhãn viec_can_lam cho "Viết nháp mở bài", ví dụ 2 nhãn y_tuong cho "Viết nháp mở bài". Hãy nêu lỗi và cách sửa.
Bài 3. Đặc tả lược đồ. Viết lược đồ JSON cho "ghi chú nghiên cứu" của riêng bạn, có ít nhất một trường enum, một trường null được phép, và một trường suy luận ngắn.
Xem gợi ý đáp án
Bài 1. a) Prompt trực tiếp: một bước, không có chuỗi ràng buộc, không cần lược đồ. b) Chain-of-thought: cần cộng và so sánh với ngưỡng. c) Structured output, có thể kèm few-shot nếu quy ước phân loại chủ đề của bạn khó diễn đạt.
Bài 2. Lỗi là nhãn mâu thuẫn cho cùng một đầu vào, mô hình sẽ học cả sự mâu thuẫn. Cách sửa: chọn một nhãn đúng theo quy tắc của bạn, ghi rõ quy tắc đó thành một dòng trong prompt, và thêm một ví dụ biên để làm rõ ranh giới giữa "việc cần làm" và "ý tưởng".
Bài 3. Ví dụ tối thiểu:
{
"loai": "y_tuong | viec_can_lam | trich_dan",
"chu_de": "nghien_cuu | viet | khac",
"han": "chuỗi ngày hoặc null",
"suy_luan": "một câu giải thích vì sao chọn nhãn này",
"do_tin_cay": "cao | trung_binh | thap"
}
Góc chuyên gia
- Quy tắc ngón tay cái: bắt đầu bằng prompt trực tiếp, chỉ thêm kỹ thuật khi bạn chỉ ra được điểm nghẽn cụ thể mà kỹ thuật đó giải quyết.
- Lỗi phổ biến nhất: dùng CoT cho mọi việc. Với tác vụ một bước, phần suy luận chỉ làm đầu ra dài hơn và khó kiểm tra hơn.
- Lỗi thứ hai: viết lược đồ quá nhiều trường. Mỗi trường thêm vào là một cơ hội để mô hình bịa. Chỉ giữ trường mà bước sau thực sự dùng.
- Mẹo về ví dụ mẫu: đặt ví dụ khó nhất ở vị trí gần câu hỏi thật nhất, vì mô hình chịu ảnh hưởng mạnh hơn từ phần ngữ cảnh gần cuối.
- Mẹo về kiểm chứng: trường
suy_luanvàdo_tin_caylà công cụ để bạn chọn mẫu nào cần đọc lại bằng mắt, thay vì đọc lại tất cả.
[!WARNING] Few-shot và CoT đều làm đầu ra trông chắc chắn hơn mà không đảm bảo đúng hơn. Một chuỗi suy luận trôi chảy là dấu hiệu của hình thức tốt, không phải của tính đúng.
Tóm tắt và bước tiếp theo
Ba kỹ thuật, ba điểm nghẽn khác nhau: few-shot xử lý quy ước khó diễn đạt bằng lời, chain-of-thought xử lý bài toán phụ thuộc chuỗi ràng buộc, structured output xử lý yêu cầu đầu ra phải dùng được cho máy. Chúng gắn vào các khe đã có của khung năm thành phần, và chỉ nên bật khi đúng điểm nghẽn.
Bài học tiếp theo mở đúng câu hỏi còn treo ở đây: làm sao biết đầu ra của ba kỹ thuật này là đúng. Chúng ta sẽ dựng vòng lặp đánh giá (evaluation loop) và các bước kiểm chứng để biến những gì vừa học thành một quy trình có thể tin được.
Few-shot dạy mô hình bằng {{c1::ví dụ mẫu}} thay vì chỉ bằng lời hướng dẫn.
Chain-of-thought phù hợp với bài toán phụ thuộc {{c2::chuỗi suy luận nhiều bước}}.
Đầu ra có cấu trúc nên khai báo {{c3::enum}} cho trường có tập giá trị hữu hạn.
Khi không chắc, nên yêu cầu mô hình trả về {{c4::null}} thay vì đoán.
Chain-of-thought không bổ sung {{c5::kiến thức}} cho mô hình, nó chỉ tổ chức lại suy luận.
[
{ "front": "Few-shot là gì?", "back": "Đưa vài cặp ví dụ vào-ra để mô hình bắt chước quy ước, thay vì mô tả quy ước bằng lời." },
{ "front": "Số ví dụ mẫu hợp lý cho một prompt là bao nhiêu?", "back": "Khoảng 3 đến 5 ví dụ, đủ để phủ cả trường hợp dễ và trường hợp biên." },
{ "front": "Điều kiện bắt buộc của một bộ ví dụ mẫu tốt?", "back": "Mọi ví dụ cùng một định dạng và nhãn nhất quán với nhau." },
{ "front": "Chain-of-thought phù hợp nhất khi nào?", "back": "Khi chất lượng đầu ra phụ thuộc vào một chuỗi suy luận hoặc ràng buộc nhiều bước." },
{ "front": "Khi nào KHÔNG nên dùng chain-of-thought?", "back": "Với việc một bước như tra cứu, viết lại, đổi giọng văn hoặc tóm tắt." },
{ "front": "Chain-of-thought có bổ sung kiến thức cho mô hình không?", "back": "Không. Nó chỉ tổ chức lại suy luận; giả định sai vẫn dẫn tới kết luận sai." },
{ "front": "Đầu ra có cấu trúc là gì?", "back": "Buộc mô hình trả về đúng một lược đồ định trước gồm tên trường, kiểu dữ liệu và tập giá trị hợp lệ." },
{ "front": "Enum trong lược đồ dùng để làm gì?", "back": "Đóng tập giá trị hợp lệ của một trường, ngăn mô hình tự đặt nhãn mới." },
{ "front": "Quy ước nào nên có khi mô hình không chắc chắn?", "back": "Trả về null kèm lý do, thay vì đoán." },
{ "front": "Vì sao tách trường suy luận khỏi trường kết luận?", "back": "Để kiểm tra được lập luận mà vẫn có dữ liệu sạch cho bước xử lý tiếp theo." },
{ "front": "Ví dụ mẫu có nhãn mâu thuẫn gây ra hậu quả gì?", "back": "Mô hình học luôn cả sự mâu thuẫn, khiến đầu ra dao động giữa các lần gọi." },
{ "front": "Rủi ro chính của chain-of-thought hiển thị?", "back": "Chuỗi suy luận nghe hợp lý nhưng vẫn có thể sai, nên phải kiểm chứng riêng." }
]