How programs use ready-made AI models
Nobody trains large models from scratch for every program – training takes days and costs a lot. Programs use ready-made, already trained models. In this lesson you will learn two ways: how to save and reuse your own model, and how a program “talks” to a language model through an API.
The part about APIs describes the situation as of November 2026 and is updated once a year.
Way 1: save your model
The network from the previous lesson learns in a few seconds. With bigger models this takes much longer, so after training we save the model to a file and later just load it. The library joblib is used for this; it is installed together with scikit-learn.
# We train the network once and save it to a file – later we use it without training again
import joblib # comes with scikit-learn
from sklearn.datasets import load_digits
from sklearn.neural_network import MLPClassifier
digits = load_digits()
network = MLPClassifier(hidden_layer_sizes=(64,), max_iter=500, random_state=0)
network.fit(digits.data / 16.0, digits.target) # we train on all the images
joblib.dump(network, "model_digits.joblib") # saving to disk
print("The model was saved to the file model_digits.joblib")
Program output:
The model was saved to the file model_digits.joblib
Now a second program loads the model and uses it right away – without training. We “draw” the digit with numbers from 0 to 16:
# A ready-made model: we load the saved network and recognize a digit we “drew” ourselves
import joblib
network = joblib.load("model_digits.joblib") # no training – the model has already been trained
# the digit 7 drawn with numbers from 0 (white) to 16 (black), 8 rows of 8 pixels
seven = [
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 4, 16, 16, 16, 16, 12, 0],
[0, 0, 0, 0, 0, 14, 8, 0],
[0, 0, 0, 0, 6, 15, 1, 0],
[0, 0, 0, 0, 14, 8, 0, 0],
[0, 0, 0, 6, 15, 1, 0, 0],
[0, 0, 0, 13, 9, 0, 0, 0],
[0, 0, 0, 15, 4, 0, 0, 0],
]
row = [p / 16.0 for line in seven for p in line] # 64 numbers in one row, from 0 to 1
print("The network says:", network.predict([row])[0])
probabilities = network.predict_proba([row])[0]
most_likely = sorted(range(10), key=lambda c: -probabilities[c])[:3]
for c in most_likely:
print(f" digit {c}: {probabilities[c] * 100:.1f} %")
Program output:
The network says: 7
digit 7: 98.8 %
digit 2: 1.1 %
digit 3: 0.0 %
predict_proba gives the probabilities for each digit – the network is 98.8% “sure” it's a seven. This is how models are used in applications too: someone trains and saves them, and the application just loads them.
Way 2: API – the program asks a model over the network
An API (application programming interface) is an “agreement” on how one program asks another for something. With language models it looks like this:
- Our program sends a request (for example a question) to a certain address.
- At that address a program with the model is running; it calculates the answer.
- The answer comes back to our program, usually in JSON format (text that looks like a Python dictionary).
The model can run on a company's server (then you need an account and an API key) or on your computer. The second way is better for school: the free program Ollama runs open language models locally, without an account and without sending data to the internet.
ollama pull llama3.2. If that isn't possible, you can follow the lesson just by reading – the program also works without Ollama, it just prints a message that Ollama is not running.# How a program uses a language model through an API
# The example works with the program Ollama, which runs a language model ON YOUR COMPUTER (without an account).
# Before running: install Ollama (ollama.com) and run in the terminal: ollama pull llama3.2
import json
import urllib.request
ADDRESS = "http://localhost:11434/api/generate" # Ollama listens on your computer (localhost)
def ask(question, model="llama3.2"):
"""Send a question to the model and return the text of the answer."""
request = {"model": model, "prompt": question, "stream": False}
data = json.dumps(request).encode("utf-8")
req = urllib.request.Request(ADDRESS, data=data, headers={"Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=120) as answer:
result = json.loads(answer.read().decode("utf-8"))
return result["response"] # the text of the answer is in the field "response"
try:
print(ask("Explain in two sentences what a neural network is, for an 8th-grade student."))
except OSError:
print("Ollama is not running – check whether it is installed and running.")
json.dumpsconverts a Python dictionary into JSON text;json.loadsdoes the opposite."stream": Falseasks for the whole answer at once (otherwise it arrives word by word).localhostmeans “this computer” – the request doesn't go out to the internet.- The model's answer is different every time you run it – remember the lesson How chatbots work.
API key: a password you don't share
Services on the internet require an API key – a long secret code by which they know who is sending the request (and whom to charge). The rules:
- never write the key directly into code that you share, send or put on the internet (for example on GitHub);
- keep it in an environment variable or a separate file that you don't share;
- if the key “leaks” – delete it immediately in the service settings and create a new one.
# the key is read from an environment variable, not written into the code
import os
key = os.environ.get("AI_API_KEY")
if key is None:
print("Set the environment variable AI_API_KEY.")
For students under 18, accounts on commercial AI services often require parental consent or are not allowed – that is why in this course we use our own and local models.
All students do the first part (saving and loading a model). The teacher shows the second part on the projector: students suggest questions, and then together they check whether the answers are correct.
Common misconceptions
- “A program “contains” AI as soon as it uses an API” – the program only sends a question to a model running somewhere else and shows the answer.
- “An API key is like a username – it can be shown” – the key is a secret, like a password; whoever has it can use your account.
Practice tasks
Try it yourself first, and only then open the solution.
- “Draw” the digit 1 with numbers from 0 to 16 and check what the saved model says. Try a thin and a thick line.
- Make a small “chatbot” in the terminal: the program reads a question in a loop (
input) and sends it to the local model, until the user types “end”. - Why must an API key not be written into code that you put on GitHub?
Solution 1: the digit one
# Task: draw the digit 1 and check what the saved model says
import joblib
network = joblib.load("model_digits.joblib")
thin = [ # the digit 1 drawn with a thin line
[0, 0, 0, 0, 12, 0, 0, 0],
[0, 0, 0, 10, 16, 0, 0, 0],
[0, 0, 8, 6, 16, 0, 0, 0],
[0, 0, 0, 0, 16, 0, 0, 0],
[0, 0, 0, 0, 16, 0, 0, 0],
[0, 0, 0, 0, 16, 0, 0, 0],
[0, 0, 0, 0, 16, 0, 0, 0],
[0, 0, 0, 8, 16, 8, 0, 0],
]
thick = [ # the same one, with a thicker line – like in the training data
[0, 0, 0, 12, 13, 0, 0, 0],
[0, 0, 6, 16, 16, 0, 0, 0],
[0, 0, 10, 14, 16, 0, 0, 0],
[0, 0, 0, 8, 16, 0, 0, 0],
[0, 0, 0, 8, 16, 0, 0, 0],
[0, 0, 0, 8, 16, 0, 0, 0],
[0, 0, 0, 8, 16, 0, 0, 0],
[0, 0, 0, 10, 16, 6, 0, 0],
]
for name, picture in [("thin", thin), ("thick", thick)]:
row = [p / 16.0 for line in picture for p in line]
print(f"{name} one -> the network says: {network.predict([row])[0]}")
Program output:
thin one -> the network says: 3
thick one -> the network says: 1
The network classifies the thin one as a three! In the training data, ones are written with a thick line, so the model “doesn't recognize” different handwriting. This is the same problem as with Teachable Machine: the model knows only what it has seen in the data.
Solution 2: a chatbot in the terminal
# Task: a small “chatbot” in the terminal – questions are sent to the local model until you type “end”
import json
import urllib.request
def ask(question, model="llama3.2"):
request = json.dumps({"model": model, "prompt": question, "stream": False}).encode("utf-8")
req = urllib.request.Request("http://localhost:11434/api/generate", data=request,
headers={"Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=120) as answer:
return json.loads(answer.read().decode("utf-8"))["response"]
while True:
question = input("You: ")
if question.strip().lower() == "end":
break
try:
print("Model:", ask(question))
except OSError:
print("Ollama is not running.")
break
If Ollama is not running, the program prints a message and ends – it doesn't “crash”, because the error is caught by try … except OSError.
Solution 3: explanation
Because then anyone can read it and use your account – at your expense. The key is kept in an environment variable or in a file that isn't shared, and a leaked key is cancelled immediately.
What's next
You have finished the module Programming artificial intelligence in Python. In the next module, artificial intelligence leaves the computer: AI and the Internet of Things – the ESP32 and micro:bit collect data, and models make decisions. Until then, take a look at the course Arduino and ESP32 (SR).
Check your knowledge
Open the quiz
Quiz: ready-made models and APIs
1. What is joblib.dump used for?
2. What is an API?
3. Where should an API key be kept?
4. Why did the network classify the thin one as a three?
