When an LLM 'calls a function,' the arguments can be perfectly valid JSON yet semantically wrong — like a plausible but nonexistent order ID. Why does constrained decoding not catch this, and what would you put in place to handle it?
technical-conceptual · Mid level · data-ml
What the interviewer is really asking
Tests a precise understanding that constrained/schema-guided decoding guarantees syntactic validity but not semantic correctness, and that the candidate knows the real safeguards — application-side validation, error feedback and retry loops, idempotency/confirmation for side-effecting tools — not just 'trust the schema.'
What to say
- Draw the distinction: constrained decoding (CFG/JSON-schema-guided generation) forces the output to match the schema's shape and types, but the model can still hallucinate a value that's syntactically valid and semantically false — a well-formed but fake ID.
- Validate on the application side: check arguments against real state (does this order ID exist?) and business rules before executing, treating tool inputs as untrusted.
- Close the loop and protect side effects: on a validation or execution failure, feed the error back to the model and retry within a bounded budget, and make side-effecting tools idempotent or require confirmation so a bad call can't double-act.
What to avoid
- Believing JSON-schema or 'strict mode' validation guarantees the call is correct — it only guarantees the shape.
- Executing the tool directly on model output with no application-side validation of the actual values.
- Retrying blindly forever with no error feedback or step budget, or letting side-effecting calls fire without idempotency/confirmation.
Example answers
Strong: Constrained decoding only enforces shape — it guarantees the JSON parses and the fields match the schema's types, but it can't know whether order ID 88231 actually exists, so the model can emit a perfectly valid hallucinated value. So I treat tool arguments as untrusted: validate them against real state and business rules before executing. If validation or the tool call fails, I feed the specific error back to the model and let it retry within a step budget. And for anything with side effects I add idempotency keys or a confirmation step, so a wrong call can't double-charge or double-act.
Weak: I'd use the provider's strict structured-output mode so the function arguments always match the schema. Once the JSON is guaranteed valid against the schema, the model can't really pass bad arguments, so the tool just runs.