ailiteracynepal 🇳🇵
Text size

Chapter 01 · Section II · 24 min read

Your first call: prompts, tokens, and cost

The smallest complete LLM program, deeply understood. What each argument does, how tokens are counted, what streaming looks like, and how to predict cost before you spend it.

Course 01 Chapter 5 gave you a hello-world Anthropic call: a few lines of Python that sent a prompt and printed a response. This section returns to the same shape but goes deep on every argument, every field in the response, and every dollar spent. By the end you can look at any LLM call in the wild and understand exactly what is happening — and predict what it will cost before you run it.

The setup

Same as Course 01. In your activated virtual environment:

pip install anthropic python-dotenv

.env file (never committed):

ANTHROPIC_API_KEY=sk-ant-api03-...your-key...

Python setup:

import os
from dotenv import load_dotenv
import anthropic

load_dotenv()
client = anthropic.Anthropic()

If any of that is unfamiliar, revisit Course 01 Chapter 5. From here we assume you have a working key.

The call, annotated

The smallest useful call, with every argument explained:

response = client.messages.create(
    model="claude-haiku-4-5-20251001",
    max_tokens=400,
    messages=[
        {"role": "user", "content": "Summarise today's Kathmandu weather in two Nepali sentences."},
    ],
)

print(response.content[0].text)
print()
print(f"Input tokens:  {response.usage.input_tokens}")
print(f"Output tokens: {response.usage.output_tokens}")
print(f"Stop reason:   {response.stop_reason}")

Six arguments and fields worth understanding one by one.

model

Which specific model to call. Anthropic’s line-up in mid-2026:

  • claude-haiku-4-5-20251001 — small, fast, cheap. Great default for most work.
  • claude-sonnet-4-6 — mid-tier, better reasoning, still affordable.
  • claude-opus-4-7 — top tier, best reasoning, expensive.

For learning and most real applications, Haiku is the right default. Reach for Sonnet when you need better reasoning or multilingual quality; reach for Opus for the hardest tasks or when quality clearly matters more than cost.

max_tokens

Upper bound on how long the response can be, in output tokens. max_tokens=400 gives you a response of at most ~300 words. Set this deliberately — leaving it huge invites the model to ramble, which costs money.

messages

The conversation so far, as a list of {role, content} dictionaries. Roles are user (you) or assistant (the model’s past responses in a multi-turn conversation). For a single-turn call you send one user message, as here.

response.content[0].text

The generated text. .content is a list of content blocks; for text-only responses there’s exactly one block, and .text on it gives you the string. This unusual structure exists to support multi-modal responses (text + images) in the future.

response.usage

Token counts for billing. input_tokens is what you sent (including the system prompt if any); output_tokens is what came back. Multiply these by the model’s per-token prices to know the exact cost of the call.

response.stop_reason

Why the model stopped generating:

  • "end_turn" — the model finished naturally.
  • "max_tokens" — you hit the max_tokens limit; the response was truncated.
  • "stop_sequence" — you provided a custom stop sequence and it appeared.
  • "tool_use" — the model wants to call a tool (Chapter 6 territory).

Always check this in production code. A max_tokens stop means you got a partial answer.

System prompts

Every serious LLM call includes a system prompt — instructions to the model about its role and behaviour that stay in effect across the whole conversation:

response = client.messages.create(
    model="claude-haiku-4-5-20251001",
    max_tokens=400,
    system=(
        "You are a Nepali-speaking assistant helping small shopkeepers "
        "in Nepal. Answer in plain Nepali (Devanagari). Keep responses "
        "under three sentences unless asked otherwise. Do not use jargon."
    ),
    messages=[
        {"role": "user", "content": "How can I accept mobile payments?"},
    ],
)

The system prompt is where you tell the model who it is and how it should behave. Everything downstream is the user asking questions to that already-configured assistant.

Two rules for good system prompts:

  • Be specific. “You are a helpful assistant” is useless. “You are a Nepali-speaking assistant for small shopkeepers, respond in three sentences of plain Nepali” is useful.
  • Be short. Long system prompts eat input tokens on every call. Keep them tight.

What a token is, concretely

