Inhoud
AI Python project (1)
β 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 )
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 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 de voorbeelden op de examples pagina van OpenAI uit kan voeren
- 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.
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
β 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
β stop β als 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