Structured Output: Bắt ChatGPT Trả JSON Chuẩn Cho n8n
Ép ChatGPT trả đúng định dạng JSON theo schema định sẵn, để cắm thẳng vào node n8n mà không cần thêm lớp xử lý lỗi.
Bài viết có thể chứa liên kết tiếp thị (affiliate) — Kudomax có thể nhận hoa hồng khi bạn mua hàng qua các liên kết này, không phát sinh thêm chi phí cho bạn. Xem chính sách minh bạch.
Trước khi biết Structured Output, workflow n8n của mình có cả một node riêng chỉ để dò lỗi khi ChatGPT trả về JSON sai định dạng: thiếu dấu ngoặc, thừa chữ giải thích trước đoạn JSON. Bật Structured Output xong, node đó bỏ luôn được. Bài này giải thích cơ chế, cách viết schema đúng chuẩn strict và hai cách cắm vào n8n tuỳ bạn thích tự gọi API hay dùng node có sẵn.

Structured Output là gì?
Là tính năng ép mô hình trả về đúng cấu trúc dữ liệu đã định nghĩa trước bằng schema, thay vì trả lời tự do bằng văn bản có thể lẫn giải thích thừa. Kết quả trả về khớp chính xác với các trường bạn khai báo, sẵn sàng đưa thẳng vào bước xử lý tiếp theo.
📌 Chưa chắc nên chọn gì? Đọc trước Học AI: Dùng Claude, ChatGPT, Gemini Đúng Việc — hướng dẫn tổng hợp của Kudomax về học ai.
Cụ thể với API của OpenAI: bạn gửi kèm một JSON Schema trong request và bật chế độ strict, mô hình bị ràng buộc sinh ra output khớp schema đó, đúng tên trường, đúng kiểu dữ liệu, không thừa trường lạ, không kèm câu chữ ngoài JSON. Ràng buộc hoạt động ngay ở tầng sinh từng token chứ không phải kiểm tra sau, nên không có chuyện JSON cụt giữa chừng vì mô hình quên đóng ngoặc.
Ba mức ép định dạng khác nhau thế nào?
Trước khi có Structured Output, dân tự động hoá đã có hai cách yếu hơn. Đặt cạnh nhau cho dễ chọn:
| Cách | Độ chắc chắn | Điểm yếu |
|---|---|---|
| Nhắc trong prompt: hãy trả về JSON | Thấp | Dễ lẫn chữ giải thích, sai tên trường, sót trường |
| JSON mode (json_object) | Trung bình | Bảo đảm JSON hợp lệ nhưng cấu trúc bên trong tự do |
| Structured Output (json_schema + strict) | Cao nhất | Phải khai schema đúng chuẩn, chỉ model đời mới hỗ trợ |
Vì sao quan trọng khi nối với n8n?
n8n xử lý dữ liệu theo từng trường cụ thể ở các node phía sau. Nếu ChatGPT trả lời tự do, mỗi lần gọi có thể ra định dạng hơi khác nhau, đủ để làm workflow lỗi giữa chừng. Structured Output bảo đảm đầu ra luôn đúng khuôn, node sau không cần đoán hay xử lý ngoại lệ nhiều.
Viết schema thế nào cho đúng chuẩn strict?
Ví dụ workflow phân loại bình luận fanpage, mình muốn nhận về ba trường: cảm xúc, có cần trả lời không, và câu trả lời gợi ý. Schema gửi kèm request như sau:
{
"name": "phan_loai_binh_luan",
"strict": true,
"schema": {
"type": "object",
"properties": {
"sentiment": {
"type": "string",
"enum": ["tich_cuc", "tieu_cuc", "trung_lap"]
},
"can_tra_loi": { "type": "boolean" },
"cau_tra_loi": { "type": "string" }
},
"required": ["sentiment", "can_tra_loi", "cau_tra_loi"],
"additionalProperties": false
}
}
Ba quy tắc của chế độ strict mà người mới hay vấp: mọi trường trong properties đều phải có mặt trong required; phải khai additionalProperties là false; trường không bắt buộc thì khai kiểu dạng mảng gồm kiểu chính và null, chứ không phải bỏ khỏi required. Dùng enum như trường sentiment ở trên để giới hạn giá trị, node Switch phía sau sẽ không bao giờ gặp giá trị lạ.
Cắm vào n8n theo cách nào?
- Cách 1, node HTTP Request gọi thẳng API OpenAI: toàn quyền kiểm soát request, dán schema vào trường response_format trong body. Hợp khi bạn đã quen đọc tài liệu API.
- Cách 2, dùng node AI có sẵn của n8n: nối node OpenAI Chat Model với node Structured Output Parser, dán schema (hoặc một JSON ví dụ để n8n tự suy ra schema) vào node parser. Kết quả được parse sẵn thành field, node sau truy cập thẳng kiểu {{ $json.output.sentiment }}.
Body của cách 1 trông thế này:
{
"model": "gpt-4o-mini",
"messages": [
{ "role": "user", "content": "Phan loai binh luan sau: ..." }
],
"response_format": {
"type": "json_schema",
"json_schema": "<dan nguyen khoi schema o muc tren vao day>"
}
}
Ví dụ thật: bỏ hẳn node xử lý lỗi?
Workflow trả lời bình luận của mình trước đây gồm: node OpenAI, node Code để bóc JSON khỏi chữ thừa, node IF kiểm tra đủ trường, thêm một nhánh xử lý khi thiếu. Sau khi chuyển sang Structured Output còn lại: node OpenAI kèm schema, node Switch rẽ theo sentiment, node đăng trả lời. Hai node biến mất, và đáng kể hơn là ba tháng nay chưa lỗi định dạng lần nào. Toàn bộ workflow đó mình mô tả trong bài tự động đăng bài và trả lời bình luận bằng n8n; còn nếu bạn chưa từng dựng workflow nào, bắt đầu từ n8n cơ bản: dựng workflow tự động đầu tiên trước, bài này sẽ dễ theo hơn nhiều.
Lỗi hay gặp và giới hạn?
- Lỗi 400 khi gọi API: gần như luôn do schema thiếu một trong hai thứ, required chưa đủ mọi trường hoặc thiếu additionalProperties false. Đọc message lỗi, nó chỉ đích danh chỗ thiếu.
- Model không hỗ trợ: tính năng chỉ có từ thế hệ gpt-4o trở đi qua API, model cũ hơn báo lỗi hoặc âm thầm bỏ qua schema.
- Đúng khuôn không có nghĩa đúng nội dung: schema chỉ ép cấu trúc, giá trị bên trong vẫn có thể sai (phân loại nhầm cảm xúc chẳng hạn), nên vẫn cần test bằng dữ liệu thật trước khi cho chạy tự động.
- Trường refusal: khi mô hình từ chối trả lời vì nội dung vi phạm chính sách, response chứa refusal thay vì JSON theo schema. Workflow nên có nhánh kiểm tra trường này thay vì mặc định lúc nào cũng có dữ liệu.
- Lần gọi đầu với schema mới có thể chậm hơn bình thường do hệ thống xử lý schema, các lần sau nhanh trở lại.
- Dùng Structured Output khi output đổ thẳng vào node tự động phía sau.
- Dùng JSON mode khi chỉ cần JSON hợp lệ để lưu log, cấu trúc lỏng được.
- Nhắc định dạng trong prompt chỉ đủ cho lúc thử nghiệm tay, đừng đem vào workflow chạy thật.
Bước tiếp theo: lấy đúng cái workflow n8n đang hay lỗi định dạng nhất của bạn, viết schema cho ba trường thiết yếu nhất theo mẫu ở trên, chạy 20 bản ghi thật và đếm số lần lỗi. Con số đó sẽ thuyết phục bạn hơn bất kỳ bài viết nào.




