Your First AI Project

Lesson 4 of 14

Reading the response

You got text back. The reply object holds more than the text, and two of the extra fields are the difference between a hobby project and one you can budget for.

What actually comes back

python
response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=300,
    messages=[{"role": "user", "content": "Name three Indian cities."}],
)
print(type(response))
print(response.usage)
print(response.stop_reason)
print(response.content[0].text)

The object carries the generated text, a count of tokens used, and a reason the model stopped. One run printed:

text
<class 'anthropic.types.message.Message'>
Usage(input_tokens=15, output_tokens=24)
end_turn
Here are three Indian cities:

1. Mumbai
2. Delhi
3. Bengaluru
What comes back from a model call: the text, the token counts, and why it stopped
What comes back from a model call: the text, the token counts, and why it stopped

Tokens, and why the count is on the invoice

A token is a chunk of text — very roughly three-quarters of an English word, so 1,000 tokens is about 750 words. Models read and write in tokens, and you are billed per token.

Two counts come back. Input tokens cover everything you sent: your instructions, the document, the conversation so far. Output tokens cover what the model generated.

They are priced differently — output typically costs several times more than input — which has a direct design consequence. Sending a long document is cheap; asking for a long answer is not. "Summarise this in 200 words" and "summarise this in 2,000 words" cost meaningfully different amounts on the same input, and the shorter one is usually more useful anyway.

stop_reason, the field nobody reads

Why the model stopped generating. Two values matter.

end_turn — it finished naturally. Good.

max_tokens — it hit your limit and was cut off mid-sentence. This is the silent failure of the whole course. You get a response, it looks fine at a glance, and the last thirty per cent is missing. In a loop over 400 documents you will not notice, and the truncated ones flow into your spreadsheet looking exactly like the complete ones.

So check it:

python
if response.stop_reason == "max_tokens":
    print("WARNING: truncated — raise max_tokens")

Three lines, and it converts an invisible corruption into a visible warning. Put it in every loop you write.

Real money, computed

Take the meeting-notes tool at Studio-scale: about 1,800 input tokens per transcript and 220 output tokens, at illustrative rates of $3 per million input tokens and $15 per million output.

python
in_tok, out_tok = 1800, 220
per_run = in_tok/1_000_000*3.0 + out_tok/1_000_000*15.0
print(f"per file  = ${per_run:.5f}")
print(f"400/week  = ${per_run*400:.2f}")
print(f"per year  = ${per_run*400*52:.2f}")
text
per file  = $0.00870
400/week  = $3.48
per year  = $180.96

Under a cent per document. Three and a half dollars a week. About $181 a year to process 400 meeting transcripts every week.

Look at that number properly, because it reframes the whole field. The cost of a model call is almost never what makes an AI project expensive — the expensive parts are the people, the checking, and the integration. Meanwhile the shape of the number matters enormously: this is per call, so it scales linearly and without limit, which is why a runaway loop is a financial event rather than an inconvenience. Lesson 13 is about caps.

Check today's actual prices on your provider's pricing page before you quote any of this to anyone; rates move, generally downward.

A small habit worth forming

python
total_in = total_out = 0

def track(response):
    global total_in, total_out
    total_in += response.usage.input_tokens
    total_out += response.usage.output_tokens
    return response.content[0].text

Call track(response) instead of digging out the text by hand, and you have a running total for the session. When lesson 6 turns one call into four hundred, you will want it, and adding it afterwards is always slightly more annoying than it sounds.

Do this today: make one call and print usage and stop_reason. Then set max_tokens=20 deliberately, ask for something long, and watch stop_reason come back as max_tokens. Seeing the truncation happen on purpose is what makes you remember to check for it.

← Previous