Bỏ qua để đến nội dung

4.3 Structured Output with Tool Use

Khi cần structured output đảm bảo đúng schema từ Claude, có một thứ tự độ tin cậy rất rõ:

  1. tool_use kèm JSON schema — loại bỏ hoàn toàn lỗi cú pháp JSON
  2. JSON dựa trên prompt — model vẫn có thể trả về JSON hỏng

Thuộc thứ tự này. Đề thi xây trên nó. Với tool use, JSON schema của tool ràng buộc hình dạng thứ Claude trả về, xóa sạch các lỗi cú pháp kiểu thiếu ngoặc, thừa dấu phẩy hay key không có dấu nháy. Tham số tool_choice là thứ riêng biệt, nó mới là cái ép model thực sự gọi tool. Extraction dựa trên prompt (yêu cầu model xuất JSON trong một text response) không cho bạn bảo đảm nào về cấu trúc và sẽ định kỳ tạo ra output không parse nổi trên production.

Tham số tool_choice kiểm soát việc model có gọi tool hay không và gọi thế nào. Hiểu ba chế độ này là bắt buộc cho kỳ thi:

"auto" (mặc định): Model tự quyết định gọi tool hay trả về text. Nó có thể chọn trả lời bằng một text message thay vì gọi tool extraction. Dùng khi model thật sự cần quyền trả lời theo kiểu hội thoại.

"any": Model BẮT BUỘC phải gọi một tool nhưng được tự chọn tool nào. Dùng khi bạn có nhiều schema extraction (ví dụ extract_invoice, extract_receipt, extract_contract) và chưa biết loại tài liệu. Model chọn tool phù hợp rồi trả về structured output. Đảm bảo có structured output, linh hoạt ở khâu chọn tool.

{"type": "tool", "name": "extract_metadata"}: Model BẮT BUỘC phải gọi đúng tool được chỉ định. Dùng để cưỡng chế một bước đầu tiên bắt buộc — ví dụ đảm bảo extraction metadata chạy trước các bước enrichment. Không linh hoạt, kiểm soát tối đa.

extract_metadata ở đây là tool do chính bạn định nghĩa; tên gọi là tùy ý. tool_choice cũng áp theo từng request, không phải theo cả hội thoại. Khi lượt gọi bị cưỡng chế đã trả về, hãy gửi request kế tiếp với auto (hoặc bỏ hẳn tham số), nếu không model buộc phải gọi lại đúng tool đó và bạn rơi vào vòng lặp.

// Force guaranteed structured output with unknown document type
const response = await client.messages.create({
model: "claude-sonnet-5",
max_tokens: 4096,
tool_choice: { type: "any" },
tools: [extractInvoiceTool, extractReceiptTool, extractContractTool],
messages: [{ role: "user", content: documentText }]
});
// Force a specific extraction step
const response = await client.messages.create({
model: "claude-sonnet-5",
max_tokens: 4096,
tool_choice: { type: "tool", name: "extract_metadata" },
tools: [extractMetadataTool],
messages: [{ role: "user", content: documentText }]
});

Đây là chỗ đề thi chơi khó. tool_use kèm JSON schema loại bỏ lỗi cú pháp nhưng KHÔNG chặn được lỗi ngữ nghĩa:

  • Lệch tổng: Các line item cộng lại không khớp với tổng ghi trong tài liệu
  • Đặt sai field: Giá trị rơi vào field sai (ví dụ một ngày tháng nằm trong field số tiền khi cả hai đều là string)
  • Bịa dữ liệu: Model tự nghĩ ra giá trị cho field bắt buộc khi tài liệu gốc không có thông tin đó

Schema đảm bảo cấu trúc. Nó không đảm bảo tính đúng đắn. Validation ngữ nghĩa cần logic bổ sung (xem Task Statement 4.4).

Thiết kế schema tốt chặn được nguyên cả nhóm lỗi ngay ở tầng cấu trúc:

Field optional/nullable — Khi tài liệu gốc có thể không chứa một số thông tin, hãy để field đó optional hoặc nullable. Đây là tuyến phòng thủ chính chống bịa dữ liệu. Nếu field là bắt buộc, model bị ép phải sinh ra giá trị dù nguồn không có gì. Nếu field nullable, model được phép trả về null một cách trung thực.

{
"type": "object",
"properties": {
"invoice_number": { "type": "string" },
"vendor_name": { "type": "string" },
"payment_terms": { "type": ["string", "null"] },
"purchase_order": { "type": ["string", "null"] }
},
"required": ["invoice_number", "vendor_name"]
}

Giá trị enum “unclear” — Với những ca mà nguồn thật sự không rõ ràng, thêm một lựa chọn “unclear” vào field enum. Việc này ngăn model ép một phân loại khi bằng chứng còn mơ hồ.

