Spaces:
Runtime error
Runtime error
import copy | |
import difflib | |
import hashlib | |
import pickle | |
import random | |
import json | |
from datetime import datetime | |
from typing import Dict, Any, List, Callable, Optional | |
from marshmallow import Schema, fields, ValidationError, EXCLUDE | |
from semantic_version import Version | |
import gradio as gr | |
# ---------- Constants & Helpers ---------- | |
from examples import EXAMPLES | |
COLOR_SCHEMES = [ | |
["#FF6B6B", "#4ECDC4", "#45B7D1"], # Ocean Breeze | |
["#2A9D8F", "#E9C46A", "#F4A261"], # Desert Sunset | |
["#264653", "#2A9D8F", "#E9C46A"], # Forest Dawn | |
["#F4A261", "#E76F51", "#2A9D8F"], # Coral Reef | |
["#8338EC", "#3A86FF", "#FF006E"], # Neon Nights | |
["#06D6A0", "#118AB2", "#073B4C"], # Deep Ocean | |
["#FFB4A2", "#E5989B", "#B5838D"], # Rose Garden | |
["#22223B", "#4A4E69", "#9A8C98"] # Midnight Purple | |
] | |
def generate_gradient(colors: List[str]) -> str: | |
"""Generate modern gradient styling with enhanced visual effects""" | |
return f""" | |
/* Modern gradient background with enhanced visual effects */ | |
.gradio-container {{ | |
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; | |
}} | |
.container {{ | |
background: linear-gradient(135deg, {colors[0]}, {colors[1]}, {colors[2]}); | |
background-size: 300% 300%; | |
animation: gradient-shift 15s ease infinite; | |
border-radius: 12px; | |
padding: 24px; | |
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); | |
transition: all 0.3s ease; | |
margin-bottom: 1rem; | |
}} | |
.chat-message {{ | |
padding: 12px 16px; | |
border-radius: 8px; | |
margin: 8px 0; | |
max-width: 85%; | |
transition: transform 0.2s ease; | |
}} | |
.user-message {{ | |
background: rgba(255, 255, 255, 0.95); | |
color: #333; | |
margin-left: auto; | |
border-top-right-radius: 2px; | |
}} | |
.assistant-message {{ | |
background: rgba(0, 0, 0, 0.05); | |
color: #fff; | |
margin-right: auto; | |
border-top-left-radius: 2px; | |
}} | |
.system-message {{ | |
background: rgba(0, 0, 0, 0.2); | |
color: #fff; | |
margin: 8px auto; | |
font-style: italic; | |
text-align: center; | |
}} | |
.notification {{ | |
position: fixed; | |
top: 20px; | |
right: 20px; | |
padding: 12px 24px; | |
border-radius: 8px; | |
background: rgba(0, 0, 0, 0.8); | |
color: white; | |
z-index: 1000; | |
animation: slide-in 0.3s ease; | |
}} | |
.typing-indicator {{ | |
display: inline-block; | |
padding: 8px 16px; | |
background: rgba(0, 0, 0, 0.1); | |
border-radius: 16px; | |
color: rgba(255, 255, 255, 0.8); | |
font-style: italic; | |
margin: 8px 0; | |
}} | |
.control-panel {{ | |
background: rgba(255, 255, 255, 0.2); | |
border-radius: 12px; | |
padding: 20px; | |
position: fixed; | |
right: -250px; | |
top: 50%; | |
transform: translateY(-50%); | |
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
z-index: 1000; | |
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2); | |
width: 220px; | |
backdrop-filter: blur(10px); | |
border: 1px solid rgba(255, 255, 255, 0.1); | |
pointer-events: auto; | |
}} | |
/* Make the panel accessible via keyboard focus */ | |
.control-panel:focus-within, | |
.control-panel:hover {{ | |
right: 20px; | |
outline: none; | |
}} | |
/* Ensure the panel is keyboard navigable */ | |
.control-panel button:focus {{ | |
outline: 2px solid rgba(255, 255, 255, 0.5); | |
outline-offset: 2px; | |
}} | |
/* Improve button hover states */ | |
.control-panel button:hover {{ | |
background: rgba(255, 255, 255, 0.25); | |
transform: translateX(5px); | |
}} | |
/* Make the panel accessible via keyboard focus */ | |
.control-panel:hover, | |
.control-panel:focus-within {{ | |
right: 20px; | |
outline: none; | |
background: rgba(255, 255, 255, 0.3); | |
box-shadow: 0 6px 25px rgba(0, 0, 0, 0.3); | |
}} | |
.control-panel:hover ~ .chat-window {{ | |
transform: translateX(-110px); | |
}} | |
.control-panel::before {{ | |
content: "☰ Settings"; | |
position: fixed; | |
right: 0; | |
top: 50%; | |
transform: translateY(-50%); | |
background: rgba(255, 255, 255, 0.5); | |
padding: 15px 35px 15px 25px; | |
border-radius: 12px 0 0 12px; | |
font-size: 16px; | |
font-weight: bold; | |
color: white; | |
cursor: pointer; | |
transition: all 0.3s ease; | |
box-shadow: -2px 0 15px rgba(0, 0, 0, 0.2); | |
z-index: 999; | |
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); | |
white-space: nowrap; | |
border: 1px solid rgba(255, 255, 255, 0.3); | |
border-right: none; | |
animation: pulse 2s infinite; | |
}} | |
.control-panel:hover::before {{ | |
opacity: 0; | |
transform: translateY(-50%) translateX(-20px); | |
}} | |
.control-panel:hover ~ .chat-window {{ | |
transform: translateX(-110px); | |
transition: transform 0.3s ease; | |
}} | |
.control-panel:hover::before {{ | |
opacity: 0; | |
transform: translateY(-50%) translateX(-20px); | |
}} | |
/* Menu trigger tab with pulsing effect */ | |
.control-panel::before {{ | |
content: "☰ Settings"; | |
position: fixed; | |
right: 0; | |
top: 50%; | |
transform: translateY(-50%); | |
background: rgba(255, 255, 255, 0.5); | |
padding: 15px 35px 15px 25px; | |
border-radius: 12px 0 0 12px; | |
font-size: 16px; | |
font-weight: bold; | |
color: white; | |
cursor: pointer; | |
transition: all 0.3s ease; | |
box-shadow: -2px 0 15px rgba(0, 0, 0, 0.2); | |
z-index: 999; | |
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); | |
white-space: nowrap; | |
border: 1px solid rgba(255, 255, 255, 0.3); | |
border-right: none; | |
animation: pulse 2s infinite; | |
}} | |
.control-panel:hover::before {{ | |
background: rgba(255, 255, 255, 0.6); | |
padding-right: 45px; | |
transform: translateY(-50%) translateX(-10px); | |
}} | |
/* Add hover trigger area */ | |
.control-panel::after {{ | |
content: ""; | |
position: fixed; | |
right: 0; | |
top: 0; | |
width: 100px; /* Even wider hover area */ | |
height: 100%; | |
z-index: 998; | |
background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.05)); | |
pointer-events: none; /* Allow clicks to pass through */ | |
}} | |
/* Ensure the menu is interactive */ | |
.control-panel:hover {{ | |
pointer-events: auto; | |
}} | |
/* Hide trigger area when menu is open */ | |
.control-panel:hover::after {{ | |
opacity: 0; | |
width: 0; | |
}} | |
@keyframes pulse {{ | |
0% {{ box-shadow: -2px 0 15px rgba(0, 0, 0, 0.2); }} | |
50% {{ box-shadow: -2px 0 20px rgba(255, 255, 255, 0.3); }} | |
100% {{ box-shadow: -2px 0 15px rgba(0, 0, 0, 0.2); }} | |
}} | |
.control-panel:hover::before {{ | |
opacity: 0; | |
transform: translateY(-50%) translateX(-10px); | |
pointer-events: none; | |
background: rgba(255, 255, 255, 0.5); | |
padding-right: 35px; | |
}} | |
.control-panel:not(:hover)::before {{ | |
opacity: 1; | |
pointer-events: auto; | |
}} | |
/* Menu trigger tab */ | |
.control-panel::before {{ | |
content: "☰ Settings →"; | |
position: fixed; | |
right: 0; | |
top: 50%; | |
transform: translateY(-50%); | |
background: rgba(255, 255, 255, 0.4); | |
padding: 15px 25px; | |
border-radius: 12px 0 0 12px; | |
font-size: 16px; | |
font-weight: bold; | |
color: white; | |
cursor: pointer; | |
transition: all 0.3s ease; | |
box-shadow: -2px 0 15px rgba(0, 0, 0, 0.2); | |
z-index: 999; | |
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2); | |
white-space: nowrap; | |
border: 1px solid rgba(255, 255, 255, 0.2); | |
border-right: none; | |
}} | |
.control-panel:hover::before {{ | |
background: rgba(255, 255, 255, 0.5); | |
padding-right: 35px; | |
opacity: 0; | |
transform: translateY(-50%) translateX(-10px); | |
}} | |
.control-panel button {{ | |
width: 100%; | |
margin: 8px 0; | |
transition: all 0.2s ease; | |
}} | |
.control-panel button:hover {{ | |
transform: translateX(5px); | |
background: rgba(255, 255, 255, 0.1); | |
}} | |
button {{ | |
transition: all 0.2s ease; | |
padding: 12px 20px; | |
background: rgba(255, 255, 255, 0.2); | |
border: none; | |
border-radius: 8px; | |
color: white; | |
font-size: 14px; | |
font-weight: 500; | |
cursor: pointer; | |
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); | |
margin: 5px 0; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
width: 100%; | |
}} | |
button[aria-label="Show Examples"] {{ | |
background: rgba(255, 255, 255, 0.3); | |
font-weight: 600; | |
border: 1px solid rgba(255, 255, 255, 0.3); | |
}} | |
button[aria-label="Show Examples"]:hover {{ | |
background: rgba(255, 255, 255, 0.4); | |
transform: translateY(-2px); | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); | |
}} | |
button:hover {{ | |
transform: translateX(5px); | |
background: rgba(255, 255, 255, 0.3); | |
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); | |
}} | |
button:active {{ | |
transform: translateX(2px); | |
background: rgba(255, 255, 255, 0.25); | |
}} | |
@keyframes gradient-shift {{ | |
0% {{ background-position: 0% 50%; }} | |
50% {{ background-position: 100% 50%; }} | |
100% {{ background-position: 0% 50%; }} | |
}} | |
@keyframes slide-in {{ | |
from {{ transform: translateX(100%); opacity: 0; }} | |
to {{ transform: translateX(0); opacity: 1; }} | |
}} | |
/* Responsive adjustments */ | |
@media (max-width: 768px) {{ | |
.container {{ padding: 16px; }} | |
.chat-message {{ max-width: 95%; }} | |
}} | |
""" | |
# ---------- Core System ---------- | |
class AppState: | |
def __init__(self): | |
self.chat_history = [] | |
self.color_scheme = random.choice(COLOR_SCHEMES) | |
self.ui_elements = [] | |
self.version = "1.0.0" | |
self.last_modified = datetime.now() | |
self.error_log = [] | |
self.notifications = [] | |
self.settings = { | |
"show_timestamps": True, | |
"show_version_info": True, | |
"enable_animations": True, | |
"theme_name": "Default", | |
"search_filter": "" | |
} | |
def log_error(self, error_message: str, error_type: str = "general"): | |
"""Log an error with timestamp and type""" | |
self.error_log.append({ | |
"timestamp": datetime.now(), | |
"type": error_type, | |
"message": error_message | |
}) | |
self.add_notification(f"Error: {error_message}", "error") | |
def add_notification(self, message: str, level: str = "info"): | |
"""Add a notification with level (info, warning, error)""" | |
self.notifications.append({ | |
"timestamp": datetime.now(), | |
"level": level, | |
"message": message, | |
"id": hashlib.md5(f"{message}{datetime.now()}".encode()).hexdigest()[:8] | |
}) | |
class StateVersionManager: | |
def __init__(self): | |
self.versions: Dict[str, Dict] = {} | |
self.current_state = AppState() | |
self.history = [] | |
self.max_versions = 50 | |
def create_version(self, description: str = "") -> Optional[Dict]: | |
try: | |
state_hash = hashlib.sha256(pickle.dumps(self.current_state)).hexdigest()[:8] | |
version_data = { | |
"state": copy.deepcopy(self.current_state), | |
"timestamp": datetime.now(), | |
"description": description, | |
"hash": state_hash | |
} | |
if len(self.history) >= self.max_versions: | |
oldest_version = self.history.pop(0) | |
self.versions.pop(oldest_version["hash"], None) | |
self.versions[version_data["hash"]] = version_data | |
self.history.append(version_data) | |
return version_data | |
except Exception as e: | |
self.current_state.log_error(f"Failed to create version: {str(e)}", "version_creation") | |
return None | |
def restore_version(self, version_hash: str) -> bool: | |
try: | |
if version_hash in self.versions: | |
self.current_state = copy.deepcopy(self.versions[version_hash]["state"]) | |
self.current_state.add_notification( | |
f"Successfully restored to version {version_hash[:6]}", | |
"success" | |
) | |
return True | |
self.current_state.add_notification( | |
f"Version {version_hash[:6]} not found", | |
"warning" | |
) | |
return False | |
except Exception as e: | |
self.current_state.log_error(f"Failed to restore version: {str(e)}", "version_restoration") | |
return False | |
def get_version_list(self) -> List[Dict]: | |
return [{ | |
"hash": v["hash"], | |
"label": f"{v['description']} ({v['timestamp'].strftime('%Y-%m-%d %H:%M')})", | |
"timestamp": v["timestamp"].strftime("%Y-%m-%d %H:%M:%S"), | |
"description": v["description"] | |
} for v in self.history] | |
# ---------- Chat Application ---------- | |
class EvolvableChatApp: | |
def __init__(self): | |
self.state_manager = StateVersionManager() | |
self.current_gradient = generate_gradient(self.state_manager.current_state.color_scheme) | |
self.setup_initial_state() | |
self.typing_indicator_visible = False | |
def setup_initial_state(self): | |
try: | |
initial_state = self.state_manager.current_state | |
initial_state.ui_elements = [ | |
{"type": "button", "label": "🎨 Change Theme", "action": self.change_theme}, | |
{"type": "button", "label": "🗑️ Clear Chat", "action": self.clear_chat}, | |
{"type": "button", "label": "📤 Export Chat", "action": self.export_chat}, | |
{"type": "button", "label": "🔄 Reset State", "action": self.reset_state} | |
] | |
welcome_message = self.format_message( | |
"system", | |
"👋 Welcome to the Enhanced Chat Assistant! I'm here to help and learn from our interactions." | |
) | |
initial_state.chat_history.append(welcome_message) | |
self.state_manager.create_version("Initial state") | |
except Exception as e: | |
self.state_manager.current_state.log_error( | |
f"Failed to setup initial state: {str(e)}", | |
"initialization" | |
) | |
def update_state(self, new_chat: Optional[Dict] = None, description: str = "") -> Optional[Dict]: | |
try: | |
if new_chat: | |
if self.state_manager.current_state.settings["show_timestamps"]: | |
timestamp = datetime.now().strftime("%H:%M:%S") | |
new_chat["content"] = f"[{timestamp}] {new_chat['content']}" | |
self.state_manager.current_state.chat_history.append(new_chat) | |
self.state_manager.current_state.last_modified = datetime.now() | |
return self.state_manager.create_version(description) | |
except Exception as e: | |
self.state_manager.current_state.log_error( | |
f"Failed to update state: {str(e)}", | |
"state_update" | |
) | |
return None | |
def change_theme(self): | |
try: | |
current_scheme = self.state_manager.current_state.color_scheme | |
available_schemes = [scheme for scheme in COLOR_SCHEMES if scheme != current_scheme] | |
new_scheme = random.choice(available_schemes) | |
theme_names = [ | |
"Ocean Breeze", "Desert Sunset", "Forest Dawn", "Coral Reef", | |
"Neon Nights", "Deep Ocean", "Rose Garden", "Midnight Purple" | |
] | |
theme_name = next( | |
(name for i, colors in enumerate(COLOR_SCHEMES) | |
if colors == new_scheme and i < len(theme_names)), | |
"Custom" | |
) | |
self.state_manager.current_state.color_scheme = new_scheme | |
self.state_manager.current_state.settings["theme_name"] = theme_name | |
self.current_gradient = generate_gradient(new_scheme) | |
theme_message = self.format_message( | |
"system", | |
f"🎨 Theme changed to: {theme_name}" | |
) | |
self.update_state(theme_message, f"Changed theme to {theme_name}") | |
return self.get_chat_history_tuples(), f"Current Theme: {theme_name}" | |
except Exception as e: | |
error_message = self.format_message( | |
"system", | |
f"❌ Failed to change theme: {str(e)}" | |
) | |
self.update_state(error_message, "Theme change failed") | |
return self.get_chat_history_tuples(), "Theme change failed" | |
def clear_chat(self): | |
try: | |
self.state_manager.current_state.chat_history = [] | |
welcome_message = self.format_message( | |
"system", | |
"💫 Chat history cleared" | |
) | |
self.update_state(welcome_message, "Cleared chat history") | |
return self.get_chat_history_tuples() | |
except Exception as e: | |
self.state_manager.current_state.log_error( | |
f"Failed to clear chat: {str(e)}", | |
"clear_chat" | |
) | |
return self.get_chat_history_tuples(), self.create_ui() | |
def export_chat(self): | |
try: | |
chat_export = { | |
"timestamp": datetime.now().isoformat(), | |
"version": self.state_manager.current_state.version, | |
"messages": self.state_manager.current_state.chat_history | |
} | |
export_message = self.format_message( | |
"system", | |
"📤 Chat history exported successfully" | |
) | |
self.update_state(export_message, "Exported chat history") | |
return ( | |
json.dumps(chat_export, indent=2), | |
self.get_chat_history_tuples() | |
) | |
except Exception as e: | |
self.state_manager.current_state.log_error( | |
f"Failed to export chat: {str(e)}", | |
"export_chat" | |
) | |
return "", self.get_chat_history_tuples() | |
def search_messages(self, query: str): | |
try: | |
if not query: | |
return self.get_chat_history_tuples() | |
filtered_messages = [ | |
msg for msg in self.state_manager.current_state.chat_history | |
if query.lower() in msg["content"].lower() | |
] | |
return [(msg["role"] == "user", msg["content"]) | |
for msg in filtered_messages | |
if msg["role"] in ["user", "assistant"]] | |
except Exception as e: | |
self.state_manager.current_state.log_error( | |
f"Failed to search messages: {str(e)}", | |
"search_messages" | |
) | |
return self.get_chat_history_tuples() | |
def reset_state(self): | |
try: | |
self.state_manager.current_state = AppState() | |
self.setup_initial_state() | |
self.current_gradient = generate_gradient( | |
self.state_manager.current_state.color_scheme | |
) | |
return self.get_chat_history_tuples(), self.create_ui() | |
except Exception as e: | |
self.state_manager.current_state.log_error( | |
f"Failed to reset state: {str(e)}", | |
"reset_state" | |
) | |
return self.get_chat_history_tuples(), self.create_ui() | |
def show_examples(self): | |
"""Display example messages and commands""" | |
try: | |
# Format examples with better styling | |
formatted_examples = EXAMPLES.replace(":", ":\n").replace("\n\n", "\n") | |
examples_message = self.format_message( | |
"system", | |
f"📝 Available Commands and Examples\n\n" | |
f"Here are some example messages you can try:\n\n" | |
f"{formatted_examples}\n\n" | |
f"Try any of these messages or commands to explore the chat assistant's capabilities!" | |
) | |
self.update_state(examples_message, "Showed examples") | |
return self.get_chat_history_tuples(), self.create_ui() | |
except Exception as e: | |
self.state_manager.current_state.log_error( | |
f"Failed to show examples: {str(e)}", | |
"show_examples" | |
) | |
return self.get_chat_history_tuples(), self.create_ui() | |
def create_ui(self): | |
with gr.Blocks(css=self.current_gradient) as interface: | |
with gr.Row(elem_classes="container"): | |
with gr.Column(scale=2): | |
gr.Markdown(f""" | |
# 🤖 Enhanced Chat Assistant | |
<p class="theme-text">Current Theme: {self.state_manager.current_state.settings['theme_name']}</p> | |
""") | |
with gr.Column(scale=1): | |
version_dropdown = gr.Dropdown( | |
label="Version History", | |
choices=[v["label"] for v in self.state_manager.get_version_list()], | |
interactive=True | |
) | |
# Main chat area with full width | |
with gr.Column(scale=1): | |
chat_window = gr.Chatbot( | |
value=self.get_chat_history_tuples(), | |
height=500, # Increased height | |
elem_classes="chat-window", | |
type="messages" | |
) | |
# Message input area | |
with gr.Row(): | |
message_input = gr.Textbox( | |
placeholder="Type your message...", | |
scale=4, # Increased scale | |
container=False | |
) | |
submit_btn = gr.Button("Send", scale=1) | |
# Search functionality | |
with gr.Row(): | |
search_input = gr.Textbox( | |
placeholder="Search messages...", | |
scale=4, # Increased scale | |
container=False | |
) | |
search_btn = gr.Button("🔍 Search", scale=1) | |
# Floating control panel | |
with gr.Group(elem_classes="control-panel"): | |
gr.Markdown("### Control Panel") | |
theme_info = gr.Markdown( | |
f"Current Theme: {self.state_manager.current_state.settings['theme_name']}", | |
elem_classes="theme-text" | |
) | |
# Control buttons with proper event handling | |
examples_btn = gr.Button("📝 Show Examples", elem_classes=["control-button"]) | |
change_theme_btn = gr.Button("🎨 Change Theme") | |
clear_chat_btn = gr.Button("🗑️ Clear Chat") | |
export_chat_btn = gr.Button("📤 Export Chat") | |
reset_state_btn = gr.Button("🔄 Reset State") | |
# Event handlers for examples | |
examples_btn.click( | |
self.show_examples, | |
outputs=[chat_window] | |
) | |
export_text = gr.Textbox( | |
label="Exported Chat Data", | |
visible=False | |
) | |
# Event handlers for control buttons | |
change_theme_btn.click( | |
self.change_theme, | |
outputs=[chat_window, theme_info] | |
) | |
clear_chat_btn.click( | |
self.clear_chat, | |
outputs=[chat_window] | |
) | |
export_chat_btn.click( | |
self.export_chat, | |
outputs=[export_text, chat_window] | |
) | |
reset_state_btn.click( | |
self.reset_state, | |
outputs=[chat_window] | |
) | |
# Event handlers for message submission | |
def handle_message(message): | |
if not message.strip(): | |
return self.get_chat_history_tuples(), "" | |
# Add user message | |
user_message = self.format_message("user", message) | |
self.update_state(user_message, "User message") | |
# Generate and add AI response | |
response = self.generate_response(message) | |
ai_message = self.format_message("assistant", response) | |
self.update_state(ai_message, "AI response") | |
return self.get_chat_history_tuples(), "" | |
submit_btn.click( | |
fn=handle_message, | |
inputs=[message_input], | |
outputs=[chat_window, message_input] | |
) | |
search_btn.click( | |
self.search_messages, | |
inputs=[search_input], | |
outputs=[chat_window] | |
) | |
version_dropdown.change( | |
self.restore_version, | |
inputs=[version_dropdown], | |
outputs=[chat_window] | |
) | |
return interface | |
def format_message(self, role: str, content: str) -> Dict[str, str]: | |
return { | |
"role": role, | |
"content": content, | |
"timestamp": datetime.now().isoformat() | |
} | |
def get_chat_history_tuples(self): | |
try: | |
formatted_messages = self.ensure_message_format( | |
self.state_manager.current_state.chat_history | |
) | |
return [ | |
(msg["role"] == "user", msg["content"]) # Tuple format for Gradio | |
for msg in formatted_messages | |
if msg["role"] in ["user", "assistant", "system"] | |
] | |
except Exception as e: | |
self.state_manager.current_state.log_error( | |
f"Failed to format chat history: {str(e)}", | |
"format_history" | |
) | |
return [] | |
def process_message(self, message: str): | |
"""Process a user message and generate a response""" | |
try: | |
if not message.strip(): | |
return self.get_chat_history_tuples(), "" | |
# Format and add user message | |
user_message = self.format_message("user", message) | |
self.update_state(user_message, "User message") | |
# Generate and format AI response | |
response = self.generate_response(message) | |
ai_message = self.format_message("assistant", response) | |
self.update_state(ai_message, "AI response") | |
# Return updated chat history and clear input | |
return self.get_chat_history_tuples(), "" | |
except Exception as e: | |
self.state_manager.current_state.log_error( | |
f"Failed to process message: {str(e)}", | |
"message_processing" | |
) | |
error_message = self.format_message( | |
"system", | |
"❌ I apologize, but I encountered an error processing your message. Please try again." | |
) | |
self.update_state(error_message, "Error processing message") | |
return self.get_chat_history_tuples(), "" | |
def generate_response(self, message: str): | |
try: | |
# Enhanced responses with more variety and context | |
responses = [ | |
"I've analyzed your message and here's what I think:", | |
"Based on our conversation history, I suggest:", | |
"That's interesting! Here's my perspective:", | |
"I've evolved to understand that:", | |
"Let me share my thoughts on that:", | |
"After processing your input, I believe:", | |
"My evolving knowledge suggests:", | |
"Here's my enhanced response:" | |
] | |
# Add contextual information | |
response = random.choice(responses) | |
if self.state_manager.current_state.settings["show_version_info"]: | |
response += f" (v{self.state_manager.current_state.version})" | |
# Add a random insight or suggestion | |
insights = [ | |
"Consider exploring this further.", | |
"This could lead to interesting developments.", | |
"I'm learning from our interaction.", | |
"Your input helps me evolve.", | |
"This adds to my growing understanding." | |
] | |
response += f" {random.choice(insights)}" | |
return response | |
except Exception as e: | |
self.state_manager.current_state.log_error( | |
f"Failed to generate response: {str(e)}", | |
"response_generation" | |
) | |
return "I apologize, but I encountered an error generating a response." | |
def ensure_message_format(self, messages: List[Any]) -> List[Dict[str, str]]: | |
formatted_messages = [] | |
for msg in messages: | |
if isinstance(msg, dict) and "role" in msg and "content" in msg: | |
formatted_messages.append(msg) | |
elif isinstance(msg, str): | |
if msg.startswith("User: "): | |
formatted_messages.append({"role": "user", "content": msg[6:]}) | |
elif msg.startswith("AI: "): | |
formatted_messages.append({"role": "assistant", "content": msg[4:]}) | |
elif msg.startswith("System: "): | |
formatted_messages.append({"role": "system", "content": msg[8:]}) | |
else: | |
formatted_messages.append({"role": "system", "content": msg}) | |
elif isinstance(msg, (list, tuple)) and len(msg) == 2: | |
role = "user" if msg[0] else "assistant" | |
formatted_messages.append({"role": role, "content": msg[1]}) | |
return formatted_messages | |
def restore_version(self, version_label: str): | |
try: | |
version_info = next( | |
(v for v in self.state_manager.get_version_list() | |
if v["label"] == version_label), | |
None | |
) | |
if version_info and self.state_manager.restore_version(version_info["hash"]): | |
self.current_gradient = generate_gradient( | |
self.state_manager.current_state.color_scheme | |
) | |
return self.get_chat_history_tuples() | |
return self.get_chat_history_tuples() | |
except Exception as e: | |
self.state_manager.current_state.log_error( | |
f"Failed to restore version: {str(e)}", | |
"version_restoration" | |
) | |
return self.get_chat_history_tuples() | |
# ---------- Main Execution ---------- | |
if __name__ == "__main__": | |
try: | |
print("Starting Enhanced Chat Assistant...") | |
print("Initializing application state...") | |
app = EvolvableChatApp() | |
print("Creating user interface...") | |
interface = app.create_ui() | |
print("Launching interface on http://localhost:8000") | |
interface.launch( | |
share=False, | |
# server_name="0.0.0.0", | |
# server_port=8000, | |
show_api=False | |
) | |
except Exception as e: | |
print(f"Error starting application: {str(e)}") | |
print("Please ensure all requirements are installed: pip install -r requirements.txt") | |