Je hebt vast al eens gewerkt met ChatGPT van OpenAI of één van de andere varianten, Gemini van Google of Claude van Anthropic bijvoorbeeld. Zulke diensten zijn leuk en kunnen al veel voor je doen, maar interessanter wordt het als je je eigen tools kunt bouwen met AI.
In deze tutorial leer je daarom werken met de OpenAI API. Een API is een manier om vanuit je eigen programma te communiceren met een ander programma, vaak via het internet. Je kunt op deze manier de AI-modellen van OpenAI gebruiken zonder naar hun website te gaan.
Het project
In dit project maak je een script dat jou toetst over een bepaald onderwerp. Je geeft een Wikipedia-URL op en met behulp van AI maak je hier automatisch een samenvatting van én maak je drie vragen waarmee je kennis over het gegeven onderwerp kunt toetsen. Uiteraard krijg je ook de correcte antwoorden!
Let op: om te kunnen werken met de API van OpenAI heb je een account nodig. In tegenstelling tot ChatGPT is het gebruik van de API niet gratis, je betaalt naar gebruik.
Zie deze pagina voor meer informatie over de kosten. Het kost je niet veel, zeker niet bij kleinere projecten zoals deze. Bovendien kun je een bovengrens instellen, zodat je nooit tegen onverwachte kosten aanloopt.
Maak nu eerst een account als je die nog niet hebt. Nadat je alles hebt ingesteld, kun je een apart project in de OpenAI Dashboard aanmaken. Klik eerst linksbovenin op je (organisatie)naam en vervolgens op "Create project". Maak een nieuw project aan met de naam "WikiTest".
Vervolgens maak je een API-key aan voor het project. Ga naar de API keys pagina en klik op "Create new secret key". Geef het een naam, kies het zojuist aangemaakte project en klik op "Create secret key". LET OP: kopieer de API-key direct en sla het op een veilige plek op, je krijgt het niet nogmaals te zien.
Als je een account en een API-key hebt aangemaakt, maak je een nieuw Python project aan en installeer je de drie externe packages die je gaat gebruiken: openai
, wikipedia-api
en python-dotenv
. De openai
package is de client om met de API van OpenAI te communiceren. De wikipedia-api package is een handig hulpmiddel om pagina's van Wikipedia op basis van een titel op te halen en de tekst in te lezen. Het is een client om te communiceren met de Wikipedia API. De python-dotenv
package tot slot is een hulpmiddel om op een veilige manier je API-key in te kunnen lezen, waarover later meer.
shell
cd projects
mkdir wikitest && cd wikitest
python -m venv .venv
source .venv/bin/activate # .venv\Scripts\activate.bat voor Windows
python -m pip install openai wikipedia-api python-dotenv
python -m pip freeze > requirements.txt
Je kunt de code van dit project ook op Github bekijken.
API-key
Je API-key is persoonlijk, als deze in de verkeerde handen valt kan iemand het gebruiken en draai jij voor de kosten op. Het is daarom belangrijk om deze geheim te houden. Hier zijn verschillende manieren voor. In dit project gebruik je python-dotenv
. Je maakt een .env
bestand in je project aan, waarin je de API-key noteert.
.env
OPENAI_API_KEY=sk-proj-123abc
Noem je API-key OPENAI_API_KEY
en de openai client zal het automatisch inlezen. Zie ook de documentatie van OpenAI.
Maak ook een .gitignore
-bestand aan, waarin je aangeeft dat het .env
bestand niet in je repository opgenomen mag worden.
.gitignore
.env
.venv
*.pyc
__pycache__
Ook al gebruik je nu (nog) geen Git, het is toch verstandig alvast wel een .gitignore
aan te maken.
Ben je wel zover om versiebeheer te gaan doen met Git en je pusht je code naar bijvoorbeeld Github, dan zal je API-key
niet per ongeluk meegestuurd worden.
Wikipedia pagina inlezen
Om een samenvatting van en toetsvragen over een Wikipedia-pagina te maken, moet je de pagina wel kunnen laten lezen door het AI-model. Er zijn hiervoor verschillende manieren, maar om het zo platform-onafhankelijk te houden, lees je eerst de pagina zelf in als platte tekst. Deze tekst kun je dan weer naar het model sturen.
Wikipedia heeft gelukkig een API zodat de pagina eenvoudig programmatisch is in te lezen. En met de package wikipedia-api
wordt dit proces nog eenvoudiger.
Maak in je project een bestand wiki.py
aan en plaats hierin de volgende code.
wiki.py
import wikipediaapi
USER_AGENT = "WikiTest (info@python-cursus.nl)"
LANGUAGE = "nl"
def read_wiki(titel):
"""Lees een Wikipedia-artikel in."""
# Initialiseer de Wikipedia client
wiki = wikipediaapi.Wikipedia(
user_agent=USER_AGENT,
language=LANGUAGE,
extract_format=wikipediaapi.ExtractFormat.WIKI
)
# Haal de pagina op, op basis van titel
page = wiki.page(titel)
# Controleer of de pagina bestaat
if not page.exists():
raise ValueError("Pagina bestaat niet")
# Geef de tekst terug
return page.text
Met deze functie kun je een Wikipedia-pagina inlezen op basis van een op te geven titel. Zorg ervoor dat je de USER_AGENT
aanpast naar je eigen gegevens.
Zie de documentatie van Wikipedia API voor meer over het gebruik van de package.
Samenvatting en toets maken
Nu je een Wikipedia-pagina in kunt lezen, is de volgende stap het maken van een samenvatting en toetsvragen over de tekst. Hiervoor gebruik je een AI-model, in dit voorbeeld via de API van OpenAI. In de kern is het werken met de API van OpenAI eenvoudig. De aanroep ziet er als volgt uit:
openai
client = OpenAI()
response = client.chat.completions.create(
model=MODEL, # Bijvoorbeeld 'gpt-4o'
response_format={"type": "json_object"},
messages=[system_message, user_message]
)
Je roept de completions-endpoint aan, met het gekozen model, de bericht(en) die je wilt sturen en optioneel een formaat waarin het antwoord teruggegeven moet worden.
Er zijn nog meer opties beschikbaar, maar voor nu volstaat dit. Zie de documentatie voor meer informatie.
De berichten (messages) bestaan uit een lijst met één of meer berichten. Een bericht bestaat uit een dict
met de sleutels role
en content
. De rollen zijn onder ander system
, user
en assistant
. De berichten zijn de berichten die je ook in ChatGPT zou zien, dus jouw berichten en de reactie van het model (assistant
). Het verschil hier is dat je ook de reactie van het model op kunt sturen. Dit kan nodig zijn als je een applicatie maakt waarbij je de geschiedenis van het gesprek wilt behouden.
De messages
voor dit project kun je als volgt opstellen:
messages
# Bereid de instructies voor
# Zorg ervoor dat het model JSON teruggeeft
system_message = {
"role": "system",
"content": """
Je bent een assistent die Wikipediapagina's samenvat en vragen bedenkt voor
studenten om hun kennis te toetsen. Je reageert altijd in JSON.
"""
}
# Zorg ook voor een voorbeeld van hoe de JSON eruit moet zien.
# Er zijn geen garanties dat het model zich hier aan houdt, maar
# in de praktijk gaat het 99% van de tijd wel goed.
user_prompt = """
Lees de tekst die hierna volgt\n.
Maak een samenvatting van de tekst in maximaal drie zinnen\n.
Maak drie meerkeuzevragen met opties A, B en C over het onderwerp.
Er kan steeds 1 antwoord goed zijn\n.
Geef van elke vraag aan wat het goede antwoord is (A, B of C)\n.
Gebruik het volgende JSON-schema: \n\n
{
"samenvatting": "De samenvatting",
"vragen: [
{
"vraag": "De eerste vraag",
"opties: ["A: Optie A", "B: Optie B", "C: Optie C"],
"antwoord": A
},
{
"vraag": "De tweede vraag",
"opties: ["A: Optie A", "B: Optie B", "C: Optie C"],
"antwoord": B
},
]
}
De tekst is als volgt:\n\n
"""
user_message = {
"role": "user",
"content": user_prompt + text
}
Hierbij is text
op het de een-na-laatste regel de ingelezen Wikipediapagina.
Het is erg belangrijk om in je prompt aan te geven dat je JSON als output wilt, ook al heb je dit eerder al aangegeven bij het aanroepen van de API. In dit geval is dat in de system prompt gedaan. Zie de JSON mode documentatie voor meer toelichting hierop.
Het is ook belangrijk om een voorbeeld te geven van de gewenste JSON-structuur. Zo weet het model beter wat het terug moet geven. Doe je dit niet, dan is de kans groter dat bijvoorbeeld de sleutels ("vraag", "opties", "antwoord", etc.) soms een andere naam krijgen (bijvoorbeeld "antwoordopties" in plaats van "opties"). Omdat je later met de sleutels wilt werken, wil je wel dat dit consistent is.
Werken met Large Language Models blijft fundamenteel onzeker. Door het opgeven van voorbeelden haal je veel van de onzekerheid weg, maar het is niet gegarandeerd dat de gewenste JSON-structuur elke keer wordt teruggegeven. Houd hier rekening mee in de rest van je code.
Plaats bovenstaande nu in een functie create_text
, in een bestand toets.py
.
toets.py
def create_test(text):
"""
Gebruik OpenAI om de opgegeven tekst samen te vatten en er een toets over te maken.
"""
client = OpenAI()
# Bereid de instructies voor
# Zorg ervoor dat het model JSON teruggeeft
# ...
# Haal de response op
# ...
return response.choices[0].message.content
Bekijk de complete code op Github
De toets afnemen
Je hebt nu de code om een Wikpedia-pagina in te lezen en de code om hiervan met behulp van AI een samenvatting en een toets van te maken. De laatste stap is het daadwerkelijk afnemen van de toets. Voor dit voorbeeld kun je het eenvoudig houden door de input
-functie te gebruiken. Uiteraard zou je het uitgebreider kunnen maken door er bijvoorbeeld een webapplicatie van te maken.
Maak hiervoor een functie take_test
in het bestand toets.py
. In vereenvoudigde vorm ziet het eerste deel van deze functie er als volgt uit:
toets.py
def take_test():
print("Geef de titel op (haal dit uit de url, na '/wiki/'")
titel = input("Titel: ")
# Lees de Wikipedia-pagina in
text = read_wiki(titel=titel)
# Maak de samenvatting en toets
result = create_test(text=text)
# Zet om van JSON naar dict
result_json = json.loads(result)
samenvatting = result_json.get("samenvatting")
vragen = result_json.get("vragen")
In een volledige versie gebruik je try/except
-blokken om eventuele fouten af te handelen.
Het laatste deel van de functie:
toets.py
def take_test():
# ...
# Toon samenvatting
print("\nSAMENVATTING")
print(samenvatting)
# Begin de toets. Elke vraag bestaat uit een `dict` met vraag,
# opties en correct antwoord.
print("TOETS")
for vraag in vragen:
print(f"Vraag: {vraag['vraag']}\n")
for optie in vraag["opties"]:
print(optie)
user_antwoord = input("Wat is je antwoord (A, B of C)? ")
if user_antwoord.upper() == vraag["antwoord"]:
print("Goed!\n")
else:
print(f"Helaas, het goede antwoord is {vraag['antwoord']}\n")
Toon eerst de samenvatting. Vervolgens itereer je over alle vragen en de antwoordopties en controleer je of de gebruiker hetzelfde antwoord geeft als het goede antwoord.
Bekijk de complete code op Github
Nu rest alleen nog de code aan te roepen in main.py
:
main.py
from dotenv import load_dotenv
from toets import take_test
if __name__ == '__main__':
load_dotenv()
take_test()
Gebruik load_dotenv()
om je .env
bestand met je API-sleutel van OpenAI in te lezen. Vervolgens roep je take_test()
aan en ben je klaar om je code uit te proberen!
shell
python main.py
Over welke Wikipediapagina wil je een toets maken?
Geef de titel op (haal dit uit de url, na '/wiki/'
Titel: Guido_van_Rossum
SAMENVATTING
Guido van Rossum is een Nederlandse informaticus, bekend als de ontwerper van de programmeertaal Python. Hij ontving in 1999 de Dr. Dobb's
Journal Excellence in Programming Award en diverse andere accolades voor zijn bijdragen aan de softwareontwikkeling.
Van Rossum woonde in Nederland en sinds 1995 in de VS, en werkte voor bedrijven zoals Google, Dropbox en Microsoft.
TOETS
Vraag: In welk jaar ontwierp Guido van Rossum de programmeertaal Python?
A: 1980
B: 1989
C: 1999
Wat is je antwoord (A, B of C)? b
Goed!
// etc
Conclusie
In deze tutorial heb je een eenvoudig programma gemaakt dat een Wikipedia-pagina inleest en er vervolgens met behulp van de OpenAI API een samenvatting van maakt en er een toets over maakt. Het is een eenvoudig voorbeeld om te laten zien dat je ook op andere manieren AI-modellen kunt gebruiken dan via een chat-interface.
Het voordeel is dat je hiermee bepaalde taken kunt automatiseren, dus niet steeds weer je opdrachten in een chat typen! Een ander voordeel is dat je eenvoudig je eigen input mee kunt geven, zoals documenten of inhoud uit spreadsheets. Vervolgens kun je de response weer programmatisch verwerken.
Dit voorbeeld was met OpenAI, maar bekijk ook eens de API's van andere aanbieders. Veelal hebben ze zelf ook een Python-client en is de werking vrijwel hetzelfde als die van OpenAI.
Enkele voorbeelden:
De mogelijkheden zijn eindeloos. Veel succes!