Trong nhiều AI feature, vấn đề không nằm ở việc gọi LLM được hay không. Vấn đề thật là: output của model có đủ ổn định để backend, workflow, database và downstream service xử lý như một contract production hay không. Nếu application code kỳ vọng JSON nhưng model trả thêm lời giải thích, thiếu field, đổi enum, hoặc tạo dữ liệu có vẻ hợp lệ nhưng sai nghĩa, hệ thống sẽ lỗi theo cách rất khó debug.

LLM structured outputs với JSON Schema là cách biến output tự nhiên của model thành một contract có thể validate, test, monitor và version. Bài này đi vào thiết kế kỹ thuật cho IT professionals: schema nên đặt ở đâu, validation gồm những lớp nào, retry thế nào để không tạo retry storm, quan sát metric gì và checklist trước khi đưa AI feature vào production.

Sơ đồ contract structured outputs giữa ứng dụng LLM, JSON Schema, validator và downstream service
Structured outputs không chỉ là “bắt model trả JSON”; đó là contract giữa AI layer và hệ thống production.

Structured outputs là gì trong ứng dụng LLM?

Structured outputs là kỹ thuật yêu cầu model trả kết quả theo một cấu trúc đã định nghĩa trước, thường là JSON object phù hợp với JSON Schema. Thay vì parse một đoạn text tự do, backend nhận một payload có field, type, enum và constraint rõ ràng.

{
  "schema_version": "1.0",
  "intent": "refund_request",
  "priority": "high",
  "confidence": 0.86,
  "evidence": ["customer asked for refund", "order delayed 12 days"]
}

Điểm khác biệt so với prompt “hãy trả JSON” là production system cần coi schema như API contract: có validation tự động, logging, alerting, versioning, test case và fallback. Nếu bạn đang xây backend API nghiêm túc, tư duy này giống bài REST API Design Checklist: contract rõ thì system dễ vận hành hơn.

Vì sao JSON hợp lệ vẫn chưa đủ?

Nhiều team dừng ở bước JSON.parse(). Đây là lớp bảo vệ quá mỏng. Output có thể là JSON hợp lệ nhưng vẫn sai contract: thiếu required field, field sai kiểu, enum ngoài danh sách, confidence vượt range, hoặc một object có schema đúng nhưng business meaning sai.

Ma trận rủi ro malformed JSON, thiếu field, hallucinated enum và semantic invalid output trong AI feature
Rủi ro LLM output gồm cả lỗi syntax, lỗi schema và lỗi ngữ nghĩa nghiệp vụ.

Ví dụ một hệ thống phân loại ticket cho phép enum billing, technical, account. Nếu model trả payment_issue, code downstream có thể rơi vào default branch, route sai queue hoặc tạo dữ liệu bẩn. Nếu model trả confidence 1.2, dashboard có thể méo số liệu. Nếu model đưa evidence không có trong input, bạn có hallucination nhưng JSON vẫn parse thành công.

Thiết kế JSON Schema cho LLM output

Một schema tốt nên nhỏ, rõ, typed chặt và phản ánh đúng việc downstream cần. Đừng bắt model trả toàn bộ “bài văn” nếu service chỉ cần decision, confidence và evidence.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "additionalProperties": false,
  "required": ["schema_version", "intent", "priority", "confidence", "evidence"],
  "properties": {
    "schema_version": { "const": "1.0" },
    "intent": { "enum": ["refund_request", "bug_report", "sales_question", "other"] },
    "priority": { "enum": ["low", "medium", "high"] },
    "confidence": { "type": "number", "minimum": 0, "maximum": 1 },
    "evidence": {
      "type": "array",
      "minItems": 1,
      "maxItems": 5,
      "items": { "type": "string", "minLength": 5, "maxLength": 240 }
    }
  }
}

Schema nên chặt ở đâu?

  • Dùng additionalProperties: false cho output đi vào workflow quan trọng.
  • Dùng enum cho các field route logic, queue, trạng thái hoặc action.
  • Dùng min/max cho score, money, quantity, retry delay.
  • Giới hạn length cho string để tránh payload phình hoặc prompt injection đi sâu vào downstream.
  • Luôn có schema_version để debug và migration.

Validation pipeline: parse, schema, semantic

Luồng validate JSON Schema, retry có kiểm soát và fallback khi LLM trả output không hợp lệ
Validation nên có nhiều lớp: parse JSON, validate schema, validate business rule, rồi mới cho downstream xử lý.

Production pipeline nên tách ít nhất ba lớp:

  1. Syntax validation: parse JSON an toàn, reject markdown wrapper hoặc text ngoài JSON nếu contract yêu cầu strict.
  2. Schema validation: dùng JSON Schema validator như Ajv, Zod hoặc Pydantic để kiểm type, required, enum, range.
  3. Semantic validation: kiểm điều kiện nghiệp vụ mà schema không biết, ví dụ evidence phải trích từ input, priority high cần lý do, action refund không được vượt policy.
import Ajv from "ajv";

const ajv = new Ajv({ allErrors: true, removeAdditional: false });
const validate = ajv.compile(ticketSchema);

