Python for AIPython 3.10+ · Pydantic 2.12
Dashboard
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
34 small wins to finish your pathNext lesson →

Stand-in model

A stand-in model is a plain Python function that answers the way a language model does, so a program can be built and tested with no API key.

Last updated: 30 Sep, 2026 · Python 3.14

A real model needs an API key and charges for every call. For learning, a function that answers in the same shape is free, instant and easy to read. It uses Functions and JSON.

Writing ask_model

A model asked to sort a ticket as JSON sends back a string. Usually it is the JSON you asked for. Sometimes it is a polite sentence instead. The stand-in does both:

Example
def ask_model(ticket_text):
    text = ticket_text.lower()
    if "charged" in text or "refund" in text:
        return '{"category": "billing", "priority": 4}'
    if "parcel" in text or "arrived" in text:
        return '{"category": "shipping", "priority": 3}'
    return "I am not sure how to sort this one."

print(ask_model("I was charged twice for one order"))
print(ask_model("How do I change my password?"))

It returns strings, not dictionaries, because that is what arrives from a real model: text, which your program then has to read. It decides from the words in the ticket, so a different ticket gets a different answer.

Project files used on this pageThis lesson builds on a project from earlier lessons. The code below imports this file. Click a file to see its code, or follow the link to the lesson that wrote it. To run the code yourself, keep it in the same folder.
View the code here
tickets.json
[
  {
    "id": 1,
    "customer": "Asha",
    "text": "I was charged twice for one order"
  },
  {
    "id": 2,
    "customer": "Ben",
    "text": "My parcel has not arrived"
  },
  {
    "id": 3,
    "customer": "Chen",
    "text": "Can I get a refund for the blue mug?"
  },
  {
    "id": 4,
    "customer": "Dara",
    "text": "How do I change my password?"
  },
  {
    "id": 5,
    "customer": "Eli",
    "text": "The parcel arrived but the box was crushed"
  }
]

Asking about every ticket

This reads tickets.json from JSON; keep that file in the same folder as your code.

Example
import json

with open("tickets.json") as f:
    tickets = json.load(f)

for ticket in tickets:
    answer = ask_model(ticket["text"])
    print(ticket["id"], answer)

Four answers are JSON and ticket 4's is not. Real models do this too, which is why a program that trusts every answer eventually breaks.

Parsing every answer, and where it breaks

Example
for ticket in tickets:
    data = json.loads(ask_model(ticket["text"]))
    print(ticket["id"], data["category"])

Tickets 1 to 3 print, then ticket 4's sentence reaches json.loads and the whole program stops. On your computer the error also lists lines from inside the json module; the last line is the one to read. Ticket 5 is never sorted. try and except keeps the program running.

Stand-in vs a real model

Stand-in ask_modelA real model
NeedsNothingAn API key and a network
AnswerThe same every runCan change between runs
Cost and speedFree, instantPaid per token, a second or more
ReturnsA stringA string

Where stand-ins show up in AI code

  • Tests that must run the same way every time, with no key.
  • Building the rest of a program before a model account exists.
  • The stand-in models the agent framework courses write, which follow the same idea.
Watch out. A stand-in only answers the way you wrote it. When a real model replaces it, test again: Project: ticket triage does, and the real model sorts ticket 4 differently.
Try it yourself
  • Add a branch for "password" that returns {"category": "other", "priority": 2} as JSON text, and run the loop that broke.
  • Make it return '{"category": "billing", "priority": "high"}' for refunds. It parses; is it still right? Pydantic models comes back to this.
  • Print type(ask_model("refund")).
PreviousJSON

Slow is fine. Stopping is the only problem.