====== AI Python project (1) ======
<= [[python|Terug naar Python start]]\\
* [[ai-ki|AI: Kunstmatige intelegentie]]
* [[python|Python]]
=>**[[ai_python_project_code_snippets| AI Python project code snippets]]** <=
//Een project om mezelf een beetje op weg te helpen met Python en de OpenAI API.//\\
-> //De applicatie is zeker niet perfect en na een klik op de verzend knop bevriest de applicatie tot het resultaat binnen is (zie het als een preloader 8-o )//
-> **[[https://github.com/a3dijke/A3DOpenAI|A3DOpenAI project op GitHub]]**
===== Doelen =====
- De basis van Python leren
* //Ik begin pas met Python dus ik ben er van overtuigd dat de code die ik ga schrijven (op meerdere gebieden) voor verbetering vatbaar zal zijn.//
- Leren communiceren met de [[https://platform.openai.com/docs/api-reference|OpenAI API]] m.b.v. Python
- Een //(simpele / basic)// desktop applicatie bouwen met Python die kan communiceren met de OpenAI API
* //Ik wil dat met deze desktop applicatie **[[https://platform.openai.com/examples|de voorbeelden op de examples pagina van OpenAI]]** uit kan voeren//
- Afbeeldingen genereren met [[https://openai.com/dall-e-2|DALL-E 2]] //Deze afbeelding opent in de browser als deze klaar is//
----
===== Voorbereiding =====
->[[https://programmeerplaats.nl/python-installeren/|Download en installeer Python]]\\
->[[https://platform.openai.com/docs/api-reference?lang=python|Installeer openai bibliotheek voor python]]\\
python -m pip install -U pip
pip install openai
----
===== Structuur =====
app.py -> //Start applicatie//\\
-> include //(map)//\\
-- -> vieuw.py //(GUI gebruikers interface)//\\
-- -> controler.py //(besturing (callbacks ed.)//\\
-- -> api.py //(Maakt contact met en verstuur berichten met OpenAI API)//\\
-- -> dmod.py //((soort) dataModel)//
----
===== app.py =====
import tkinter as tk
from include.vieuw import MyGUI
from include.controler import Controller
from include.api import MyAPI
from include.dmod import DMod
def main():
root = tk.Tk() # create the main window VIEW BASIS ROOT
myGUI = MyGUI(root) #GUI USERSINTERFACE create an instance of the MyUI class VIEW
dmod = DMod() #DATA MODEL
api = MyAPI(dmod) #API communicatie
controller = Controller(myGUI, api, dmod) #Controller class
api.setControler(controller) #referentie controler maken in api (MijnAPI class)
controller.on_reset() # Set Defaults
root.mainloop() # start the GUI
if __name__ == "__main__":
main()
----
===== vieuw.py =====
import tkinter as tk
from tkinter import scrolledtext, ttk
class MyGUI:
def __init__(self, root):
self.root = root
self.root.geometry("1200x800")
self.root.title("A3D OpenAI API Communicator")
# Create main frame
self.main_frame = tk.Frame(self.root)
self.main_frame.pack(fill=tk.BOTH, expand=True)
# Create two kolommen
self.left_frame = tk.Frame(self.main_frame)
self.left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=10, pady=10)
self.right_frame = tk.Frame(self.main_frame)
self.right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10, pady=10)
# Create text areas in the left frame
self.text_areas = ["system", "user1", "assistant"]
self.text_area_widgets = {}
for area in self.text_areas:
labsyst = tk.Label(self.left_frame, text=f"{area}", bg="#dddddd")
labsyst.pack(pady=2, padx=10, fill="x")
st = scrolledtext.ScrolledText(self.left_frame, width=30, height=0.5, wrap=tk.WORD)
st.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
st.configure(font=("TkDefaultFont", 10), padx=4, pady=4)
self.text_area_widgets[area] = st
self.text_areas2 = ["prompt"]
for area in self.text_areas2:
labsyst = tk.Label(self.left_frame, text=f"{area}", bg="#dddddd")
labsyst.pack(pady=2, padx=10, fill="x")
st = scrolledtext.ScrolledText(self.left_frame, width=30, height=20, wrap=tk.WORD)
st.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
st.configure(font=("TkDefaultFont", 10), padx=4, pady=4)
self.text_area_widgets[area] = st
# Create upper frame in the right frame
self.upper_right_frame = tk.Frame(self.right_frame)
self.upper_right_frame.pack(side=tk.TOP, fill=tk.X)
# Create text fields in the left part of the upper right frame
self.text_fields_frame = tk.Frame(self.upper_right_frame)
self.text_fields_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.text_fields = ["temperature", "max_tokens", "frequency_penalty", "presence_penalty"]
self.text_field_widgets = {}
for field in self.text_fields:
labsyst = tk.Label(self.text_fields_frame, text=f"{field}", bg="#dddddd")
labsyst.pack(pady=2, padx=10, fill="x")
entry = tk.Entry(self.text_fields_frame)
entry.pack(fill=tk.X, padx=10, pady=10)
self.text_field_widgets[field] = entry
self.text_fields_frame2 = tk.Frame(self.upper_right_frame)
self.text_fields_frame2.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.text_fields2 = ["top_p", "stop"]
self.text_field_widgets2 = {}
for field in self.text_fields2:
labsyst = tk.Label(self.text_fields_frame2, text=f"{field}", bg="#dddddd")
labsyst.pack(pady=2, padx=10, fill="x")
entry = tk.Entry(self.text_fields_frame2)
entry.pack(fill=tk.X, padx=10, pady=10)
self.text_field_widgets2[field] = entry
# Create comboboxes in the right part of the upper right frame
self.comboboxes_frame = tk.Frame(self.upper_right_frame)
self.comboboxes_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
labsyst = tk.Label(self.comboboxes_frame, text="AI API", bg="#dddddd")
labsyst.pack(pady=2, padx=10, fill="x")
self.ai_combobox = ttk.Combobox(self.comboboxes_frame)
self.ai_combobox['values'] = ('ChatCompletion', 'Completion', 'Image')
self.ai_combobox.current(0) # set the default value
self.ai_combobox.pack(fill=tk.X, padx=10, pady=10)
labsyst = tk.Label(self.comboboxes_frame, text="Models", bg="#dddddd")
labsyst.pack(pady=2, padx=10, fill="x")
self.models_combobox = ttk.Combobox(self.comboboxes_frame)
self.models_combobox['values'] = ('gpt-3.5-turbo', 'gpt-3.5-turbo-0613', 'gpt-4', 'gpt-4-0613', 'text-davinci-003', 'text-curie-003', 'text-babbage-003', 'text-ada-003')
self.models_combobox.current(0) # set the default value
self.models_combobox.pack(fill=tk.X, padx=10, pady=10)
# Create text area in the right frame
labsyst = tk.Label(self.right_frame, text="Resultaat", bg="#dddddd")
labsyst.pack(pady=2, padx=10, fill="x")
self.st_result = scrolledtext.ScrolledText(self.right_frame, width=30, height=10, wrap=tk.WORD)
self.st_result.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
self.st_result.configure(font=("TkDefaultFont", 10), padx=4, pady=4)
# Create buttons frame
self.buttons_frame = tk.Frame(self.root)
self.buttons_frame.pack(side=tk.BOTTOM, fill=tk.X)
# Create buttons
self.buttons = ["versturen", "reset"]
self.button_widgets = {}
for button in self.buttons:
btn = tk.Button(self.buttons_frame, text=button)
btn.pack(side=tk.LEFT, padx=10, pady=10)
self.button_widgets[button] = btn
----
===== controler.py =====
class Controller:
def __init__(self, gui, api, dmod):
self.gui = gui # View USER INTERFACE
self.api = api # API
self.dmod = dmod # DATA MODEL
self.gui.button_widgets["versturen"].config(command=self.on_versturen_clicked)
self.gui.button_widgets["reset"].config(command=self.on_reset)
# CALLBACK VAN DE API hier verwerken
def api_callback(self, boodschap):
self.gui.st_result.delete("1.0", "end")
self.gui.st_result.insert("end", f"{boodschap}\n")
# KNOPPEN
def on_versturen_clicked(self):
system = self.gui.text_area_widgets["system"].get("1.0", "end-1c")
user1 = self.gui.text_area_widgets["user1"].get("1.0", "end-1c")
assistant = self.gui.text_area_widgets["assistant"].get("1.0", "end-1c")
prompt = self.gui.text_area_widgets["prompt"].get("1.0", "end-1c")
temperature = self.gui.text_field_widgets["temperature"].get()
max_tokens = self.gui.text_field_widgets["max_tokens"].get()
mod = self.gui.models_combobox.get()
fp = self.gui.text_field_widgets["frequency_penalty"].get()
pp = self.gui.text_field_widgets["presence_penalty"].get()
top_p = self.gui.text_field_widgets2["top_p"].get()
stop = self.gui.text_field_widgets2["stop"].get()
self.dmod.setDataModel(system, user1, assistant, prompt, temperature, max_tokens, mod, fp, pp, top_p, stop)
if self.gui.ai_combobox.get() == "ChatCompletion":
self.api.chat_completion()
elif self.gui.ai_combobox.get() == "Completion":
self.api.ai_completion()
elif self.gui.ai_combobox.get() == "Image":
self.api.ai_Image()
def on_reset(self):
self.gui.text_area_widgets["system"].delete("1.0", "end")
self.gui.text_area_widgets["user1"].delete("1.0", "end")
self.gui.text_area_widgets["assistant"].delete("1.0", "end")
self.gui.text_area_widgets["prompt"].delete("1.0", "end")
self.gui.st_result.delete("1.0", "end")
self.gui.text_field_widgets["temperature"].delete(0, "end")
self.gui.text_field_widgets["temperature"].insert(0, "0.5")
self.gui.text_field_widgets["max_tokens"].delete(0, "end")
self.gui.text_field_widgets["max_tokens"].insert(0, "500")
self.gui.text_field_widgets["frequency_penalty"].delete(0, "end")
self.gui.text_field_widgets["frequency_penalty"].insert(0, "0.0")
self.gui.text_field_widgets["presence_penalty"].delete(0, "end")
self.gui.text_field_widgets["presence_penalty"].insert(0, "0.0")
self.gui.text_field_widgets2["top_p"].delete(0, "end")
self.gui.text_field_widgets2["top_p"].insert(0, "1.0")
self.gui.text_field_widgets2["stop"].delete(0, "end")
self.gui.text_field_widgets2["stop"].insert(0, "")
self.gui.ai_combobox.current(0)
self.gui.models_combobox.current(0)
----
===== api.py =====
import openai
import webbrowser
class MyAPI:
def __init__(self, dmod):
self.controller = ""
self.dmod = dmod
def setControler(self, controller):
self.controller = controller
def chat_completion(self):
openai.api_key = self.dmod.api_openai_key
mod=self.dmod.aimodel
completion = openai.ChatCompletion.create(
model=f"{mod}",
messages=self.dmod.to_ai_messages(),
temperature=float(self.dmod.temperature),
max_tokens=int(self.dmod.max_tokens)
)
#print(completion.choices[0].message)
self.controller.api_callback(completion.choices[0].message.content)
def ai_completion(self):
openai.api_key = self.dmod.api_openai_key
mod=self.dmod.aimodel
prompt=self.dmod.prompt,
temperature=float(self.dmod.temperature),
top_p=float(self.dmod.top_p),
max_tokens=int(self.dmod.max_tokens)
frequency_penalty = float(self.dmod.frequency_penalty)
presence_penalty = float(self.dmod.presence_penalty)
stop = self.dmod.stop
params = {
"model": f"{mod}",
"prompt": f"{prompt}", # Jouw prompt
"temperature": float(temperature[0]),
"max_tokens": int(max_tokens),
"top_p": float(top_p[0]),
"frequency_penalty": float(frequency_penalty),
"presence_penalty": float(presence_penalty),
}
if stop != "":
params["stop"] = [stop]
response = openai.Completion.create(**params)
#print(response.choices[0])
self.controller.api_callback(response.choices[0].text)
def ai_Image(self):
openai.api_key = self.dmod.api_openai_key
response = openai.Image.create(
prompt = self.dmod.prompt,
n = 1,
size = "1024x1024",
response_format = "url"
)
# Toon de URL van de gegenereerde afbeelding
#print(response)
self.controller.api_callback(response.data[0].url)
# open url in browser
webbrowser.open(response.data[0].url)
----
===== dmod.py =====
class DMod:
def __init__(self, system="", user1="", assistant="", prompt="", temperature=0.5, max_tokens=500, aimodel="gpt-3.5-turbo", pf=0.0, pp=0.0, top_p=1.0, stop=""):
self.api_openai_key = "***************************************"
self.aimodel = aimodel
self.system = system
self.user1 = user1
self.assistant = assistant
self.prompt = prompt
self.temperature = temperature
self.max_tokens = max_tokens
self.frequency_penalty = pf
self.presence_penalty = pp
self.top_p =top_p
self.stop = stop
def setDataModel(self, system="", user1="", assistant="", prompt="", temperature=0.5, max_tokens=500, aimodel="gpt-3.5-turbo", pf=0.0, pp=0.0, top_p=1.0, stop=""):
self.aimodel = aimodel
self.system = system
self.user1 = user1
self.assistant = assistant
self.prompt = prompt
self.temperature = temperature
self.max_tokens = max_tokens
self.frequency_penalty = pf
self.presence_penalty = pp
self.top_p =top_p
self.stop = stop
def to_ai_messages(self):
messages = []
if self.system != "":
messages.insert(0, {"role": "system", "content": self.system})
if self.user1 != "":
messages.append({"role": "user", "content": self.user1})
if self.assistant != "":
messages.append({"role": "assistant", "content": self.assistant})
if self.prompt != "":
messages.append({"role": "user", "content": self.prompt})
return messages
def getKey(self):
return self.api_key
----
===== Parameters =====
**Hier is wat meer informatie over de minder bekende parameters**:
**top_p**: Dit is een parameter die bekend staat als 'nucleus sampling'. Het is een alternatief voor de temperature parameter en biedt een andere manier om de willekeurigheid van de uitvoer van het model te regelen. Met top_p geeft je een kansverdeling op en het model zal alleen woorden kiezen uit de 'top p' van die verdeling. Bijvoorbeeld, als top_p=0.1, dan zal het model alleen de 10% meest waarschijnlijke volgende woorden overwegen bij het genereren van tekst.
**frequency_penalty**: Dit is een parameter die bepaalt hoe sterk het model wordt gestraft voor het kiezen van woorden die zeldzaam zijn in de trainingsdata. Een hogere waarde betekent een sterkere straf voor zeldzame woorden, waardoor ze minder waarschijnlijk worden gekozen.
**presence_penalty**: Dit is een parameter die bepaalt hoe sterk het model wordt gestraft voor het niet kiezen van woorden die al aanwezig zijn in de gegeven prompt. Een hogere waarde betekent een sterkere straf voor het negeren van bestaande woorden, waardoor ze waarschijnlijker worden gekozen.
**stop**: Dit is een lijst van tekenreeksen waarbij het model stopt met het genereren van verdere tokens. Dit is nuttig als je een specifieke einde-tekenreeks in gedachten hebt, zoals een specifieke interpunctie of een bepaald woord of zin. Het model zal stoppen met genereren zodra het een van de tekenreeksen in deze lijst tegenkomt.
//[[#gebruik|Deze parameters bieden verschillende manieren om de output van het model te beïnvloeden en te beheersen]].//
----
===== De flow =====
Hier een beschrijving van wat er op welk moment gebeurd bij het opstaren en gebruiken van de applicatie:\\
* Applicatie wordt gestart -> $ **python app.py** //gevolgd door enter//
* De **GUI** gebruikers interface //(vieuw.py)// wordt geladen en gemaakt //(sorry van de u)//
* De **controller** //(controler.py)// wordt geladen -> //Besturing//
* De **MyAPI** class //(api.py)// wordt geladen -> //communicatie met OpenAI API//
* de **DMod** class //(dmod.py)// wordt geladen -> //Het (soort van) data model//
* Als op de "**versturen**" knop wordt geklikt wordt in de controller de "**on_versturen_clicked**" methode aangeroepen\\
* In de functie wordt de gegevens van alle tekst velden en combiboxen opgeslagen in het "data model"\\
* Vervolgens wordt //(afhankelijk van de keuze in de "AI API" combi box wordt gemaakt)// de juiste methode in de MyAPI class aangeroepen om de data te versturen naar de OpenAI API\\
* In de **MyAPI class** wordt de data uit het data model gehaald die voor de gemaakte keuze nodig is
* De data wordt verstuurd naar de OpenAI API
* Het resultaat wordt via de "**api_callback**" methode van de controller naar het "**resultaat**" tekst veld gestuurd
----
===== Gebruik =====
:!: Op eigen risico LOL\\
-> Open een console in de map war het app.py bestand is opgeslagen en type:
python app.py
en klik op ENTER
----
==== AI API's combi box ====
De keuze in deze combi box bepaald welke "API" aangeroepen wordt. Iedere "API" vraagt om verschillende parameters. Hieronder een overzicht van welke parameters er met welke keuze in de combi box worden meegestuurd naar de diverse API's":
=== ChatCompletion ===
Dit is de standaard instelling en deze werkt met diverse "Model" keuzes in de "Models" combi box
-> **systeem** -> Instructies voor de AI\\
-> **user1** -> Een eerdere vraag van de gebruiker //(i.v.m. vervolg vraag)//\\
-> **assistant** -> Een eerder antwoord van de AI\\
-> **prompt** -> de gebruikers vraag / instructies\\
-> **temperature** -> tussen 1.0 en 0.0 -> lagere waarden geven striktere antwoorden\\
-> **max_tokens** -> het maximaal te gebruiken aantal tokens
----
=== Completion ===
Met "**Completion**" zijn alle voorbeelden op **[[https://platform.openai.com/examples|de voorbeeld pagina van OpenAI]]** uit te voeren\\
:!: Keus als "**text-davinci-003**" als Model\\
//[[#parameters|Lees hier meer over de minderbekende parameters die hier worden gebruikt]]//
-> **prompt** -> de gebruikers vraag / instructies\\
-> **temperature** -> tussen 1.0 en 0.0 -> lagere waarden geven striktere antwoorden\\
-> **max_tokens** -> het maximaal te gebruiken aantal tokens\\
-> **frequency_penalty**\\
-> **presence_penalty**\\
-> **top_p**\\
-> **stop** -> //als er iets is ingevuld anders niet//
----
=== Image ===
Genereer afbeeldingen d.m.v. een prompt.\\
Maakt gebruik van **[[https://openai.com/dall-e-2|DALL-E 2]]**
-> **prompt** -> Beschrijf de gewenste afbeelding -> //na uitvoeren verschijnt een link in het resultaat tekst veld die je kunt openen in de browser en waar je de afbeelding kunt bekijken en desgewenst kunt downloaden.//
-> De afbeelding wordt geopend in je browser als deze klaar is
----