Inhoud

AI Python project (1)

Terug naar Python start

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 )

A3DOpenAI project op GitHub

Doelen

  1. 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.
  2. Leren communiceren met de OpenAI API m.b.v. Python
  3. Een (simpele / basic) desktop applicatie bouwen met Python die kan communiceren met de OpenAI API
  4. Afbeeldingen genereren met DALL-E 2 Deze afbeelding opent in de browser als deze klaar is

Voorbereiding

Download en installeer 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.

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:


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 de voorbeeld pagina van OpenAI uit te voeren
:!: Keus als “text-davinci-003” als Model
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
stopals er iets is ingevuld anders niet


Image

Genereer afbeeldingen d.m.v. een prompt.
Maakt gebruik van 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