OverpayingForAIPricing desk

Lesson 6 of 6 · 14 min read · Beginner

Ship a tiny tool you actually use

Put lessons 1 to 5 into one 30-line script with a cost ceiling, a cheap default and an escalation path. Finish the course with something on your machine that works.

In this lesson you will

  • Write and run a small script that does a real job
  • Build in the spend ceiling and cheap-first routing from earlier lessons
  • Know what to change when your needs grow

Courses that end in theory get forgotten. This one ends with a file on your disk. The tool below turns any text file into a structured summary, defaults to a cheap model, escalates only when you ask, and refuses to run if the job would cost more than you allowed.

pythonsummarise.py — the whole thing. Every line is explained below.
#!/usr/bin/env python3
"""Summarise a text file into structured JSON. Cheap by default."""
import json, os, sys, urllib.request

CHEAP = "google/gemini-2.5-flash-lite"   # $0.10 in / $0.40 out per 1M
STRONG = "anthropic/claude-sonnet-5"     # $2.00 in / $10.00 out per 1M
MAX_SPEND = 0.05                         # hard ceiling, in dollars

RATES = {CHEAP: (0.10, 0.40), STRONG: (2.00, 10.00)}

def estimate(text, model, out_tokens=400):
    tokens_in = len(text) / 4          # ~4 characters per token
    rate_in, rate_out = RATES[model]
    return tokens_in / 1e6 * rate_in + out_tokens / 1e6 * rate_out

def main():
    path = sys.argv[1]
    model = STRONG if "--strong" in sys.argv else CHEAP
    text = open(path, encoding="utf-8").read()

    cost = estimate(text, model)
    if cost > MAX_SPEND:
        sys.exit(f"Refusing: estimated ${cost:.4f} exceeds ceiling ${MAX_SPEND}")
    print(f"[{model}] estimated ${cost:.6f}", file=sys.stderr)

    body = json.dumps({
        "model": model,
        "max_tokens": 400,
        "messages": [{"role": "user", "content":
            "Return JSON with keys summary, decisions, risks.\n\n" + text}],
    }).encode()

    req = urllib.request.Request(
        "https://openrouter.ai/api/v1/chat/completions", data=body,
        headers={"Authorization": f"Bearer {os.environ['OPENROUTER_API_KEY']}",
                 "Content-Type": "application/json"})
    with urllib.request.urlopen(req) as r:
        data = json.load(r)

    print(data["choices"][0]["message"]["content"])
    u = data["usage"]
    rate_in, rate_out = RATES[model]
    actual = u["prompt_tokens"] / 1e6 * rate_in + u["completion_tokens"] / 1e6 * rate_out
    print(f"[actual ${actual:.6f} — {u['prompt_tokens']} in, "
          f"{u['completion_tokens']} out]", file=sys.stderr)

if __name__ == "__main__":
    main()
Running your tool

Save the script, make it executable, and point it at a file.

recorded session — not a live shell0 / 3
  1. chmod +x summarise.py && ./summarise.py transcript.txtEstimate first, then the answer, then what it really cost. Estimated $0.000702 against $0.000602 actual — the character-per-token approximation ran 16% high, which is the direction you want it to be wrong.
  2. ./summarise.py transcript.txt --strongThe strong model is noticeably richer — and 21x the price. Now you have both numbers and can decide per job instead of per habit.
  3. ./summarise.py enormous-report.txtThe ceiling doing its job. It stopped before spending, not after — which is the entire difference between a limit and an alert.

Your own numbers will differ — token counts depend on your text, and rates move. The arithmetic is what transfers.

What each piece is doing

  • CHEAP / STRONG constants — lesson 4's routing rule, made explicit. The default is cheap; expensive is a flag you have to type.
  • MAX_SPEND — lesson 3's ceiling. It refuses rather than warns.
  • estimate() — the four-characters-per-token approximation. Rough, and rough is enough to catch a job that is 100× larger than you thought.
  • max_tokens: 400 — the seatbelt on the expensive half of the bill.
  • The actual-cost line — closes the loop. Every run teaches you whether your estimates are any good.

Where to go next

  1. 1

    Change the prompt

    The keys in that JSON are yours to choose. Make it extract what your actual job needs.

  2. 2

    Point it at a folder

    Wrap the call in a loop over files — with lesson 3's estimate-first habit intact.

  3. 3

    Re-run lesson 4 quarterly

    The cheap tier keeps getting cheaper. Your CHEAP constant should move with it.

  4. 4

    Take the provider courses

    The 101 course for whichever model you settled on goes deeper on its plans and quirks.

Knowledge check

Why does the script estimate cost before sending rather than just reporting it after?

Lesson FAQ

Do I need Python installed?

Python 3 ships with macOS and most Linux distributions; on Windows install it from python.org. The script uses only the standard library — nothing to pip install.

Can I use a different provider?

Yes. Change the URL and the model id; the request shape is the OpenAI-compatible format that most providers accept. Update the RATES table to match, or your estimates will lie to you.

Finished reading?

Mark it done to track your progress through the course.

Save progress across devices

Get a private link that restores your lessons on any device. Email is optional and only used to send you the link.

Compare, calculate, decide

If our calculators helped you cut down on hidden AI wallet leaks, thanks for using them. A tiny fraction of your savings is what keeps our pricing indexes updated daily.

Not sure which AI is cheapest for your use case? Find out in 30 seconds — no signup required.

AI cost intelligence

Stop overpaying for AI tools

Join the OverpayingForAI list for pricing updates, cheaper alternatives, and practical buying guidance.

Now tracking 50+ AI tools, models, platforms, subscriptions, coding tools, and automation products.

We use your email only for OverpayingForAI updates. Unsubscribe anytime.