“other” + chuỗi chi tiết — Để phân loại có thể mở rộng, thêm giá trị enum “other” đi kèm một field chuỗi tự do mô tả chi tiết. Cách này hứng được các edge case mà danh mục định sẵn chưa phủ.

{
"category": {
"type": "string",
"enum": ["invoice", "receipt", "contract", "unclear", "other"]
},
"category_detail": {
"type": ["string", "null"],
"description": "Freeform detail when category is 'other'"
}
}

Quy tắc chuẩn hóa định dạng — Đưa chỉ dẫn chuẩn hóa định dạng vào prompt, song song với schema. Schema cưỡng chế cấu trúc. Prompt cưỡng chế tính nhất quán về định dạng (ví dụ “All dates in ISO 8601 format”, “All currency amounts as decimal numbers without currency symbols”).

Hệ thống extraction của bạn dùng tool_use với một JSON schema chặt, mọi field đều bắt buộc. Tester báo rằng model tự nghĩ ra ngày tháng và số tiền trông rất hợp lý khi xử lý những tài liệu không có các thông tin đó. Cách sửa tốt nhất là gì?

  • A. Thêm chỉ dẫn vào prompt nói rằng model tuyệt đối không được hallucinate bất kỳ giá trị nào
  • B. Chuyển từ tool_use sang extraction JSON dựa trên prompt để output linh hoạt hơn
  • C. Để field ở dạng optional hoặc nullable khi tài liệu gốc có thể không chứa thông tin đó
  • D. Thêm bước validation sau extraction, đối chiếu mọi giá trị với tài liệu gốc
Đáp án & giải thích

Đúng: C

  • A — Chỉ dẫn mơ hồ không đè được ràng buộc của schema. Field bắt buộc gây sức ép cấu trúc buộc model sinh giá trị bất kể chỉ dẫn là gì.
  • B — Cách này đi lùi trong thứ tự độ tin cậy. JSON dựa trên prompt mang thêm lỗi cú pháp mà vẫn không giải quyết được chuyện bịa dữ liệu.
  • C — Field optional/nullable cho phép model trả về null thay vì bịa giá trị. Nó xử lý chuyện bịa dữ liệu ngay ở tầng thiết kế schema — đúng nguyên nhân gốc.
  • D — Validation hậu kiểm có giá trị nhưng chỉ chữa triệu chứng. Để field optional mới chặn việc bịa dữ liệu ngay ở tầng schema, và đó mới là cách sửa đúng gốc.

Sáu câu trắc nghiệm theo format đề thi về Structured Output with Tool Use. Chọn đáp án trước, rồi mở phần giải thích.

Hệ thống extraction của bạn dùng tool_use với một JSON schema chặt, mọi field đều bắt buộc. Tester báo rằng model tự nghĩ ra ngày tháng và số tiền trông rất hợp lý khi xử lý những tài liệu không có các thông tin đó. Cách sửa tốt nhất là gì?

  • A. Thêm chỉ dẫn yêu cầu model không hallucinate giá trị
  • B. Chuyển từ tool_use sang extraction JSON dựa trên prompt cho linh hoạt hơn
  • C. Thêm bước validation sau extraction, đối chiếu mọi giá trị với tài liệu gốc
  • D. Để field ở dạng optional hoặc nullable khi tài liệu gốc có thể không chứa thông tin đó
Đáp án & giải thích

Đúng: D

  • A sai vì chỉ dẫn mơ hồ không đè được ràng buộc của schema. Field bắt buộc gây sức ép cấu trúc buộc model sinh giá trị bất kể chỉ dẫn là gì.
  • B sai vì cách này đi lùi trong thứ tự độ tin cậy. JSON dựa trên prompt mang thêm lỗi cú pháp mà không giải quyết được chuyện bịa dữ liệu.
  • C sai vì validation hậu kiểm chữa triệu chứng chứ không chữa nguyên nhân gốc. Để field optional mới chặn việc bịa dữ liệu ngay ở tầng schema.
  • D đúng vì field optional/nullable cho phép model trả về null thay vì bịa giá trị. Nó xử lý chuyện bịa dữ liệu ngay ở tầng thiết kế schema.

Bạn cần đảm bảo có structured output từ Claude khi xử lý tài liệu chưa biết loại. Bạn có ba tool extraction: extract_invoice, extract_receipt và extract_contract. Thiết lập tool_choice nào là đúng?

  • A. tool_choice: { type: “auto” }
  • B. tool_choice: { type: “any” }
  • C. tool_choice: { type: “tool”, name: “extract_invoice” }
  • D. Không set tool_choice, để mặc định của API xử lý
Đáp án & giải thích

Đúng: B

  • A sai vì “auto” cho phép model trả về text thay vì gọi tool, nên không bảo đảm có structured output.
  • B đúng vì “any” bảo đảm có tool call trong khi vẫn để model chọn tool extraction hợp với loại tài liệu. Vừa đảm bảo structured output, vừa linh hoạt ở khâu chọn tool.
  • C sai vì ép một tool cụ thể nghĩa là mọi tài liệu đều bị xử như invoice, bất kể loại thật là gì.
  • D sai vì mặc định là “auto”, dính đúng vấn đề của phương án A — không bảo đảm structured output.

