Reading six kinds of reply without crashing
The replies are written out as raw JSON text, the way they arrive. Java reads them with the course's Json helper; real Java projects use Jackson.
A reply is more than text: finish_reason says why the model stopped (finished, cut off, wants a tool, blocked) and usage says how many tokens you paid for. Read every field defensively, because any of them can be missing, null or empty.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 6 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write is_complete(reply_json_text) that returns True only when the first choice has finish_reason equal to stop and non-empty content.
Write total_tokens(reply_json_text) that returns usage.total_tokens, or prompt_tokens + completion_tokens when total_tokens is missing, or None without usage.
Explain it without notes
What does finish_reason: "length" mean and how should code react?
Which fields of a chat reply can be missing or null, and why does it matter?
How is the bill for one call computed from the reply?
Expected output
normal -> OK: Rain all week. | tokens=25
cut off -> CUT OFF (raise max_tokens): Rain is expected, but the | tokens=26
tool call -> TOOL CALL: get_weather | tokens=52
filtered -> BLOCKED by the provider's filter | tokens=20
no usage -> OK: Rain all week. | tokens=unknown
no choices -> ERROR no choices in the reply