|
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() |
|
|