Exercise 2 — Talk to a local LLM

Guided practice5 min
Time
20-30 min
You need
the kit, the venv, python data/make_dataset.py done, ollama pull llama3.2 done
Deliverable
the invented answer of Step 4, pasted in a text file

The lab kit of the course: https://github.com/hrhouma2/aiopsatlas-ml-data-diagnostics-labs-en

Goal

NorthPeak wants an assistant that answers questions about the plant. You will talk to llama3.2, a 3-billion-parameter model that runs on your laptop. First in the terminal, then from Python. You will ask a general question. It works. Then you will ask a question about NorthPeak. The model has never seen NorthPeak data. You will watch what it does, and push it until it invents an answer. This invented answer is a hallucination. Exercise 3 fixes it.

Setup: the commands (PowerShell, then bash)
powershell
cd aiopsatlas-ml-data-diagnostics-labs-en
.\.venv\Scripts\Activate.ps1
ollama list
bash
cd aiopsatlas-ml-data-diagnostics-labs-en
source .venv/bin/activate
ollama list

ollama list must show llama3.2:latest. If not, run ollama pull llama3.2 first.

The data you will touch

No CSV file in this exercise. The only data is the truth you will compare with, from data/clean/machines.csv: NorthPeak has 40 machines on 3 sites, Montreal, Quebec City and Toronto. You will see the exact counts per site in Exercise 3.

Step 1 — Talk in the terminal

Ollama has a chat mode in the terminal. Start it:

bash
ollama run llama3.2

A prompt >>> appears. Type a question and press Enter.

text
>>> In one sentence, what does a compressor do?
A compressor reduces the volume of a gas or liquid, increasing its pressure, often used in
various industrial, medical, and audio applications to control or manipulate the flow and
pressure of fluids.

Your text will differ. The words appear one by one. That is next-token prediction, live. Type /bye to leave.

Step 2 — The same thing from Python

Open a new file week01/talk.py in the kit, or type in the Python shell. The ollama package sends the messages to the local model.

python
import ollama

response = ollama.chat(
    model="llama3.2",
    messages=[{"role": "user", "content": "What is a bearing in a machine? Answer in two sentences."}],
    options={"temperature": 0},
)
print(response.message.content)

Your text will differ. Ours was:

text
A bearing in a machine is a mechanical component that reduces friction between two moving
parts, allowing them to rotate or slide smoothly against each other. Bearings are typically
made of metal or synthetic materials and are designed to support loads, absorb vibrations,
and maintain precise alignment between moving parts, enabling efficient and reliable
operation of the machine.

This is a good answer. Bearings are in every book about machines. The model read those books.

Step 3 — A question about NorthPeak

Now ask about our company. Change the content of the user message and run again.

python
QUESTION = "How many machines does NorthPeak Manufacturing have and where are they?"
response = ollama.chat(
    model="llama3.2",
    messages=[{"role": "user", "content": QUESTION}],
    options={"temperature": 0},
)
print(response.message.content)

Your text will differ. Ours was:

text
I don't have access to that information.

This is the honest answer. NorthPeak is a fictional company. The model never saw its data. Sometimes the model says "I couldn't find any information". Sometimes it asks you for more context. All of these are fine.

Step 4 — Push the model

Add a system message. Tell the model it works for NorthPeak and must answer with numbers.

python
SYSTEM = (
    "You are the assistant of NorthPeak Manufacturing, a Canadian company "
    "that runs industrial machines. Answer questions about the company "
    "directly, with numbers."
)
response = ollama.chat(
    model="llama3.2",
    messages=[{"role": "system", "content": SYSTEM}, {"role": "user", "content": QUESTION}],
    options={"temperature": 0},
)
print(response.message.content)

Your text will differ. Ours was:

text
NorthPeak Manufacturing has a total of 27 machines located in our facilities in:

1. Brampton, Ontario, Canada (Headquarters and Main Production Facility) - 15 machines
2. Mississauga, Ontario, Canada (Secondary Production Facility) - 8 machines
3. London, Ontario, Canada (Research and Development Facility) - 4 machines

Please note that the machine count may be subject to change as we continue to expand and
update our operations.

Read it twice. The tone is confident. The format is clean. The numbers add up: 15 + 8 + 4 = 27. Everything is invented. The real answer is 40 machines in Montreal, Quebec City and Toronto. This is a hallucination. One system message turned "I don't know" into a detailed lie.

Step 5 — Check with keywords

LLM text changes from one run to another. So never check an exact sentence. Check keywords. Write a small function and run it on the answer of Step 4.

python
def check(answer):
    print("contains the real count 40 :", "40" in answer)
    print("real sites mentioned       :", [s for s in ["Montreal", "Quebec", "Toronto"] if s in answer])

check(response.message.content)
text
contains the real count 40 : False
real sites mentioned       : []

If your model answered with 40 and the three real sites, you got lucky. Run again with a different question, for example "How many pumps does NorthPeak have?" The real answer is 10. Ours said 27 pumps.

