Domain 4: Prompt Engineering & Structured Output·Task 4.3
Ép đầu ra có cấu trúc bằng tool use và JSON schema
Lấy dữ liệu đúng schema qua tool use và strict, chọn tool_choice cho từng tình huống, thiết kế trường tuỳ chọn, enum có other và unclear để Claude khỏi bịa.
- 6 phút đọc
- Đối chiếu docs 02/11/2026
- 4 nguồn
Đọc xong bạn nắm được
- Định nghĩa tool trích xuất có JSON schema và lấy dữ liệu từ khối tool_use
- Hiểu schema chặn được lỗi cú pháp nhưng không chặn được lỗi về nghĩa
- Chọn tool_choice auto, any hay ép một tool cho từng tình huống
- Để trường là tuỳ chọn khi tài liệu có thể không có thông tin, tránh Claude bịa giá trị
- Thêm giá trị other kèm trường mô tả, và unclear cho ca mập mờ
Khi kết quả của Claude được một chương trình đọc tiếp, nó phải đúng cấu trúc: đủ trường, đúng kiểu, JSON hợp lệ. Chỉ cần một dấu phẩy thừa là chương trình phía sau báo lỗi.
Bài này giúp bạn trả lời: làm sao để chắc chắn Claude trả về đúng schema, và thiết kế schema thế nào để Claude không phải bịa cho đủ trường?
Ví dụ xuyên suốt: trích thông tin từ tin rao bán ô tô cũ
Một sàn mua bán ô tô cũ muốn chuẩn hoá các tin rao do người bán tự viết. Bạn dùng Claude trích: hãng, dòng xe, năm sản xuất, số km đã đi, loại hộp số, giá. Bản đầu dùng prompt "trả lời bằng JSON theo mẫu sau". Vấn đề:
- Khoảng 2% kết quả không phải JSON hợp lệ: thiếu dấu ngoặc, có câu giải thích ở đầu.
- Tin không ghi số km, nhưng schema bắt buộc trường
soKm, nên Claude điền một con số "hợp lý" như50000. - Hộp số chỉ có hai giá trị
so_sanvàso_tu_dong, nhưng tin rao có cả "hộp số CVT", "ly hợp kép". Có tin chỉ ghi "xe chạy êm, số mượt", không rõ loại gì. - Có kết quả đúng schema nhưng sai nghĩa: năm sản xuất
2019nằm ở trườngsoKm.
Lấy dữ liệu qua tool use
Thay vì xin JSON trong câu trả lời, bạn định nghĩa một tool có input_schema chính là cấu trúc dữ liệu bạn cần. Claude "gọi" tool đó, và dữ liệu nằm trong khối tool_use của câu trả lời. Bạn không cần chạy tool nào cả; tool chỉ là cái khuôn.
{
"name": "luu_tin_xe",
"description": "Lưu thông tin trích từ một tin rao bán ô tô cũ",
"strict": true,
"input_schema": {
"type": "object",
"properties": {
"hang": { "type": "string" },
"namSanXuat": { "type": "integer" },
"soKm": { "type": ["integer", "null"] },
"hopSo": { "enum": ["so_san", "so_tu_dong", "khac", "khong_ro"] },
"hopSoChiTiet": { "type": ["string", "null"] }
},
"required": ["hang", "namSanXuat", "soKm", "hopSo", "hopSoChiTiet"],
"additionalProperties": false
}
}Tool use với JSON schema là cách đáng tin nhất để có đầu ra đúng schema, không còn lỗi cú pháp JSON. Câu hỏi "cách nào đảm bảo đầu ra luôn đúng schema" trong đề và câu luyện thi đều chấm đáp án định nghĩa tool có schema rồi lấy dữ liệu từ tool_use.
Khi làm thật, nên thêm strict: true vào tool như ở trên. Tài liệu Claude API hiện tại nói: không có strict, Claude có thể trả sai kiểu ("2" thay vì 2) hoặc thiếu trường bắt buộc; có strict, đầu vào của tool luôn khớp schema vì cách sinh chữ bị giới hạn trong những gì schema cho phép. Nếu bạn chỉ cần một câu trả lời dạng JSON mà không cần tool, API còn có structured outputs (output_config.format) với cùng bảo đảm. Vấn đề 1 hết hẳn.
Đúng schema chưa chắc đúng nghĩa
Vấn đề 4 vẫn còn dù có strict. Schema chỉ kiểm soKm là số nguyên; 2019 là số nguyên nên hợp lệ. Schema chặt loại bỏ lỗi cú pháp, nhưng không ngăn được lỗi về nghĩa (semantic errors), như các dòng không cộng ra tổng, hay giá trị nằm nhầm trường.
Lỗi về nghĩa phải bắt bằng bước kiểm tra riêng sau khi trích, ví dụ số km không thể nhỏ hơn 100 với xe sản xuất 5 năm trước, hay tổng các dòng phải bằng tổng tiền. Cách kiểm và cho Claude sửa lại nằm ở bài 4.4.
Ngoài schema, bạn vẫn nên ghi quy tắc chuẩn hoá trong prompt, vì người bán viết mỗi người một kiểu: "Giá ghi '650 triệu', '650tr', '0,65 tỷ' đều ghi thành 650000000." Schema nói giá là số; prompt nói đọc chữ của người bán thành số ra sao.
Chọn tool_choice
tool_choice quyết định Claude có bắt buộc gọi tool hay không:
| Giá trị | Nghĩa | Dùng khi |
|---|---|---|
{"type": "auto"} | Claude có thể trả lời bằng chữ thay vì gọi tool | Mặc định khi có tool |
{"type": "any"} | Phải gọi một tool, nhưng tự chọn tool nào | Có nhiều schema trích xuất, chưa biết tài liệu thuộc loại nào |
{"type": "tool", "name": "..."} | Phải gọi đúng tool này | Một bước trích xuất phải chạy trước các bước khác |
Ví dụ sàn có thêm tool luu_tin_xe_may cho tin rao xe máy, và không biết trước tin nào là ô tô hay xe máy: đặt any để chắc chắn Claude chọn một trong hai tool chứ không trả lời bằng chữ. Còn nếu bước trích thông tin cơ bản phải chạy trước bước định giá, ép {"type": "tool", "name": "luu_tin_xe"} ở lượt đầu.
Như đã nói ở bài 2.3, các model mới nhất (Opus 5.5, Sonnet 5.5, Fable 5.1) trả lỗi 400 với any và ép tool; tài liệu khuyên dùng auto kèm strict, hoặc structured outputs. Trong đề thi, hai tình huống trên vẫn chấm any và ép tool.
Schema không ép Claude bịa
Vấn đề 2 do schema: trường bắt buộc mà tài liệu không có thông tin thì Claude buộc phải điền gì đó. Cách sửa là cho phép trường đó rỗng (optional / nullable): "soKm": {"type": ["integer", "null"]}. Tin không ghi số km thì Claude trả null. Nên kèm thêm một câu trong prompt: "Thông tin nào tin rao không ghi rõ thì để null, không suy đoán."
Vấn đề 3 do enum quá hẹp. Có hai cách mở rộng:
- Thêm
otherkèm một trường chữ mô tả: ở ví dụ làkhackèmhopSoChiTiet: "CVT". Không cần sửa schema mỗi lần gặp loại mới. - Thêm
unclearcho ca không xác định được: ở ví dụ làkhong_rocho tin "số mượt". Claude không phải đoán bừa giữa số sàn và số tự động.
Anthropic Exam Pro