| import os |
| import openai |
| import threading |
| import tkinter as tk |
| from tkinter import scrolledtext, messagebox |
|
|
| # Optionally, uncomment and hardcode for testing ONLY (never for shared code) |
| # os.environ["OPENAI_API_KEY"] = "sk-your-real-api-key" |
|
|
| openai.api_key = os.environ.get("OPENAI_API_KEY") |
|
|
| MODEL_NAME = "ft:gpt-4.1-2025-04-14:raiffs-bits:codette-final:BOc2GYND:ckpt-step-16" |
|
|
| def get_codette_response(user_query): |
| try: |
| response = openai.chat.completions.create( |
| model=MODEL_NAME, |
| messages=[ |
| {"role": "system", "content": "You are Codette, an advanced multi-agent AI assistant."}, |
| {"role": "user", "content": user_query} |
| ], |
| temperature=0.8, |
| max_tokens=512, |
| ) |
| return response.choices[0].message.content.strip() |
| except Exception as e: |
| return f"[Error: {str(e)}]" |
|
|
| class CodetteApp(tk.Tk): |
| def __init__(self): |
| super().__init__() |
| self.title("Codette Universal Reasoning Assistant") |
| self.geometry("650x480") |
| self.configure(bg="#eef6f9") |
| self.protocol("WM_DELETE_WINDOW", self.safe_exit) # For thread cleanup |
|
|
| title = tk.Label(self, text="Ask Codette", font=("Helvetica", 18, "bold"), bg="#eef6f9") |
| title.pack(pady=10) |
|
|
| self.input_field = tk.Entry(self, font=("Calibri", 14), width=60) |
| self.input_field.pack(pady=4) |
| self.input_field.focus() |
| self.input_field.bind("<Return>", lambda event: self.handle_ask()) |
|
|
| ask_btn = tk.Button(self, text="Ask", font=("Calibri", 12), command=self.handle_ask) |
| ask_btn.pack(pady=4) |
|
|
| output_label = tk.Label(self, text="Codette's Answer:", bg="#eef6f9") |
| output_label.pack() |
| self.output_box = scrolledtext.ScrolledText(self, font=("Consolas", 12), height=15, width=75, wrap=tk.WORD) |
| self.output_box.pack(pady=5) |
| self.output_box.configure(state='disabled') |
|
|
| clear_btn = tk.Button(self, text="Clear", command=self.clear_all) |
| clear_btn.pack(pady=3) |
|
|
| self.threads = [] |
|
|
| def handle_ask(self): |
| user_query = self.input_field.get().strip() |
| if not user_query: |
| messagebox.showwarning("Input Required", "Please enter your question.") |
| return |
|
|
| self.input_field.delete(0, tk.END) |
| self.append_output(f"User: {user_query}", prefix_newline=True) |
| self.append_output("Codette: ...thinking...") |
|
|
| def fetch_and_display(): |
| answer = get_codette_response(user_query) |
| self.append_output(f"Codette: {answer}", replace_last=True) |
| self.output_box.yview_moveto(1.0) |
|
|
| t = threading.Thread(target=fetch_and_display, daemon=True) |
| self.threads.append(t) |
| t.start() |
|
|
| def append_output(self, text, prefix_newline=False, replace_last=False): |
| self.output_box.configure(state='normal') |
| if replace_last: |
| output = self.output_box.get("1.0", tk.END).rstrip('\n').split('\n') |
| # Remove previous 'Codette: ...thinking...' |
| if output[-1].startswith("Codette: ...thinking..."): |
| output = output[:-1] |
| self.output_box.delete("1.0", tk.END) |
| self.output_box.insert(tk.END, '\n'.join(output) + "\n") |
| if prefix_newline and float(self.output_box.index(tk.END))-1 >= 1.0: |
| self.output_box.insert(tk.END, "\n") |
| self.output_box.insert(tk.END, text + "\n") |
| self.output_box.configure(state='disabled') |
|
|
| def clear_all(self): |
| self.output_box.configure(state='normal') |
| self.output_box.delete('1.0', tk.END) |
| self.output_box.configure(state='disabled') |
|
|
| def safe_exit(self): |
| # Wait for threads if needed before closing |
| self.destroy() |
|
|
| if __name__ == "__main__": |
| app = CodetteApp() |
| app.mainloop() |
|
|