function validateLlmOutput(raw, inputText) {
  let data;
  try { data = JSON.parse(raw); }
  catch { return { ok: false, reason: "malformed_json" }; }

  if (!validate(data)) {
    return { ok: false, reason: "schema_invalid", errors: validate.errors };
  }

  const unsupportedEvidence = data.evidence.filter(e => !inputText.includes(e));
  if (unsupportedEvidence.length) {
    return { ok: false, reason: "semantic_invalid", unsupportedEvidence };
  }

  return { ok: true, data };
}

Retry thế nào để không tạo retry storm?

Khi output invalid, retry là hợp lý, nhưng retry vô hạn sẽ làm tăng cost, latency và tải lên provider. Với endpoint production, hãy đặt retry budget rõ ràng: ví dụ tối đa 1 retry cho synchronous path, 2-3 retry cho async job, exponential backoff nhẹ, timeout cứng và fallback sau khi hết budget.

Retry prompt nên đưa lỗi cụ thể thay vì lặp lại prompt ban đầu:

The previous output failed validation:
- field "priority" must be one of: low, medium, high
- field "confidence" must be between 0 and 1
Return only JSON matching the schema. Do not include markdown.

Nếu AI feature nằm trong hệ thống chịu tải, retry policy cần liên hệ với backpressure. Khi provider chậm hoặc invalid rate tăng, service nên giảm concurrency, chuyển sang queue hoặc fallback deterministic. Đây là cùng tinh thần với Backpressure và Load Shedding trong Backend.

Schema versioning cho AI feature

Checklist versioning schema và observability cho structured outputs trong production
Schema versioning giúp debug drift, migration và so sánh chất lượng giữa các prompt/model version.

Prompt, model và schema đều thay đổi theo thời gian. Nếu log chỉ ghi “LLM failed”, bạn sẽ không biết failure đến từ model mới, prompt mới hay schema mới. Mỗi request nên log ít nhất:

  • schema_version
  • prompt_version
  • model và provider
  • validation_result và reason
  • latency, token/cost nếu có
  • sample hash hoặc redacted sample để điều tra

Khi thêm field mới, ưu tiên backward-compatible: thêm optional field trước, deploy consumer hiểu cả v1/v1.1, rồi mới chuyển required field sau khi dữ liệu ổn định. Với workflow quan trọng, hãy có contract tests chứa input mẫu và expected output shape để phát hiện prompt regression.

Observability: metric cần theo dõi

Đừng chỉ monitor HTTP 500. Với AI feature, nhiều lỗi nguy hiểm không tạo exception. Một dashboard thực dụng nên có:

  • llm_output_invalid_rate theo schema_version/prompt_version/model.
  • malformed_json_rate, schema_invalid_rate, semantic_invalid_rate.
  • retry count, fallback rate, human review rate.
  • p50/p95/p99 latency gồm cả retry.
  • cost per successful structured output, không chỉ cost per request.
  • distribution của enum quan trọng để phát hiện drift bất thường.

Nếu bạn đã có tracing cho microservices, hãy đưa validation result vào span attribute. Xem thêm Distributed Tracing cho Microservices để nối AI call với request path tổng thể.

Không đưa output thẳng vào action nguy hiểm

Structured output giúp giảm rủi ro, nhưng không biến LLM thành source of truth. Với action có tác động thật như refund tiền, khóa tài khoản, gửi email cho khách hàng, thay đổi dữ liệu production hoặc chạy command, output của model nên là recommendation đi qua policy engine, permission check hoặc human approval.

Một pattern an toàn là tách decisionaction. LLM phân loại intent và đề xuất next step; service deterministic kiểm policy và quyết định có thực thi hay không. Field như reason, evidenceconfidence hỗ trợ audit, nhưng không thay thế business rule.

Checklist trước khi ship structured outputs

  • Schema có additionalProperties: false hoặc strategy rõ cho unknown field.
  • Các enum ảnh hưởng routing/action được giới hạn chặt.
  • Có syntax + schema + semantic validation.
  • Retry có budget, timeout và fallback; không retry vô hạn.
  • Log schema_version, prompt_version, model, validation reason.
  • Có contract tests cho prompt/model/schema.
  • Có dashboard invalid rate, fallback rate, latency và cost per success.
  • Không cho LLM output trực tiếp thực hiện action nguy hiểm nếu chưa qua policy/approval.
  • Có kế hoạch migration khi schema thay đổi.
  • Sample invalid output được review định kỳ để cải thiện prompt/schema.

Kết luận

LLM structured outputs với JSON Schema là một bước quan trọng để đưa AI feature từ demo sang production. Nhưng giá trị thật không nằm ở việc “model trả JSON”, mà nằm ở contract được validate, retry có kiểm soát, schema có version, observability đủ sâu và downstream không tin mù quáng vào output.

Nếu backend team áp dụng cùng kỷ luật như thiết kế API, database migration và production monitoring, structured outputs sẽ giúp AI feature dễ vận hành hơn rất nhiều: ít parse lỗi hơn, ít dữ liệu bẩn hơn, debug nhanh hơn và an toàn hơn khi tích hợp vào workflow thật.