Tokens are the units the model reads and generates. They are not words — a token is typically a piece of a word, a common word, or a punctuation mark. Some examples with Claude’s tokeniser (approximate):

  • "Hello" → 1 token
  • "Kathmandu" → 1 token
  • "unfortunately" → 2 tokens ("un" + "fortunately")
  • "नमस्कार" (Devanagari) → 3-4 tokens
  • "तपाईं कस्तो हुनुहुन्छ?" → 12-15 tokens

Rules of thumb:

  • English text: ~1.3 tokens per word.
  • Nepali (Devanagari): ~2-3 tokens per word — roughly 2x English.
  • Code: variable, but usually a bit denser than English.
  • JSON: dense in punctuation, so more tokens per character than prose.

For a Nepali-heavy application, always budget in tokens, not characters. A 500-word Nepali response is around 1000-1500 tokens.

Predicting cost

For a Claude Haiku call with 500 input tokens and 200 output tokens, at late-2025 prices (~$0.25/M input, $1.25/M output):

cost = (500 / 1_000_000) * $0.25 + (200 / 1_000_000) * $1.25
     = $0.000125 + $0.00025
     = $0.000375

Three ten-thousandths of a dollar. For a million such calls per month:

monthly = 1_000_000 * $0.000375 = $375

Manageable. The same call on Opus would be about $0.024 — sixty times more, and $24,000/month at the same volume. Model choice is real money at scale.

Streaming responses

For interactive UIs, you rarely want to wait for the full response before showing anything. Enable streaming and text arrives token by token:

with client.messages.stream(
    model="claude-haiku-4-5-20251001",
    max_tokens=400,
    messages=[
        {"role": "user", "content": "Explain NEPSE to a shopkeeper in Nepali."},
    ],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
    print()

Same call as before, but you see words appear as they’re generated. Perceived latency drops dramatically. For any chat-style UI, streaming is the default; batch responses are for background jobs and scripts.

A minimal, honest starter script

Every serious project starts with a small utility that wraps the API call, handles the boring bits, and returns clean output:

import os
from dataclasses import dataclass
from dotenv import load_dotenv
import anthropic

load_dotenv()
_client = anthropic.Anthropic()


@dataclass
class LLMResponse:
    text: str
    input_tokens: int
    output_tokens: int
    stop_reason: str
    cost_usd: float


HAIKU_INPUT_PER_M  = 0.25
HAIKU_OUTPUT_PER_M = 1.25


def ask(user_message: str, system: str = "", max_tokens: int = 400) -> LLMResponse:
    response = _client.messages.create(
        model="claude-haiku-4-5-20251001",
        max_tokens=max_tokens,
        system=system if system else anthropic.NOT_GIVEN,
        messages=[{"role": "user", "content": user_message}],
    )
    text = response.content[0].text
    in_tok, out_tok = response.usage.input_tokens, response.usage.output_tokens
    cost = (in_tok / 1_000_000) * HAIKU_INPUT_PER_M + (out_tok / 1_000_000) * HAIKU_OUTPUT_PER_M
    return LLMResponse(text, in_tok, out_tok, response.stop_reason, cost)


if __name__ == "__main__":
    r = ask(
        "Summarise today's Kathmandu weather in two Nepali sentences.",
        system="You are a friendly Nepali weather assistant.",
    )
    print(r.text)
    print(f"\n[cost: ${r.cost_usd:.5f}{r.input_tokens} in / {r.output_tokens} out]")

Thirty lines. Clean interface. Cost visible on every call. This is the shape you’ll build on for the rest of Course 04.

Check your understanding

Quick check

Your LLM call returns text but `stop_reason` is `'max_tokens'`. What does that tell you, and what should you do?

Quick check

An app calls Claude Haiku for every user message. Average call is 300 input tokens and 400 output tokens. Prices: $0.25 per million input, $1.25 per million output. What's the approximate cost per 10,000 user messages?

What comes next

You have a call, you know what it costs, you know why it stopped. The last piece of Chapter 1 is temperature — the single most important knob for controlling how deterministic (or creative) the output is. Setting it right for your task is the difference between a useful assistant and one that either bores or hallucinates.