tool_use kèm JSON schema chặn được lỗi nào sau đây?

  • A. Các line item cộng lại không khớp với tổng ghi trong tài liệu
  • B. Giá trị đặt sai field (ví dụ một ngày tháng nằm trong field số tiền)
  • C. JSON hỏng: thiếu ngoặc, thừa dấu phẩy
  • D. Dữ liệu bịa cho thông tin không có trong tài liệu gốc
Đáp án & giải thích

Đúng: C

  • A sai vì lệch tổng là lỗi ngữ nghĩa. Schema đảm bảo cấu trúc, không đảm bảo tính đúng về toán học.
  • B sai vì đặt sai field là lỗi ngữ nghĩa. Cả hai field có thể cùng nhận string, và schema không kiểm chứng được giá trị nào thuộc về đâu.
  • C đúng vì tool_use kèm JSON schema loại bỏ hoàn toàn lỗi cú pháp JSON — thiếu ngoặc, thừa dấu phẩy, key không có dấu nháy.
  • D sai vì bịa dữ liệu là lỗi ngữ nghĩa. Schema ép model sinh ra giá trị đúng kiểu nhưng không kiểm chứng được tính xác thực của nó.

Schema extraction tài liệu của bạn có field enum “category” với các giá trị: [“invoice”, “receipt”, “contract”]. Khi chạy thực tế, có những tài liệu không thuộc các loại này và model ép chúng vào phân loại sai. Cách sửa ở tầng thiết kế schema nào phù hợp nhất?

  • A. Thêm “unclear” cho tài liệu mơ hồ và “other” đi kèm một field chuỗi chi tiết tự do
  • B. Bỏ ràng buộc enum và dùng field chuỗi tự do
  • C. Thêm confidence score cho mỗi phân loại rồi lọc bỏ kết quả confidence thấp
  • D. Mở rộng enum để bao trọn mọi loại tài liệu có thể có
Đáp án & giải thích

Đúng: A

  • A đúng vì “unclear” xử lý những ca thật sự mơ hồ, còn “other” kèm chuỗi chi tiết hứng được edge case mà vẫn giữ được cấu trúc phân loại.
  • B sai vì bỏ enum là mất luôn cấu trúc phân loại, thứ làm cho xử lý phía sau khả thi.
  • C sai vì confidence score được calibrate tệ và không giải quyết được chuyện thiếu danh mục.
  • D sai vì bạn không thể lường trước mọi loại tài liệu. Pattern “other” + chi tiết mở rộng được mà không phải liên tục sửa schema.

Khi nào nên dùng tool_choice { type: “tool”, name: “extract_metadata” } thay vì tool_choice “any”?

  • A. Khi bạn muốn model tự chọn tool extraction phù hợp nhất
  • B. Khi bạn muốn đảm bảo structured output với tài liệu chưa biết loại
  • C. Khi bạn cần cưỡng chế một bước đầu tiên bắt buộc trước mọi xử lý khác
  • D. Khi bạn muốn model có thể trả về text nếu không tool nào phù hợp
Đáp án & giải thích

Đúng: C

  • A sai vì linh hoạt chọn tool là mục đích của “any”, không phải của việc ép tool.
  • B sai vì đảm bảo output với tài liệu chưa biết loại cần “any” để model tự chọn tool phù hợp.
  • C đúng vì ép tool đảm bảo một bước bắt buộc luôn chạy bất kể model thích gì — ví dụ extraction metadata phải chạy trước các bước enrichment.
  • D sai vì tùy chọn trả về text là hành vi của “auto”, không phải của việc ép tool.

Bạn đang thiết kế JSON schema để extract dữ liệu tài chính. Một số tài liệu có mã số thuế, một số thì không. Nên định nghĩa field tax_id thế nào?

  • A. type: [“string”, “null”] và không đưa vào mảng required
  • B. type: “string” kèm ràng buộc required để đảm bảo dữ liệu đầy đủ
  • C. type: “string” với giá trị mặc định là “N/A”
  • D. Bỏ hẳn field này và thêm vào ở bước hậu xử lý nếu tìm thấy
Đáp án & giải thích

Đúng: A

  • A đúng vì kiểu nullable kết hợp với trạng thái optional cho phép model trả về null một cách trung thực khi thông tin không có.
  • B sai vì để tax_id là required sẽ ép model bịa ra một mã số thuế trông hợp lý khi tài liệu không có.
  • C sai vì giá trị mặc định “N/A” vẫn là bịa — nó lấp field bằng một placeholder thay vì thừa nhận rằng thông tin không tồn tại.
  • D sai vì bỏ hẳn field thì trong output bạn không phân biệt được “không tìm thấy field” với “chưa extract field”.