You will be able to
- Create a Python virtual environment and install the openai SDK
- Store an API key in a .env file that never reaches version control
- Point one client at OpenAI, Claude, a router or a local Ollama model
- Make a first chat request and read the answer and token usage
- Start the Study Buddy project folder you will grow through the course
What you need on your computer
You need three things: Python 3.11 or newer, a terminal and a code editor you are comfortable with. Check your version with python3 --version on macOS or Linux, or py --version on Windows. If it is older than 3.11, install a current release from the official Python website before going further.
You also need access to a language model. That can be an account with a hosted provider or a model running on your own machine. You do not need a cloud subscription, a container or a notebook server for this course: plain Python scripts in one folder are enough.
Work inside a virtual environment. A venv is a private set of packages for one project, so the libraries you install for Study Buddy cannot clash with anything else on your computer. If it ever gets into a strange state, delete the .venv folder and rebuild it in a minute.
Turn the folder into a git repository from day one with git init. Small commits after each lesson give you a way back when an experiment goes wrong, and they make it obvious if a secret file is about to be committed.
One client, many providers
Most model providers now accept requests in the same shape as the OpenAI Chat Completions API. That means one library, the official openai Python package, can talk to many services. You change the address and the key; the code stays as it is.
Our code reads exactly three settings from the environment. Keeping them outside the code lets you move from a hosted model to a local one, or from one vendor to another, by editing a single text file.
LLM_BASE_URL: the address of the API, ending in the version path the provider documents, usually/v1.LLM_API_KEY: the secret that identifies your account; a local server accepts any non-empty placeholder.LLM_MODEL: the model name spelled exactly as that provider lists it.
Where the three values come from
Typical choices are OpenAI itself, Anthropic's Claude through its OpenAI-compatible endpoint, a router such as OpenRouter that forwards requests to many model families, or Ollama on your laptop. Each provider's documentation gives the base URL and the current model names. Copy them from there rather than from old tutorials, because names change.
Compatibility is good but not perfect. Basic chat requests behave the same everywhere, while extras such as JSON modes, tool calls or image input may be missing or behave differently on some services. When a later lesson uses one of those features, try it on your provider first.
Ollama runs open-weight models on your own computer and serves an OpenAI-compatible API on port 11434. Install it, download a model with ollama pull followed by a name from its library, and set LLM_BASE_URL to that local address with the /v1 path. The key can be any placeholder, such as ollama, and ollama list shows the exact model names you can use.
Local models cost nothing per request and keep your notes on your machine. The price is hardware: small models run on an ordinary laptop, bigger ones need a strong graphics card or a lot of memory, and the smallest make more mistakes. For learning the mechanics, a small model is fine.
Some hosted catalogues and routers offer free or trial access to selected models. Those offers change often and usually come with tight rate limits, so read the current terms on the provider's site and expect the occasional refusal when you hit the limit.
Keep the key out of your code
An API key works like a password that can spend money. Anyone who reads it can send requests billed to you, so it must never appear in a script, a screenshot, a chat message or a commit.
The usual pattern is a .env file in the project folder. It holds lines such as LLM_MODEL=..., and the python-dotenv package loads them into the environment when your script starts. Add .env to .gitignore before your first commit, not after.
Next to it, keep a .env.example with the same three names and empty values. It documents what the project needs without exposing anything, and it is the file you share when a friend wants to run your app.
If a key ever leaks, revoke it in the provider's dashboard and create a new one. Deleting the commit is not enough, because copies of a public repository may already exist elsewhere.
Start Study Buddy
Study Buddy is the app you build across all 21 lessons: an assistant that explains a topic, quizzes you, searches your own notes and keeps a study plan. Today it gets its skeleton, one script that sends a question and prints the reply.
Keep everything in one folder called study-buddy. By the end of this lesson it should contain .venv, .env, .env.example, .gitignore, requirements.txt and buddy.py. Later lessons add files beside these rather than replacing them.
The SDK returns an object, not plain text. The reply lives in response.choices[0].message.content, and response.usage reports how many tokens the request consumed; tokens are the subject of the next lesson.
When a call fails, read the error type before changing anything. An authentication error points to the key, a not-found error usually to the model name or base URL, and a connection error to the address or a local server that is not running.
Keep this first script small on purpose. It has one job, sending a message and printing what comes back, and every feature you add later will be a separate function you can test on its own.
Example
buddy.py: the first Study Buddy script
# buddy.py - Study Buddy, step 1: one question in, one answer outimport osimport sys from dotenv import load_dotenvfrom openai import OpenAI load_dotenv() # copies LLM_BASE_URL, LLM_API_KEY and LLM_MODEL from .env into the environment client = OpenAI( base_url=os.environ["LLM_BASE_URL"], api_key=os.environ["LLM_API_KEY"],) def ask(question: str) -> str: response = client.chat.completions.create( model=os.environ["LLM_MODEL"], messages=[ {"role": "system", "content": "You are Study Buddy, a patient tutor. Answer in plain English."}, {"role": "user", "content": question}, ], ) return response.choices[0].message.content if __name__ == "__main__": question = " ".join(sys.argv[1:]) or "Explain what an API key is in two sentences." print(ask(question))Run it with python buddy.py "What is photosynthesis?". The same file works with every provider in this lesson; only the three lines in .env differ.
Practice
Set up the Study Buddy folder and make a first call
- Create a folder called
study-buddy, runpython3 -m venv .venvinside it, then activate it withsource .venv/bin/activate(macOS, Linux) or.venv\Scripts\activate(Windows). - Install the libraries with
pip install openai python-dotenvand record them withpip freeze > requirements.txt. - Create
.envwith your three values,.env.examplewith the names only, and a.gitignorethat lists.envand.venv/; then rungit init. - Save
buddy.pyfrom the example and run it with a question from a subject you are studying. - Break it on purpose: put a wrong key in
.env(with Ollama, a wrong model name), run again, read the error, then restore the correct value.
Done when: The terminal prints a sensible answer to your question, git status does not list .env, and the deliberate mistake produced a clear error message rather than a silent failure.
Common mistakes
- Pasting the key straight into the script or a notebook cell that is later shared or committed.
- Forgetting to activate the venv, so
pipinstalls into a different Python and the import fails. - Giving the full
/chat/completionspath as the base URL; the SDK appends that part itself. - Reusing a model name from another provider's docs; every endpoint has its own names.
Check yourself
Pick an answer to see whether it is right and why.
From the founder
Do this setup today, before you read the next lesson. Every later task builds on this folder, so run buddy.py once with a real question from your own studies and keep it working.