Skip to course content
Free generative AI app course

Generative AI Application Development with Python

Unit 03.01: Reading a response object, not just its text

Reading only .text throws away the four things you need when something goes wrong.

finish_reason, usage, model

A response object with all its fields, and what each finish reason means.

The code prints both.

response = {
    "text": "Refunds are allowed within 7 days.",
    "finish_reason": "stop",
    "usage": {"input_tokens": 96, "output_tokens": 12},
    "model": "some-model-2026-06",
}
print(f"text          : {response['text']}")
print(f"finish_reason : {response['finish_reason']}")
print(f"tokens        : {response['usage']}")
print(f"model         : {response['model']}")

for reason, meaning in [("stop", "the model finished"),
                        ("length", "TRUNCATED -- hit the token limit"),
                        ("content_filter", "blocked; you were still charged"),
                        ("tool_calls", "it wants to call a tool, not answer")]:
    print(f"  {reason:16} {meaning}")

# Reading only `.text` throws away the four things you need: whether it
# finished, what it cost, which model version produced it, and whether it was
# trying to do something other than answer.

finish_reason: length means the answer was truncated - it is well-formed prose that stops mid-thought, and if you were parsing JSON the parse fails somewhere that looks unrelated.

content_filter means you were charged and got nothing usable. usage is how you compute cost per successful answer, and model is how you explain a run after the provider updates.

The mistake this prevents

The mistake is wrapping the call in a helper that returns a string. It reads well and discards the truncation flag, the cost and the model version - which is everything you need during an incident.

Takeaway

Read the whole response object. finish_reason catches truncation and filtering, usage gives you cost per success, and model is what lets you explain an old run.