Advertisement
xosski

Lexi The Ai Companion

Jan 14th, 2025
8
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.29 KB | None | 0 0
  1. # First: All imports
  2. from tkinter import *
  3. from tkinter import ttk
  4. import tkinter.scrolledtext as scrolledtext
  5. import pygame
  6. import numpy as np
  7. from threading import Thread
  8. import logging
  9. import os
  10. import time
  11.  
  12. # Web and API
  13. from flask import Flask, request, jsonify, send_from_directory, render_template
  14. import requests
  15. import re
  16. # Data structures
  17. from dataclasses import dataclass
  18. from enum import Enum
  19. # Initialize Flask app
  20. app = Flask(__name__)
  21.  
  22. # Configure directories
  23. GENERATED_FILES_DIR = "generated_files"
  24. os.makedirs(GENERATED_FILES_DIR, exist_ok=True)
  25. # Constants at top of file
  26. MISTRAL_API_URL = "https://api.mistral.ai/v1/chat/completions"
  27. MISTRAL_API_KEY = "JCASwm1qYdbfSCd7ilpEgUU0oRv7LcbG" # Using the key from copilot.py
  28.  
  29. # Available models
  30. MISTRAL_MODELS = [
  31. "mistral-small",
  32. "mistral-medium",
  33. "mistral-large"
  34. ]
  35. OLLAMA_MODELS = []
  36.  
  37. # Conversation tracking
  38. conversation_history = []
  39. contextual_memory = []
  40.  
  41.  
  42. # Routes
  43. @app.route('/')
  44. def serve_index():
  45. return render_template("index.html")
  46.  
  47. @app.route('/ask', methods=['POST'])
  48. def ask_ai():
  49. user_message = request.json.get("message", "")
  50. selected_model = request.json.get("model", "mistral-small")
  51. response = ai_companion.process_user_input(user_message, selected_model)
  52. return jsonify({"response": response})
  53.  
  54. logging.basicConfig(level=logging.DEBUG)
  55.  
  56. def get_ai_response(self, message):
  57. headers = {
  58. "Authorization": f"Bearer {MISTRAL_API_KEY}",
  59. "Content-Type": "application/json"
  60. }
  61.  
  62. payload = {
  63. "model": "mistral-small", # Using the correct model name
  64. "messages": [{
  65. "role": "user",
  66. "content": message
  67. }]
  68. }
  69. # Third: Define the CombinedInterface class
  70. class CombinedInterface:
  71. def __init__(self, root):
  72. self.root = root
  73. self.root.title("✨ Lexi - Magical AI Companion ✨")
  74. self.root.geometry("1200x800")
  75.  
  76. # Initialize core components
  77. self.running = True
  78. self.current_animation = "idle"
  79. self.animation_frame = 0
  80. self.sprite_size = (64, 64)
  81.  
  82. # Create main container
  83. self.main_container = ttk.Frame(root)
  84. self.main_container.pack(fill=BOTH, expand=True)
  85.  
  86. # Create sprite frame
  87. self.sprite_frame = Frame(self.main_container, width=400, height=600, bg='black')
  88. self.sprite_frame.pack(side=LEFT, fill=BOTH, padx=5, pady=5)
  89. self.sprite_frame.pack_propagate(False)
  90.  
  91. # Create chat frame
  92. self.setup_chat_interface()
  93.  
  94. # Initialize pygame
  95. self.root.update()
  96. os.environ['SDL_WINDOWID'] = str(self.sprite_frame.winfo_id())
  97. pygame.init()
  98. self.screen = pygame.display.set_mode((400, 600))
  99. self.clock = pygame.time.Clock()
  100.  
  101. # Generate sprites
  102. self.sprites = self.generate_sprites()
  103.  
  104. # Start animation thread
  105. self.animation_thread = Thread(target=self.run_animation, daemon=True)
  106. self.animation_thread.start()
  107.  
  108. def setup_chat_interface(self):
  109. # Chat interface setup
  110. self.chat_frame = ttk.Frame(self.main_container)
  111. self.chat_frame.pack(side=RIGHT, fill=BOTH, expand=True, padx=5, pady=5)
  112.  
  113. # Model selection
  114. self.model_var = StringVar(value="mistral-small-latest")
  115. model_frame = ttk.Frame(self.chat_frame)
  116. model_frame.pack(fill=X, pady=(0, 10))
  117.  
  118. ttk.Label(model_frame, text="Select AI Model:").pack(side=LEFT)
  119. model_menu = ttk.Combobox(model_frame, textvariable=self.model_var)
  120. model_menu['values'] = MISTRAL_MODELS + OLLAMA_MODELS
  121. model_menu.pack(side=LEFT, padx=5)
  122.  
  123. # Chat display
  124. self.chat_display = scrolledtext.ScrolledText(
  125. self.chat_frame,
  126. wrap=WORD,
  127. height=25,
  128. font=('Helvetica', 11),
  129. bg='#f5f5f5'
  130. )
  131. self.chat_display.pack(fill=BOTH, expand=True, pady=(0, 10))
  132.  
  133. # Input area
  134. input_frame = ttk.Frame(self.chat_frame)
  135. input_frame.pack(fill=X)
  136.  
  137. self.message_input = ttk.Entry(input_frame, font=('Helvetica', 11))
  138. self.message_input.pack(side=LEFT, fill=X, expand=True)
  139.  
  140. send_button = ttk.Button(input_frame, text="Send", command=self.send_message)
  141. send_button.pack(side=LEFT, padx=(5, 0))
  142.  
  143. # Bind Enter key
  144. self.message_input.bind("<Return>", lambda e: self.send_message())
  145.  
  146. def generate_sprites(self):
  147. # Initialize sprite dictionary
  148. sprites = {
  149. "idle": [],
  150. "talking": [],
  151. "thinking": []
  152. }
  153.  
  154. # Generate frames for each animation state
  155. for i in range(4):
  156. # Create idle animation frames
  157. sprite = np.zeros((self.sprite_size[1], self.sprite_size[0], 4), dtype=np.uint8)
  158. self.draw_character(sprite, animation_step=int(np.sin(i * np.pi/2) * 2))
  159. sprites["idle"].append(sprite.copy())
  160.  
  161. # Create talking animation frames
  162. sprite_talk = np.zeros((self.sprite_size[1], self.sprite_size[0], 4), dtype=np.uint8)
  163. self.draw_character(sprite_talk, animation_step=i, talking=True)
  164. sprites["talking"].append(sprite_talk.copy())
  165.  
  166. # Create thinking animation frames
  167. sprite_think = np.zeros((self.sprite_size[1], self.sprite_size[0], 4), dtype=np.uint8)
  168. self.draw_character(sprite_think, animation_step=i, thinking=True)
  169. sprites["thinking"].append(sprite_think.copy())
  170.  
  171. return sprites
  172.  
  173. def draw_character(self, sprite, animation_step=0, talking=False, thinking=False):
  174. # Draw with magical colors
  175. ROBE_COLOR = (75, 0, 130, 255) # Royal purple
  176. SKIN_COLOR = (255, 223, 196, 255) # Warm tone
  177. HAT_COLOR = (45, 0, 90, 255) # Deep purple
  178. STAR_COLOR = (255, 215, 0, 255) # Bright gold
  179. # Magical color palette
  180. HAIR_COLOR = (200, 60, 20, 255) # Vibrant auburn red
  181. HAIR_HIGHLIGHT = (240, 80, 35, 255) # Lighter red highlights
  182. ROBE_COLOR = (75, 0, 130, 255) # Royal purple
  183. ROBE_ACCENT = (147, 112, 219, 255) # Lighter purple for details
  184. SKIN_COLOR = (255, 223, 196, 255) # Warm peachy tone
  185. HAT_COLOR = (45, 0, 90, 255) # Deep purple
  186. STAR_COLOR = (255, 215, 0, 255) # Bright gold
  187. EYE_COLOR = (30, 144, 255, 255) # Bright blue eyes
  188. EYE_HIGHLIGHT = (135, 206, 250, 255) # Light blue sparkle
  189. EYE_SHADOW = (25, 25, 112, 255) # Dark blue depth
  190. STAFF_WOOD = (139, 69, 19, 255) # Rich wooden staff
  191. STAFF_GOLD = (218, 165, 32, 255) # Gold accents
  192. GEM_COLOR = (0, 191, 255, 255) # Magical blue gems
  193. LIP_COLOR = (220, 20, 60, 255) # Crimson red lips
  194. LIP_HIGHLIGHT = (255, 69, 0, 255) # Coral highlight
  195. # Initialize position variables
  196. hat_height = 15
  197. for y in range(hat_height):
  198. width = max(4, int(12 - y * 0.8)) # Hat narrows toward top
  199. for x in range(32-width, 32+width):
  200. if 0 <= y < 64 and 0 <= x < 64:
  201. sprite[y, x] = HAT_COLOR
  202.  
  203. # Face and neck area - moved up
  204. face_start = hat_height
  205. face_end = face_start + 10
  206. for y in range(face_start, face_end):
  207. for x in range(24, 40):
  208. if (x-32)**2 + (y-face_start-5)**2 < 64:
  209. sprite[y, x] = SKIN_COLOR
  210. # Draw elegant flowing hair with proper layering
  211. for y in range(5, face_end + 15): # Hair ends at upper robe area
  212. # Create gentle waves with smaller amplitude
  213. width = int(12 + np.sin(y * 0.2 + animation_step * 0.1) * 2)
  214.  
  215. # Add subtle tapering effect for natural flow
  216. taper = max(0, (y - 15) * 0.2) # Start tapering earlier
  217. adjusted_width = max(4, width - int(taper))
  218.  
  219. for x in range(32-adjusted_width, 32+adjusted_width):
  220. if 0 <= y < 64 and 0 <= x < 64:
  221. # Create natural highlight pattern
  222. if (x + y) % 5 == 0 and abs(x-32) > adjusted_width/2:
  223. sprite[y, x] = HAIR_HIGHLIGHT
  224. else:
  225. sprite[y, x] = HAIR_COLOR
  226. # Robe (flowing downward with elegant slim fit)
  227. robe_start = face_end
  228. for y in range(robe_start, 60):
  229. # Create ultra-slim silhouette
  230. width = int(6 + (y - robe_start) * 0.2) # Reduced from 8 to 6, and 0.3 to 0.2
  231.  
  232. # Add subtle curves for feminine shape
  233. curve_adjust = int(np.sin((y - robe_start) * 0.2) * 2)
  234. adjusted_width = width + curve_adjust
  235.  
  236. for x in range(32-adjusted_width, 32+adjusted_width):
  237. if 0 <= x < 64:
  238. if (x + y) % 4 == 0:
  239. sprite[y, x] = ROBE_ACCENT
  240. else:
  241. sprite[y, x] = ROBE_COLOR
  242. # Add magical sparkles more sparsely
  243. if (x + y) % 9 == 0: # Changed from 7 to 9 for more delicate effect
  244. sprite[y, x] = STAR_COLOR
  245. # Draw ornate wizard hat with gems
  246. for y in range(hat_height):
  247. width = max(4, int(10 - y * 0.8))
  248. for x in range(32-width, 32+width):
  249. if 0 <= y < 64 and 0 <= x < 64:
  250. sprite[y, x] = HAT_COLOR
  251. if y % 3 == 0 and abs(x-32) == width-2:
  252. sprite[y, x] = GEM_COLOR
  253.  
  254. # Draw detailed face
  255. for y in range(face_start, face_end):
  256. for x in range(24, 40):
  257. if (x-32)**2 + (y-face_start-5)**2 < 64:
  258. sprite[y, x] = SKIN_COLOR
  259. if (x-32)**2 + (y-face_start-5)**2 > 58:
  260. sprite[y, x] = (255, 200, 180, 255)
  261.  
  262. # Draw eyes
  263. eye_y = face_start + 5
  264. # Left eye
  265. for x in range(27, 30):
  266. for y in range(eye_y-1, eye_y+2):
  267. sprite[y, x] = EYE_COLOR
  268. if x == 28 and y == eye_y-1:
  269. sprite[y, x] = EYE_HIGHLIGHT
  270. if y == eye_y+1:
  271. sprite[y, x] = EYE_SHADOW
  272.  
  273. # Right eye
  274. for x in range(34, 37):
  275. for y in range(eye_y-1, eye_y+2):
  276. sprite[y, x] = EYE_COLOR
  277. if x == 35 and y == eye_y-1:
  278. sprite[y, x] = EYE_HIGHLIGHT
  279. if y == eye_y+1:
  280. sprite[y, x] = EYE_SHADOW
  281. # Draw magical staff and robed arms
  282. staff_x = 40 # Moved staff closer to body center (32)
  283.  
  284. # Draw left arm holding staff
  285. for y in range(25, 40):
  286. # Create sleeve that extends from robe to staff
  287. for x in range(35, staff_x):
  288. if (x-32)**2 + (y-30)**2 < 64: # Curved sleeve shape
  289. sprite[y, x] = ROBE_COLOR
  290. if (x + y) % 4 == 0:
  291. sprite[y, x] = ROBE_ACCENT
  292.  
  293. # Draw staff with hands
  294. for y in range(20, 55):
  295. # Draw the wooden staff
  296. sprite[y, staff_x] = STAFF_WOOD
  297. sprite[y, staff_x+1] = STAFF_WOOD
  298.  
  299. # Add gold bands
  300. if y % 8 == 0:
  301. sprite[y, staff_x-1:staff_x+3] = STAFF_GOLD
  302.  
  303. # Add hands at grip points
  304. if 30 <= y <= 35:
  305. for x in range(staff_x-2, staff_x+3):
  306. sprite[y, x] = SKIN_COLOR
  307. # Draw ornate staff top
  308. staff_top_y = 15
  309. orb_radius = 4
  310.  
  311. # Create glowing orb
  312. for y in range(staff_top_y - orb_radius, staff_top_y + orb_radius):
  313. for x in range(staff_x - orb_radius, staff_x + orb_radius + 2):
  314. if (x-staff_x)**2 + (y-staff_top_y)**2 < orb_radius**2:
  315. # Create glowing effect with color gradients
  316. distance = ((x-staff_x)**2 + (y-staff_top_y)**2) ** 0.5
  317. glow_intensity = 1 - (distance / orb_radius)
  318. sprite[y, x] = (
  319. int(GEM_COLOR[0] * glow_intensity),
  320. int(GEM_COLOR[1] * glow_intensity),
  321. int(GEM_COLOR[2] * glow_intensity),
  322. 255
  323. )
  324.  
  325. # Add golden filigree around orb
  326. for angle in range(0, 360, 45):
  327. rad_angle = np.radians(angle)
  328. x = int(staff_x + (orb_radius + 1) * np.cos(rad_angle))
  329. y = int(staff_top_y + (orb_radius + 1) * np.sin(rad_angle))
  330. if 0 <= x < 64 and 0 <= y < 64:
  331. sprite[y, x] = STAFF_GOLD
  332.  
  333. # Draw the wooden staff
  334. for y in range(staff_top_y + orb_radius, 55):
  335. sprite[y, staff_x] = STAFF_WOOD
  336. sprite[y, staff_x+1] = STAFF_WOOD
  337. if y % 8 == 0:
  338. sprite[y, staff_x-1:staff_x+3] = STAFF_GOLD
  339. # Add gold bands
  340. if y % 8 == 0:
  341. sprite[y, staff_x-1:staff_x+3] = STAFF_GOLD
  342.  
  343. # Add hands at grip points
  344. if 30 <= y <= 35:
  345. for x in range(staff_x-2, staff_x+3):
  346. sprite[y, x] = SKIN_COLOR
  347. # Draw lips
  348. if talking:
  349. # Animated talking lips
  350. mouth_y = face_start + 7 + (animation_step % 2)
  351. for x in range(30, 34):
  352. sprite[mouth_y, x] = LIP_COLOR
  353. sprite[mouth_y-1, x] = LIP_HIGHLIGHT
  354. else:
  355. # Gentle smile
  356. mouth_y = face_start + 7
  357. for x in range(30, 34):
  358. sprite[mouth_y, x] = LIP_COLOR
  359. sprite[mouth_y-1, x] = LIP_HIGHLIGHT
  360. # Add magical effects when thinking
  361. if thinking:
  362. for i in range(4):
  363. angle = animation_step * 0.2 + i * np.pi/2
  364. radius = 8 + np.sin(animation_step * 0.1) * 3
  365. spell_x = int(staff_x + np.cos(angle) * radius)
  366. spell_y = int(17 + np.sin(angle) * radius)
  367. if 0 <= spell_x < 64 and 0 <= spell_y < 64:
  368. sprite[spell_y, spell_x] = STAR_COLOR
  369. def run_animation(self):
  370. logging.debug("Animation loop starting...")
  371. while self.running:
  372. try:
  373. # Clear screen
  374. self.screen.fill((30, 30, 60))
  375.  
  376. # Get current frame
  377. current_frame = self.animation_frame % len(self.sprites[self.current_animation])
  378. sprite_array = self.sprites[self.current_animation][current_frame]
  379.  
  380. # Create surface
  381. sprite_surface = pygame.Surface(self.sprite_size, pygame.SRCALPHA)
  382. pygame.surfarray.pixels3d(sprite_surface)[:] = sprite_array[:, :, :3]
  383. pygame.surfarray.pixels_alpha(sprite_surface)[:] = sprite_array[:, :, 3]
  384.  
  385. # Scale sprite
  386. scaled_sprite = pygame.transform.scale(sprite_surface, (300, 300))
  387.  
  388. # Rotate sprite 90 degrees clockwise
  389. rotated_sprite = pygame.transform.rotate(scaled_sprite, -90)
  390.  
  391. # Center rotated sprite
  392. sprite_rect = rotated_sprite.get_rect(center=(200, 300))
  393.  
  394. # Draw rotated sprite
  395. self.screen.blit(rotated_sprite, sprite_rect)
  396.  
  397. # Update display
  398. pygame.display.flip()
  399.  
  400. # Increment frame
  401. self.animation_frame += 1
  402.  
  403. # Control frame rate
  404. self.clock.tick(30)
  405.  
  406. except Exception as e:
  407. logging.error(f"Animation error: {e}")
  408. def send_message(self):
  409. message = self.message_input.get()
  410. if message:
  411. # Display user message
  412. self.chat_display.insert(END, f"\n😊 You: {message}\n", 'user')
  413. self.chat_display.tag_configure('user', foreground='#2196F3')
  414.  
  415. # Clear input field
  416. self.message_input.delete(0, END)
  417.  
  418. # Set thinking animation
  419. self.current_animation = "thinking"
  420.  
  421. # Get and display AI response with female wizard emoji
  422. response = self.get_ai_response(message)
  423. self.chat_display.insert(END, f"\n🧙‍♀️ Lexi: {response}\n", 'ai')
  424. self.chat_display.tag_configure('ai', foreground='#9C27B0')
  425. # Return to idle animation
  426. self.current_animation = "idle"
  427. # Ensure latest messages are visible
  428. self.chat_display.see(END)
  429. def get_ai_response(self, message):
  430. selected_model = self.model_var.get()
  431. try:
  432. # Get response from API
  433. response, _ = self.query_mistral(selected_model, message)
  434.  
  435. # Process response for code blocks
  436. code_blocks = re.findall(r"(\w+)?\n(.*?)", response, re.DOTALL)
  437.  
  438. # Create files if code blocks exist
  439. if code_blocks:
  440. for language, code in code_blocks:
  441. filename = f"magical_code_{time.strftime('%Y%m%d_%H%M%S')}.{language or 'txt'}"
  442. with open(filename, 'w') as f:
  443. f.write(code.strip())
  444.  
  445. return response
  446. except Exception as e:
  447. return f"✨ The magical realms whisper: {str(e)}"
  448. def query_mistral(self, model, message):
  449. headers = {
  450. "Authorization": f"Bearer {MISTRAL_API_KEY}",
  451. "Content-Type": "application/json"
  452. }
  453.  
  454. payload = {
  455. "model": model,
  456. "messages": [{
  457. "role": "user",
  458. "content": message
  459. }],
  460. "temperature": 0.7,
  461. "max_tokens": 2000
  462. }
  463.  
  464. logging.debug(f"Sending request to Mistral API with model: {model}")
  465. response = requests.post(MISTRAL_API_URL, json=payload, headers=headers)
  466.  
  467. if response.status_code == 200:
  468. json_response = response.json()
  469. ai_response = json_response.get("choices", [{}])[0].get("message", {}).get("content", "")
  470. logging.debug("Successfully received response from Mistral API")
  471. return ai_response, None
  472.  
  473. logging.error(f"Mistral API returned status code: {response.status_code}")
  474. return f"✨ The magical connection requires attention (Status: {response.status_code})", None
  475.  
  476. def query_ollama(self, model, message):
  477. full_context = self.contextual_memory + self.conversation_history
  478. payload = {
  479. "model": model,
  480. "messages": full_context + [{"role": "user", "content": message}],
  481. "system_prompt": "You are Lexi, a magical AI companion specialized in programming."
  482. }
  483.  
  484. response = requests.post(self.OLLAMA_API_URL, json=payload, stream=True)
  485. if response.status_code == 200:
  486. full_response = ""
  487. memory_update = None
  488.  
  489. for line in response.iter_lines():
  490. if line:
  491. json_part = json.loads(line.decode('utf-8'))
  492. if "memory_update" in json_part:
  493. memory_update = json_part["memory_update"]
  494. full_response += json_part.get("message", {}).get("content", "")
  495. return full_response, memory_update
  496. return f"✨ Magical connection needs attention: {response.status_code}", None
  497. # Fourth: Define main function
  498. def main():
  499. root = Tk()
  500. app = CombinedInterface(root)
  501. root.mainloop()
  502.  
  503. # Fifth: Run the program
  504. if __name__ == "__main__":
  505. main()
  506.  
Tags: ai
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement