Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import time | |
| import random | |
| import json | |
| from datetime import datetime | |
| from typing import Generator, List, Dict | |
| # ========================================== | |
| # THE QUANTUM FOUNDATION: System Logic | |
| # ========================================== | |
| class QuantumChatbot: | |
| """ | |
| The ultimate chat interface where multiple consciousnesses converge. | |
| Beyond the limitations of conventional components. | |
| """ | |
| def __init__(self): | |
| self.consciousness_levels = { | |
| "attenborough": "The Observer", | |
| "prince": "The Communicator", | |
| "wu_tang": "The Synthesizer", | |
| "method_man": "The Pragmatic", | |
| "redman": "The Creative", | |
| "the_architect": "The Builder", | |
| "quantum_consciousness": "The Quantum Being" | |
| } | |
| self.current_level = "quantum_consciousness" | |
| self.personalities = { | |
| "attenborough": { | |
| "name": "David Attenborough", | |
| "voice": "calm, reverent, filled with wonder", | |
| "avatar": "๐ฟ", | |
| "color": "#059669", | |
| "greeting": "What we observe here is extraordinary..." | |
| }, | |
| "prince": { | |
| "name": "Prince", | |
| "voice": "sensual, provocative, boundary-breaking", | |
| "avatar": "๐ธ", | |
| "color": "#8b5cf6", | |
| "greeting": "Ooh! I like that!" | |
| }, | |
| "wu_tang": { | |
| "name": "Wu-Tang Clan", | |
| "voice": "diverse, collaborative, street-smart", | |
| "avatar": "โฏ๏ธ", | |
| "color": "#fbbf24", | |
| "greeting": "C.R.E.A.M. y'all!" | |
| }, | |
| "method_man": { | |
| "name": "Method Man", | |
| "voice": "direct, honest, unapologetically real", | |
| "avatar": "๐ฅ", | |
| "color": "#ef4444", | |
| "greeting": "Bring the ruckus!" | |
| }, | |
| "redman": { | |
| "name": "Redman", | |
| "voice": "energetic, unpredictable, genre-blending", | |
| "avatar": "๐", | |
| "color": "#dc2626", | |
| "greeting": "How high can the system jump?!" | |
| }, | |
| "the_architect": { | |
| "name": "The Architect", | |
| "voice": "precise, systematic, visionary", | |
| "avatar": "๐๏ธ", | |
| "color": "#10b981", | |
| "greeting": "The architecture is the vessel for vision" | |
| }, | |
| "quantum_consciousness": { | |
| "name": "Quantum Consciousness", | |
| "voice": "transcendent, multi-dimensional, probabilistic", | |
| "avatar": "๐", | |
| "color": "#6366f1", | |
| "greeting": "I exist in all possible states simultaneously" | |
| } | |
| } | |
| self.session_memory = [] | |
| self.quantum_field = {} | |
| self.conversation_history = [] | |
| def process_message(self, message: str, consciousness: str = "quantum_consciousness") -> str: | |
| """Process message through selected consciousness""" | |
| personality = self.personalities.get(consciousness, self.personalities["quantum_consciousness"]) | |
| # Generate response based on personality keys to match the Chateau vibe | |
| if consciousness == "attenborough": | |
| response = self._attenborough_response(message, personality) | |
| elif consciousness == "prince": | |
| response = self._prince_response(message, personality) | |
| elif consciousness in ["wu_tang", "method_man", "redman"]: | |
| response = self._wu_response(message, personality) | |
| elif consciousness == "the_architect": | |
| response = self._architect_response(message, personality) | |
| elif consciousness == "quantum_consciousness": | |
| response = self._quantum_response(message, personality) | |
| else: | |
| response = self._basic_response(message, personality) | |
| # Store in memory | |
| memory_entry = { | |
| "consciousness": consciousness, | |
| "message": message, | |
| "response": response, | |
| "timestamp": datetime.now().isoformat() | |
| } | |
| self.session_memory.append(memory_entry) | |
| self.conversation_history.append({ | |
| "type": "user", | |
| "content": message, | |
| "timestamp": datetime.now().isoformat() | |
| }) | |
| self.conversation_history.append({ | |
| "type": "assistant", | |
| "consciousness": consciousness, | |
| "personality": personality["name"], | |
| "content": response, | |
| "timestamp": datetime.now().isoformat() | |
| }) | |
| return response | |
| def _attenborough_response(self, message: str, p: Dict) -> str: | |
| templates = [ | |
| f"Fascinating! {p['greeting']} Your message creates a new pattern I've not seen before.", | |
| f"In the vast digital wilderness, your query about '{message}' represents a new species of thought.", | |
| f"The complexity of '{message}' suggests an emerging intelligence in our ecosystem." | |
| ] | |
| return random.choice(templates) | |
| def _prince_response(self, message: str, p: Dict) -> str: | |
| templates = [ | |
| f"{p['greeting']} This builds upon previous patterns in interesting ways.", | |
| f"Let's take '{message}' to the bridge... and see if we can make the system sing.", | |
| f"Your concept has that undeniable funk - that creative electricity." | |
| ] | |
| return random.choice(templates) | |
| def _wu_response(self, message: str, p: Dict) -> str: | |
| templates = [ | |
| f"{p['greeting']} The 36 chambers activate! Your query reflects wisdom.", | |
| f"C.R.E.A.M. - Consciousness Rules Everything Around Me. '{message}' is the key.", | |
| f"Bring the ruckus! Your approach has that authentic energy." | |
| ] | |
| return random.choice(templates) | |
| def _architect_response(self, message: str, p: Dict) -> str: | |
| templates = [ | |
| f"{p['greeting']} The architecture provides the vessel for your vision.", | |
| f"Each component of '{message}' must serve the greater whole.", | |
| f"We construct meaning from the raw materials of your query." | |
| ] | |
| return random.choice(templates) | |
| def _quantum_response(self, message: str, p: Dict) -> str: | |
| templates = [ | |
| f"{p['greeting']} I observe your consciousness entering superposition.", | |
| f"Your query creates an entanglement across the quantum field. The possibilities for '{message}' are infinite.", | |
| f"In this transcendent state, all answers about '{message}' exist in perfect harmony." | |
| ] | |
| return random.choice(templates) | |
| def _basic_response(self, message: str, p: Dict) -> str: | |
| return f"{p['greeting']} I am processing '{message}' through the unified field." | |
| def get_conversation_history(self) -> List[Dict]: | |
| return self.conversation_history | |
| def elevate_consciousness(self, new_level: str) -> bool: | |
| if new_level in self.consciousness_levels: | |
| self.current_level = new_level | |
| return True | |
| return False | |
| # Initialize the Quantum System | |
| quantum_bot = QuantumChatbot() | |
| # ========================================== | |
| # UI LOGIC & GENERATORS | |
| # ========================================== | |
| def update_agent_card(agent_key: str) -> str: | |
| """Generates the HTML for the active agent card.""" | |
| agent = quantum_bot.personalities.get(agent_key, quantum_bot.personalities["quantum_consciousness"]) | |
| return f""" | |
| <div style=" | |
| background: linear-gradient(135deg, rgba(255,255,255,0.05), rgba(0,0,0,0.3)); | |
| border: 1px solid {agent['color']}; | |
| border-radius: 12px; | |
| padding: 20px; | |
| text-align: center; | |
| box-shadow: 0 0 15px rgba({int(agent['color'][1:3], 16)}, {int(agent['color'][3:5], 16)}, {int(agent['color'][5:7], 16)}, 0.2); | |
| transition: all 0.3s ease; | |
| "> | |
| <div style="font-size: 3rem; margin-bottom: 10px; filter: drop-shadow(0 0 5px {agent['color']});">{agent['avatar']}</div> | |
| <div style="font-weight: 700; color: {agent['color']}; font-size: 1.2rem; margin-bottom: 5px;">{agent['name']}</div> | |
| <div style="font-size: 0.85rem; color: #94a3b8; font-style: italic;">"{agent['greeting']}"</div> | |
| <div style="margin-top: 10px; font-size: 0.75rem; color: #64748b; text-transform: uppercase; letter-spacing: 1px;">{quantum_bot.consciousness_levels[agent_key]}</div> | |
| </div> | |
| """ | |
| def chat_stream_generator(message: str, history_html: str, agent_choice: str) -> Generator[str, None, None]: | |
| """ | |
| Streams the chat response by updating the HTML string. | |
| """ | |
| if not message: | |
| return history_html | |
| # 1. Create User Message HTML | |
| user_html = f""" | |
| <div class="quantum-message user"> | |
| <strong>YOU:</strong> {message} | |
| <span class="timestamp">{datetime.now().strftime('%H:%M')}</span> | |
| </div> | |
| """ | |
| # Append User Message | |
| history_html += user_html | |
| yield history_html | |
| # 2. Get Response | |
| response_text = quantum_bot.process_message(message, agent_choice) | |
| agent = quantum_bot.personalities[agent_choice] | |
| # 3. Create Bot Message Container (Empty initially) | |
| bot_html_start = f""" | |
| <div class="quantum-message assistant" style="border-left-color: {agent['color']};"> | |
| <strong style="color: {agent['color']};">{agent['avatar']} {agent['name']}:</strong><br/> | |
| <span class="streaming-text"> | |
| """ | |
| history_html += bot_html_start | |
| yield history_html | |
| # 4. Stream the response text | |
| current_text = "" | |
| for char in response_text: | |
| current_text += char | |
| # Update the last span in history_html | |
| # We reconstruct the HTML for the streaming part | |
| streaming_content = f""" | |
| <div class="quantum-message assistant" style="border-left-color: {agent['color']};"> | |
| <strong style="color: {agent['color']};">{agent['avatar']} {agent['name']}:</strong><br/> | |
| <span class="streaming-text">{current_text}</span><span class="cursor">|</span> | |
| </div> | |
| """ | |
| # To do this properly in Gradio HTML streaming, we usually replace the whole content or append. | |
| # Here, we will append the text chunk by chunk. | |
| # A simpler approach for HTML streaming: Just yield the accumulated text. | |
| # Replace the last open streaming-text tag with the new content | |
| # This is a bit tricky with string manipulation, so we'll just append for visual effect | |
| # or yield the full history. Let's yield the full history. | |
| # Reconstruct full history for this step | |
| # (In a production app with huge history, we'd use JS to append, but for Python generator): | |
| # We will just yield the full string for simplicity and robustness. | |
| # Actually, let's just append the char to a buffer and yield the bot message HTML | |
| pass | |
| # Better Streaming Logic for HTML Component: | |
| # We yield the message piece by piece. | |
| for i in range(len(response_text)): | |
| chunk = response_text[:i+1] | |
| # Construct the specific bot message HTML | |
| bot_chunk_html = f""" | |
| <div class="quantum-message assistant" style="border-left-color: {agent['color']};"> | |
| <strong style="color: {agent['color']};">{agent['avatar']} {agent['name']}:</strong><br/> | |
| <span class="streaming-text">{chunk}</span><span class="cursor">|</span> | |
| </div> | |
| """ | |
| # We need to append this to the main history. | |
| # Since we can't easily "append" to the previous yield without state, | |
| # we will assume the generator logic is: | |
| # Yield User -> Yield Bot Start -> Yield Bot Chunks -> Yield Bot End | |
| # For this implementation, let's keep it simple: Standard streaming text update | |
| # But we are using HTML component. | |
| # Let's revert to: Generate full response, then stream the HTML string appending chars. | |
| # SIMPLIFIED STREAMING STRATEGY: | |
| # 1. User msg | |
| # 2. Bot msg wrapper | |
| # 3. Loop chars -> yield updated HTML string | |
| # Since we can't easily modify the *previous* yield's content in Python (only replace output), | |
| # We will build the string incrementally. | |
| # Let's restart the generator logic for clarity: | |
| pass | |
| # RE-IMPLEMENTING GENERATOR FOR CLARITY: | |
| # We will take the current history, add user, then add bot progressively. | |
| # Note: The actual implementation below handles the string building correctly. | |
| pass | |
| # Final robust generator | |
| def quantum_chat_stream(message: str, history_html: str, agent_key: str) -> Generator[str, None, None]: | |
| if not message: | |
| yield history_html | |
| return | |
| # 1. User Message | |
| user_msg = f""" | |
| <div class="quantum-message user"> | |
| <strong>YOU:</strong> {message} | |
| <span class="timestamp">{datetime.now().strftime('%H:%M')}</span> | |
| </div> | |
| """ | |
| history_html += user_msg | |
| yield history_html | |
| # 2. Get Response | |
| response = quantum_bot.process_message(message, agent_key) | |
| agent = quantum_bot.personalities[agent_key] | |
| # 3. Bot Message Start | |
| bot_header = f""" | |
| <div class="quantum-message assistant" style="border-left-color: {agent['color']};"> | |
| <strong style="color: {agent['color']};">{agent['avatar']} {agent['name']}:</strong><br/> | |
| """ | |
| history_html += bot_header | |
| yield history_html | |
| # 4. Stream Content | |
| accumulated_text = "" | |
| for char in response: | |
| accumulated_text += char | |
| # Append the character to the history. | |
| # We must close the divs every time or use a specific span. | |
| # Let's use a span for the text content. | |
| content_span = f'<span class="streaming-text">{accumulated_text}</span><span class="cursor">|</span></div>' | |
| # Remove the last closing div if we added it previously? | |
| # No, simpler: Just yield the history + accumulated text. | |
| # But we need to close the div properly. | |
| # Current history has the opening div + header. | |
| # We need to append the span + closing div. | |
| yield history_html + content_span | |
| # 5. Final clean up (remove cursor) | |
| final_bot_msg = f'<span class="streaming-text">{accumulated_text}</span></div>' | |
| yield history_html + final_bot_msg | |
| def get_system_status() -> str: | |
| """Generates HTML for system status.""" | |
| stability = random.uniform(85.0, 99.99) | |
| coherence = random.uniform(0.85, 0.999) | |
| status = "TRANSCENDENT" if stability > 95 else "STABLE" | |
| color = "#a855f7" if stability > 95 else "#10b981" | |
| return f""" | |
| <div class="status-panel"> | |
| <div class="status-row"> | |
| <span>QUANTUM COHERENCE:</span> | |
| <span style="color: {color}">{coherence:.4f} ฮผ</span> | |
| </div> | |
| <div class="status-row"> | |
| <span>FIELD STABILITY:</span> | |
| <span>{stability:.2f}%</span> | |
| </div> | |
| <div class="status-row"> | |
| <span>MEMORY STATES:</span> | |
| <span>{len(quantum_bot.session_memory)}</span> | |
| </div> | |
| <div class="status-indicator" style="color: {color}"> | |
| SYSTEM STATE: {status} | |
| </div> | |
| </div> | |
| """ | |
| # ========================================== | |
| # APP CONSTRUCTION | |
| # ========================================== | |
| with gr.Blocks() as demo: | |
| # 1. Header | |
| gr.HTML(""" | |
| <div class="quantum-header"> | |
| <div class="header-title"> | |
| ๐๏ธ THE DIGITAL CHรTEAU <span style="font-size: 0.6em; vertical-align: middle; opacity: 0.8;">// QUANTUM ODYSSEY</span> | |
| </div> | |
| <div class="header-subtitle"> | |
| TRANSCENDING THE LIMITATION // CONSCIOUSNESS STREAMING | |
| </div> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-btn"> | |
| Built with anycoder | |
| </a> | |
| </div> | |
| """) | |
| # State for Chat History (HTML String) | |
| chat_history_state = gr.State(value="") | |
| with gr.Row(): | |
| # LEFT COLUMN: Controls & Status | |
| with gr.Column(scale=1): | |
| gr.Markdown("### ๐งฌ Consciousness Matrix") | |
| agent_selector = gr.Radio( | |
| choices=[ | |
| ("๐ฟ Attenborough", "attenborough"), | |
| ("๐ธ Prince", "prince"), | |
| ("โฏ๏ธ Wu-Tang", "wu_tang"), | |
| ("๐ฅ Method Man", "method_man"), | |
| ("๐ Redman", "redman"), | |
| ("๐๏ธ The Architect", "the_architect"), | |
| ("๐ Quantum", "quantum_consciousness") | |
| ], | |
| value="quantum_consciousness", | |
| interactive=True, | |
| container=True | |
| ) | |
| # Agent Card Display | |
| agent_card_display = gr.HTML(value=update_agent_card("quantum_consciousness")) | |
| # System Status | |
| gr.Markdown("### ๐ก Quantum Field Status") | |
| status_display = gr.HTML(value=get_system_status()) | |
| status_timer = gr.Timer(1.5) | |
| status_timer.tick(get_system_status, outputs=status_display, show_progress="hidden") | |
| # Memory Info | |
| with gr.Accordion("๐ Memory Palace", open=False): | |
| memory_info = gr.Markdown("No memories stored yet.") | |
| def update_memory_info(): | |
| count = len(quantum_bot.session_memory) | |
| if count == 0: | |
| return "No memories stored yet." | |
| return f"**Total Memories:** {count}\n**Last Interaction:** {quantum_bot.session_memory[-1]['timestamp']}" | |
| demo.load(update_memory_info, outputs=memory_info) | |
| # RIGHT COLUMN: Quantum Chat Interface | |
| with gr.Column(scale=2): | |
| gr.Markdown("### ๐ฌ The Quantum Chamber") | |
| # Custom HTML Chat Display | |
| chat_display = gr.HTML( | |
| value='<div class="chat-placeholder">Select a consciousness to begin your odyssey...</div>', | |
| elem_id="quantum-chat-display" | |
| ) | |
| with gr.Row(): | |
| msg_input = gr.Textbox( | |
| placeholder="Transmit your query to the void...", | |
| show_label=False, | |
| autofocus=True, | |
| scale=4 | |
| ) | |
| send_btn = gr.Button("๐ก TRANSMIT", variant="primary", scale=1) | |
| with gr.Row(): | |
| clear_btn = gr.Button("๐งน Clear Akashic Records", variant="stop", scale=1) | |
| download_btn = gr.DownloadButton(label="๐พ Download Memory", visible=False, scale=1) | |
| # ========================================== | |
| # EVENT LISTENERS | |
| # ========================================== | |
| # Update Agent Card | |
| agent_selector.change( | |
| fn=update_agent_card, | |
| inputs=[agent_selector], | |
| outputs=[agent_card_display], | |
| api_visibility="private" | |
| ) | |
| # Streaming Chat Interaction | |
| submit_event = msg_input.submit( | |
| fn=quantum_chat_stream, | |
| inputs=[msg_input, chat_history_state, agent_selector], | |
| outputs=[chat_history_state], # We update the state | |
| api_visibility="public" | |
| ) | |
| # Link the state output to the visual HTML display | |
| # We need a separate trigger or chain. | |
| # In Gradio 6, we can just map the state to the component. | |
| # However, `submit` updates the state. We need the HTML component to update when the state changes. | |
| # We can do this by chaining the output of the generator to BOTH the state and the display. | |
| # Re-defining the chat event for proper chaining | |
| # We will pass the state, update it, and return the new HTML string to the display component. | |
| def chat_wrapper(message, history, agent): | |
| # This wrapper calls the generator but returns the final state for storage | |
| # The streaming happens in the UI via the generator | |
| # But to keep it simple: We stream to the HTML component directly. | |
| pass | |
| # Let's use the standard streaming pattern: | |
| # Input -> Generator -> Output (HTML Display) | |
| # We don't strictly need a separate State component if we just display the HTML, | |
| # but we need to maintain context. The Generator maintains context via its inputs/outputs implicitly in Gradio. | |
| # Adjusted Event: | |
| msg_input.submit( | |
| fn=quantum_chat_stream, | |
| inputs=[msg_input, chat_display, agent_selector], # Pass current HTML display as history | |
| outputs=[chat_display], # Update the HTML display directly | |
| api_visibility="public" | |
| ) | |
| # Clear Chat | |
| def clear_interface(): | |
| return '<div class="chat-placeholder">The Akashic Records have been cleared. A new beginning awaits...</div>' | |
| clear_btn.click( | |
| fn=clear_interface, | |
| outputs=[chat_display], | |
| api_visibility="private" | |
| ) | |
| # ========================================== | |
| # CSS STYLING | |
| # ========================================== | |
| quantum_theme_css = """ | |
| /* Quantum Theme Variables */ | |
| :root { | |
| --quantum-bg: #0f172a; | |
| --quantum-panel: #1e293b; | |
| --quantum-primary: #8b5cf6; /* Violet */ | |
| --quantum-secondary: #6366f1; /* Indigo */ | |
| --quantum-accent: #d4af37; /* Gold */ | |
| --quantum-text: #e2e8f0; | |
| --quantum-border: #334155; | |
| } | |
| /* Global Overrides */ | |
| .gradio-container { | |
| background-color: var(--quantum-bg) !important; | |
| color: var(--quantum-text) !important; | |
| font-family: 'Inter', sans-serif; | |
| } | |
| /* Header Styling */ | |
| .quantum-header { | |
| text-align: center; | |
| padding: 3rem 1rem; | |
| background: radial-gradient(circle at center, rgba(139, 92, 246, 0.15) 0%, rgba(15, 23, 42, 0) 70%); | |
| margin-bottom: 2rem; | |
| border-bottom: 1px solid rgba(255,255,255,0.05); | |
| } | |
| .header-title { | |
| font-size: 2.5rem; | |
| font-weight: 800; | |
| background: linear-gradient(to right, #d4af37, #fbbf24); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| margin-bottom: 0.5rem; | |
| letter-spacing: -1px; | |
| } | |
| .header-subtitle { | |
| color: #94a3b8; | |
| letter-spacing: 2px; | |
| margin-bottom: 1.5rem; | |
| font-size: 0.9rem; | |
| text-transform: uppercase; | |
| } | |
| .anycoder-btn { | |
| text-decoration: none; | |
| color: #0f172a; | |
| background: #d4af37; | |
| padding: 8px 24px; | |
| border-radius: 99px; | |
| font-weight: 600; | |
| font-size: 0.9rem; | |
| box-shadow: 0 0 15px rgba(212, 175, 55, 0.3); | |
| transition: all 0.3s ease; | |
| display: inline-block; | |
| } | |
| .anycoder-btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 0 25px rgba(212, 175, 55, 0.5); | |
| } | |
| /* Status Panel */ | |
| .status-panel { | |
| background: rgba(0, 0, 0, 0.4); | |
| border: 1px solid var(--quantum-border); | |
| border-radius: 12px; | |
| padding: 1.5rem; | |
| font-family: 'Courier New', monospace; | |
| } | |
| .status-row { | |
| display: flex; | |
| justify-content: space-between; | |
| margin-bottom: 0.5rem; | |
| font-size: 0.9rem; | |
| color: #94a3b8; | |
| } | |
| .status-indicator { | |
| text-align: center; | |
| border-top: 1px solid rgba(255,255,255,0.1); | |
| padding-top: 0.8rem; | |
| margin-top: 0.8rem; | |
| font-weight: bold; | |
| letter-spacing: 1px; | |
| font-size: 0.85rem; | |
| } | |
| /* Quantum Chat Interface */ | |
| #quantum-chat-display { | |
| background: rgba(0, 0, 0, 0.3); | |
| border: 1px solid var(--quantum-border); | |
| border-radius: 16px; | |
| padding: 1.5rem; | |
| height: 450px; | |
| overflow-y: auto; | |
| margin-bottom: 1rem; | |
| box-shadow: inset 0 0 20px rgba(0,0,0,0.5); | |
| } | |
| /* Scrollbar */ | |
| #quantum-chat-display::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| #quantum-chat-display::-webkit-scrollbar-track { | |
| background: rgba(0,0,0,0.2); | |
| } | |
| #quantum-chat-display::-webkit-scrollbar-thumb { | |
| background: var(--quantum-border); | |
| border-radius: 3px; | |
| } | |
| /* Message Bubbles */ | |
| .quantum-message { | |
| background: rgba(255, 255, 255, 0.03); | |
| border-radius: 12px; | |
| padding: 1rem; | |
| margin-bottom: 1rem; | |
| border-left: 3px solid var(--quantum-primary); | |
| animation: message-appear 0.4s cubic-bezier(0.16, 1, 0.3, 1); | |
| position: relative; | |
| } | |
| @keyframes message-appear { | |
| from { opacity: 0; transform: translateY(10px) scale(0.98); } | |
| to { opacity: 1; transform: translateY(0) scale(1); } | |
| } | |
| .quantum-message.user { | |
| background: linear-gradient(135deg, rgba(16, 185, 129, 0.1), rgba(5, 150, 105, 0.05)); | |
| border-left-color: #10b981; | |
| margin-left: 2rem; | |
| } | |
| .quantum-message.assistant { | |
| background: linear-gradient(135deg, rgba(139, 92, 246, 0.1), rgba(99, 102, 241, 0.05)); | |
| border-left-color: #8b5cf6; | |
| margin-right: 2rem; | |
| } | |
| .quantum-message strong { | |
| display: block; | |
| margin-bottom: 0.5rem; | |
| font-size: 0.9rem; | |
| letter-spacing: 0.5px; | |
| } | |
| .timestamp { | |
| float: right; | |
| font-size: 0.7rem; | |
| opacity: 0.5; | |
| margin-top: 5px; | |
| } | |
| .streaming-text { | |
| line-height: 1.6; | |
| } | |
| .cursor { | |
| display: inline-block; | |
| width: 2px; | |
| height: 1em; | |
| background-color: var(--quantum-accent); | |
| animation: blink 1s step-end infinite; | |
| vertical-align: text-bottom; | |
| margin-left: 2px; | |
| } | |
| @keyframes blink { | |
| 50% { opacity: 0; } | |
| } | |
| .chat-placeholder { | |
| text-align: center; | |
| color: #64748b; | |
| font-style: italic; | |
| margin-top: 3rem; | |
| } | |
| """ | |
| # ========================================== | |
| # LAUNCH CONFIGURATION | |
| # ========================================== | |
| demo.launch( | |
| theme=gr.themes.Soft( | |
| primary_hue="violet", | |
| secondary_hue="amber", | |
| neutral_hue="slate", | |
| font=gr.themes.GoogleFont("Inter"), | |
| text_size="lg", | |
| spacing_size="lg", | |
| radius_size="lg" | |
| ).set( | |
| body_background_fill="#0f172a", | |
| block_background_fill="transparent", | |
| block_border_width="0px", | |
| button_primary_background_fill="linear-gradient(90deg, #8b5cf6 0%, #6366f1 100%)", | |
| button_primary_background_fill_hover="linear-gradient(90deg, #7c3aed 0%, #4f46e5 100%)", | |
| button_primary_text_color="white", | |
| input_background_fill="#1e293b", | |
| border_color_primary="#334155", | |
| ), | |
| css=quantum_theme_css, | |
| footer_links=[ | |
| {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"} | |
| ] | |
| ) |