Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import tkinter as tk
- from tkinter import ttk, scrolledtext
- from tkinter import filedialog
- import threading
- import anthropic
- import json
- from datetime import datetime
- class ClaudeGUI:
- def __init__(self, root):
- self.root = root
- self.root.title("Claude Prompt Caching Interface")
- self.root.geometry("1000x800")
- # Available models configuration
- self.models = {
- "Claude 3.5 Sonnet": {
- "id": "claude-3-5-sonnet-20241022",
- "description": "Best balance of intelligence and speed",
- "max_tokens": 1024,
- "icon": "🚀" # Unicode icons for visual distinction
- }
- # Add more models here as needed, example:
- # "Claude 3 Opus": {
- # "id": "claude-3-opus-20240229",
- # "description": "Most capable model",
- # "max_tokens": 4096,
- # "icon": "⭐"
- # }
- }
- # Configure style
- style = ttk.Style()
- style.configure("Custom.TFrame", background="#f0f0f0")
- style.configure("Stats.TLabel", font=("Arial", 10))
- # Create main container
- main_container = ttk.Frame(root, style="Custom.TFrame", padding="10")
- main_container.pack(fill=tk.BOTH, expand=True)
- # Top Section: API Key and Model Selection
- top_frame = ttk.Frame(main_container)
- top_frame.pack(fill=tk.X, pady=(0, 10))
- # API Key
- api_frame = ttk.Frame(top_frame)
- api_frame.pack(fill=tk.X, pady=(0, 5))
- ttk.Label(api_frame, text="API Key:").pack(side=tk.LEFT)
- self.api_key_var = tk.StringVar()
- self.api_key_entry = ttk.Entry(api_frame, textvariable=self.api_key_var, show="*")
- self.api_key_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(5, 0))
- # History Control
- history_frame = ttk.Frame(top_frame)
- history_frame.pack(fill=tk.X, pady=(0, 5))
- ttk.Label(history_frame, text="Conversation Memory (turns):").pack(side=tk.LEFT)
- self.history_turns = tk.IntVar(value=10)
- self.history_spinbox = ttk.Spinbox(
- history_frame,
- from_=1,
- to=100,
- width=5,
- textvariable=self.history_turns
- )
- self.history_spinbox.pack(side=tk.LEFT, padx=(5, 0))
- # Model Selection
- model_frame = ttk.Frame(top_frame)
- model_frame.pack(fill=tk.X, pady=(0, 5))
- ttk.Label(model_frame, text="Model:").pack(side=tk.LEFT)
- # Create model selection dropdown
- self.selected_model = tk.StringVar()
- self.model_dropdown = ttk.Combobox(model_frame,
- textvariable=self.selected_model,
- values=[f"{k} {v['icon']}" for k, v in self.models.items()],
- state="readonly")
- self.model_dropdown.pack(side=tk.LEFT, padx=(5, 0))
- self.model_dropdown.set(f"{list(self.models.keys())[0]} {self.models[list(self.models.keys())[0]]['icon']}") # Set default
- # Model description label
- self.model_description = ttk.Label(model_frame, style="Stats.TLabel")
- self.model_description.pack(side=tk.LEFT, padx=(10, 0))
- self.update_model_description()
- # Bind model change event
- self.model_dropdown.bind('<<ComboboxSelected>>', self.update_model_description)
- # Cached Prompt Section
- ttk.Label(main_container, text="Cached Prompt (Optional):").pack(anchor=tk.W)
- self.cached_prompt = scrolledtext.ScrolledText(main_container, height=5)
- self.cached_prompt.pack(fill=tk.X, pady=(0, 10))
- # Add placeholder text
- placeholder = "Enter system prompt to cache here (optional)\nExample: You are an AI assistant trained to help with coding tasks..."
- self.cached_prompt.insert("1.0", placeholder)
- self.cached_prompt.bind("<FocusIn>", self.on_cached_prompt_focus_in)
- self.cached_prompt.bind("<FocusOut>", self.on_cached_prompt_focus_out)
- self.cached_prompt.config(fg='grey')
- # Stats Display
- self.stats_label = ttk.Label(main_container,
- text="Tokens - Input: 0 | Output: 0 | Cached: 0",
- style="Stats.TLabel")
- self.stats_label.pack(anchor=tk.W, pady=(0, 5))
- # Chat Display
- self.chat_display = scrolledtext.ScrolledText(main_container, height=20)
- self.chat_display.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
- self.chat_display.tag_configure("user", foreground="blue")
- self.chat_display.tag_configure("assistant", foreground="green")
- self.chat_display.tag_configure("system", foreground="red")
- # Progress Bar
- self.progress = ttk.Progressbar(main_container, mode='indeterminate')
- self.progress.pack(fill=tk.X, pady=(0, 10))
- # User Input
- self.user_input = scrolledtext.ScrolledText(main_container, height=4)
- self.user_input.pack(fill=tk.X, pady=(0, 10))
- self.user_input.bind("<Command-Return>", self.send_message) # Mac
- self.user_input.bind("<Control-Return>", self.send_message) # Windows/Linux
- # Buttons
- button_frame = ttk.Frame(main_container)
- button_frame.pack(fill=tk.X)
- ttk.Button(button_frame, text="Send", command=self.send_message).pack(side=tk.LEFT, padx=5)
- ttk.Button(button_frame, text="Clear Chat", command=self.clear_chat).pack(side=tk.LEFT, padx=5)
- ttk.Button(button_frame, text="Save Chat", command=self.save_chat).pack(side=tk.LEFT, padx=5)
- # Initialize variables
- self.total_tokens = {"input": 0, "output": 0, "cached": 0}
- self.client = None
- self.conversation_history = [] # Store conversation history
- self.api_key = "your api key" # Put your API Key here
- self.api_key_var.set(self.api_key) # Set the API key in the UI
- self.api_key_entry.config(state='disabled') # Disable the entry since key is hardcoded
- def update_model_description(self, event=None):
- selected = self.model_dropdown.get().rsplit(' ', 1)[0] # Remove icon
- description = self.models[selected]["description"]
- self.model_description.config(text=description)
- def get_selected_model_id(self):
- selected = self.model_dropdown.get().rsplit(' ', 1)[0] # Remove icon
- return self.models[selected]["id"]
- def append_message(self, sender, message):
- timestamp = datetime.now().strftime("%H:%M:%S")
- self.chat_display.insert(tk.END, f"[{timestamp}] {sender}: ", sender.lower())
- self.chat_display.insert(tk.END, f"{message}\n\n")
- self.chat_display.see(tk.END)
- def send_message(self, event=None):
- if not self.api_key_var.get():
- self.append_message("System", "Please enter your API key.")
- return
- message = self.user_input.get("1.0", tk.END).strip()
- if not message:
- return
- self.append_message("User", message)
- self.user_input.delete("1.0", tk.END)
- # Start progress bar
- self.progress.start()
- # Create thread for API call
- thread = threading.Thread(target=self.process_message, args=(message,))
- thread.daemon = True
- thread.start()
- def process_message(self, message):
- try:
- client = anthropic.Anthropic(api_key=self.api_key)
- # Get cached prompt if it exists
- cached_prompt = self.cached_prompt.get("1.0", tk.END).strip()
- # Prepare conversation history
- messages = []
- # Add past conversations (up to last 10 turns)
- messages.extend(self.conversation_history[-10:])
- # Add current message
- messages.append({
- "role": "user",
- "content": message
- })
- # Prepare API call parameters
- params = {
- "model": self.get_selected_model_id(),
- "max_tokens": self.models[self.model_dropdown.get().rsplit(' ', 1)[0]]["max_tokens"],
- "messages": messages,
- "extra_headers": {"anthropic-beta": "prompt-caching-2024-07-31"}
- }
- # Only add system message if cached prompt is not empty
- if cached_prompt and cached_prompt != "Enter system prompt to cache here (optional)\nExample: You are an AI assistant trained to help with coding tasks...":
- params["system"] = [
- {
- "type": "text",
- "text": cached_prompt,
- "cache_control": {"type": "ephemeral"}
- }
- ]
- response = client.messages.create(**params)
- # Add the response to conversation history
- self.conversation_history.append({
- "role": "user",
- "content": message
- })
- self.conversation_history.append({
- "role": "assistant",
- "content": response.content[0].text
- })
- # Update statistics
- self.total_tokens["input"] += response.usage.input_tokens
- self.total_tokens["output"] += response.usage.output_tokens
- cache_read = getattr(response.usage, 'cache_read_input_tokens', 0)
- self.total_tokens["cached"] += cache_read
- # Update UI in the main thread
- self.root.after(0, self.update_ui, response.content[0].text)
- except Exception as e:
- self.root.after(0, self.append_message, "System", f"Error: {str(e)}")
- finally:
- self.root.after(0, self.progress.stop)
- def update_ui(self, response_text):
- self.append_message("Assistant", response_text)
- self.stats_label.config(
- text=f"Tokens - Input: {self.total_tokens['input']} | "
- f"Output: {self.total_tokens['output']} | "
- f"Cached: {self.total_tokens['cached']}"
- )
- def clear_chat(self):
- self.chat_display.delete("1.0", tk.END)
- self.total_tokens = {"input": 0, "output": 0, "cached": 0}
- self.stats_label.config(text="Tokens - Input: 0 | Output: 0 | Cached: 0")
- self.conversation_history = [] # Clear conversation history
- self.append_message("System", "Chat cleared")
- def on_cached_prompt_focus_in(self, event):
- if self.cached_prompt.get("1.0", tk.END).strip() == "Enter system prompt to cache here (optional)\nExample: You are an AI assistant trained to help with coding tasks...":
- self.cached_prompt.delete("1.0", tk.END)
- self.cached_prompt.config(fg='black')
- def on_cached_prompt_focus_out(self, event):
- if not self.cached_prompt.get("1.0", tk.END).strip():
- self.cached_prompt.insert("1.0", "Enter system prompt to cache here (optional)\nExample: You are an AI assistant trained to help with coding tasks...")
- self.cached_prompt.config(fg='grey')
- def save_chat(self):
- file_path = filedialog.asksaveasfilename(
- defaultextension=".txt",
- filetypes=[("Text files", "*.txt"), ("All files", "*.*")]
- )
- if file_path:
- try:
- with open(file_path, 'w', encoding='utf-8') as file:
- file.write(self.chat_display.get("1.0", tk.END))
- self.append_message("System", f"Chat saved to {file_path}")
- except Exception as e:
- self.append_message("System", f"Error saving chat: {str(e)}")
- def main():
- root = tk.Tk()
- app = ClaudeGUI(root)
- root.mainloop()
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement