AI without an LLM: build your own AI model Lesson 20 of 25
Lesson 20. Stop on conflicts and expired records
If a notice board has two different notices for one activity, choosing the first is unsafe. Once a notice has expired, its old schedule cannot be presented as current. Combine question parsing, lookup, and these two checks.
This text was translated with AI.
Why this matters
If a notice board has two different notices for one activity, choosing the first is unsafe. Once a notice has expired, its old schedule cannot be presented as current. Combine question parsing, lookup, and these two checks.
Before running
valid_until is the last calendar day on which the card is valid, inclusive. It uses the same year-month-day form. from datetime import date imports Python’s calendar date type. date.today() reads the computer’s date; date.fromisoformat(...) converts text into a date we can compare. The computer clock must be correct. != means “not equal”; or means either condition is enough.
[
{"club": "шахмат", "kind": "уақыт", "value": "бейсенбі, 15:00", "source": "club-sheet-01", "checked_on": "2026-09-01", "valid_until": "2026-12-31"},
{"club": "шахмат", "kind": "орын", "value": "203-бөлме", "source": "club-sheet-01", "checked_on": "2026-09-01", "valid_until": "2026-12-31"}
]
From the project root, enter the step folder and run the program:
cd course/kazakh-ai/step-20
python3 model.py
On Windows, use py model.py instead of the last command.
import json
from datetime import date
with open("facts.json", encoding="utf-8") as file:
facts = json.load(file)
question = input("Сұрақ: ").lower().replace("?", "").replace(",", "")
words = question.split()
entities = []
intents = []
for word in words:
if word in ["шахмат", "сурет"]:
entities.append(word)
if word == "қашан":
intents.append("уақыт")
if word == "қайда":
intents.append("орын")
if len(entities) != 1 or len(intents) != 1:
print("нақтылаңыз: бір үйірме және бір сұрақ түрі керек")
else:
club = entities[0]
kind = intents[0]
matches = []
for fact in facts:
if fact["club"] == club and fact["kind"] == kind:
matches.append(fact)
if len(matches) == 0:
print("білмеймін: дерек жоқ")
elif len(matches) > 1:
print("тоқта: бірнеше дерек табылды")
else:
fact = matches[0]
today = date.today()
until = date.fromisoformat(fact["valid_until"])
if today > until:
print("білмеймін: дерек ескірген")
elif kind == "уақыт":
print(fact["club"], "үйірмесінің уақыты:", fact["value"])
print("Дереккөз:", fact["source"], "| тексерілген күні:", fact["checked_on"])
else:
print(fact["club"], "үйірмесінің орны:", fact["value"])
print("Дереккөз:", fact["source"], "| тексерілген күні:", fact["checked_on"])
How the program works
First, the lesson 15 logic extracts exactly one activity and one information type. Then we scan the whole catalog. Zero records means missing information; two or more mean a possible conflict or duplicate that a person should review. Only for one card do we compare dates: today > until becomes true the day after valid_until. Only then do we print the answer and source. checked_on records a past check; valid_until sets the expiry. They serve different purposes. A bad source sheet, a wrong computer clock, and limited vocabulary can still cause errors; the model does not guarantee truth.
Support map
Question → exactly two keys → 0/1/many records → expiry of one record → sourced answer or clear stop.
Recall and check
Try Шахмат қашан?, then Сурет қайда?. Through 31 December 2026, the first answer is шахмат үйірмесінің уақыты: бейсенбі, 15:00 plus a source line; afterwards it is білмеймін: дерек ескірген. The second is always білмеймін: дерек жоқ. To test a conflict, add a second шахмат / уақыт card with another value: expect тоқта: бірнеше дерек табылды. To test expiry, set valid_until to a past date. Common mistake: deleting an old card before finding the cause of the conflict.
If you have found a mistake or a typo in this article, tell us about it
Comments (0)
Log in to leave a comment →
No comments yet. Be the first.