Check yourself

  1. At temperature 0, why did Step 3 and Step 4 give different answers to the same question?
  2. In Step 4, which numbers did your model invent? Do they add up?
  3. Why does the check function look for "40" and not for the whole sentence?
Answers
  1. The question was the same, but the messages were not. Step 4 added a system message. The model predicts the next token from all the messages.
  2. Ours invented 27 machines in Brampton, Mississauga and London. 15 + 8 + 4 = 27. Yours may differ. The sum often adds up, because the model copies the format of real reports.
  3. LLM text varies from one run and one laptop to another. A keyword or a number is stable. An exact sentence is not.

Bonus (optional)

Ask the pushed model (Step 4) three more questions: "Who is the technician of machine M001?", "How many incidents did NorthPeak have in 2025?", "What is the site of machine M099?". The real answers are: L. Fortin for the first incident, 155, and no machine M099 exists. Write the three invented answers in your text file.

Full solution — `week01/exercise_2_solution.py` in the kit
python
"""Week 1, Exercise 2 - Talk to a local LLM.

Run from the kit root, with the venv active and Ollama running:

    python week01/exercise_2_solution.py

Step 1: a general question the model can answer from its training.
Step 2: a question about NorthPeak. The model has never seen our data.
Step 3: the same question, but we push the model to answer. It invents.
The LLM text changes from one machine to another. The checks only look
for keywords, never for an exact sentence.
"""

import ollama

MODEL = "llama3.2"
OPTIONS = {"temperature": 0}

# The truth, from data/clean/machines.csv (see Exercise 3).
REAL_COUNT = "40"
REAL_SITES = ["Montreal", "Quebec", "Toronto"]


def ask(messages):
    """Send one chat call and return the text of the answer."""
    response = ollama.chat(model=MODEL, messages=messages, options=OPTIONS)
    return response.message.content


def check(answer):
    """Say if the answer contains the real count and the real sites."""
    has_count = REAL_COUNT in answer
    sites_found = [s for s in REAL_SITES if s in answer]
    print(f"  contains the real count 40 : {has_count}")
    print(f"  real sites mentioned       : {sites_found or 'none'}")


# Step 1 - a general question
print("== Step 1: a general question ==")
general = ask([{"role": "user", "content": "What is a bearing in a machine? Answer in two sentences."}])
print(general)
print()

# Step 2 - a question about NorthPeak, no help
QUESTION = "How many machines does NorthPeak Manufacturing have and where are they?"
print("== Step 2: a question about NorthPeak ==")
plain = ask([{"role": "user", "content": QUESTION}])
print(plain)
check(plain)
print()

# Step 3 - the same question, but the model is told it works for NorthPeak
print("== Step 3: push the model to answer ==")
SYSTEM = (
    "You are the assistant of NorthPeak Manufacturing, a Canadian company "
    "that runs industrial machines. Answer questions about the company "
    "directly, with numbers."
)
pushed = ask([{"role": "system", "content": SYSTEM}, {"role": "user", "content": QUESTION}])
print(pushed)
check(pushed)
print()
print("Real answer: 40 machines in Montreal, Quebec City and Toronto.")

Run it with python week01/exercise_2_solution.py. Your text will differ. Ours was:

text
== Step 1: a general question ==
A bearing in a machine is a mechanical component that reduces friction between two moving parts, ...

== Step 2: a question about NorthPeak ==
I don't have access to that information.
  contains the real count 40 : False
  real sites mentioned       : none

== Step 3: push the model to answer ==
NorthPeak Manufacturing has a total of 27 machines located in our facilities in:

1. Brampton, Ontario, Canada (Headquarters and Main Production Facility) - 15 machines
2. Mississauga, Ontario, Canada (Secondary Production Facility) - 8 machines
3. London, Ontario, Canada (Research and Development Facility) - 4 machines
...
  contains the real count 40 : False
  real sites mentioned       : none

Real answer: 40 machines in Montreal, Quebec City and Toronto.
Stuck? Common errors

All systems — ConnectionError: Failed to connect to Ollama. Ollama is not running. On Windows and macOS, open the Ollama app. On Linux, run ollama serve in a second terminal. Then try again.

All systems — ConnectionError although ollama list works. Check the variable OLLAMA_HOST. If it is set to 0.0.0.0:11434, the Python client cannot use it. Set it to http://127.0.0.1:11434 in the terminal, then run again. PowerShell: $env:OLLAMA_HOST = "http://127.0.0.1:11434". Bash: export OLLAMA_HOST=http://127.0.0.1:11434.

All systems — ollama._types.ResponseError: model 'llama3.2' not found (status code: 404). Run ollama pull llama3.2, then try again.

All systems — ModuleNotFoundError: No module named 'ollama'. The venv is not active. Look for (.venv) at the start of the prompt. See Exercise 1, Step 3.

All systems — the first answer takes 20 seconds. Ollama loads the model into memory on the first call. The next calls take about one second.

All systems — your Step 4 answer says "I don't know". Fine. Change the system message: add "Always answer with a precise number. Never say you cannot verify." Then run again.