""" Prompt Engineering Training Chat โ Gradio App ๐ =================================================== Dark romantic neon theme with hearts. Deploy as a HuggingFace Space (Docker Space). Connects to local Flask API via ngrok/tunnel. """ import gradio as gr import requests import json import os from datetime import datetime from dotenv import load_dotenv,find_dotenv from pathlib import Path from modules.shimsalabim import ShimSalaBim load_dotenv(find_dotenv()) # --------------------------------------------------------------------------- # Configuration # --------------------------------------------------------------------------- DEFAULT_API_URL = os.environ.get("FLASK_API_URL", "https://3d02-2a02-a459-18b8-0-23e8-aa8f-ba25-669a.ngrok-free.app") # --------------------------------------------------------------------------- # Prompt Engineering Tips & Lessons # --------------------------------------------------------------------------- PROMPT_ENG_TIPS = { "System Prompt": """**The System Prompt** is the most powerful tool for controlling LLM behavior. **What it does:** Sets the "personality" and rules the model follows for the entire conversation. **Key techniques to try:** 1. **Role Assignment** โ Tell the model WHO it is: *"You are a senior sales consultant with 15 years of B2B SaaS experience."* 2. **Output Format** โ Specify HOW it should respond: *"Always respond in bullet points. Start with a summary, then details."* 3. **Constraints** โ Set boundaries: *"Never mention competitors by name. Keep responses under 100 words."* 4. **Tone Control** โ *"Speak in a friendly, conversational tone. Use 'you' and 'we' frequently."* 5. **Step-by-step** โ *"Think through the problem step by step before giving your final answer."* **Experiment:** Try the same user prompt with different system prompts and observe how the output changes dramatically!""", "Temperature": """**Temperature** controls randomness/creativity in the model's output. - **0.0 โ 0.3:** Very focused, deterministic, repetitive. Great for factual Q&A, data extraction, code. - **0.4 โ 0.7:** Balanced. Good for general conversation, explanations, brainstorming. - **0.8 โ 1.5:** Creative, unpredictable. Good for storytelling, poetry, creative writing. - **1.5+:** Chaotic, often incoherent. Useful to see what "too much creativity" looks like. **Try this:** Set temperature to 0 and ask the same question 3 times โ you'll get identical answers. Then set it to 1.2 and watch how the responses vary!""", "Top-P (Nucleus Sampling)": """**Top-P** (also called nucleus sampling) filters which tokens the model can choose from. - **0.1:** Only the most likely tokens (very focused, similar to low temperature). - **0.5:** Moderate filtering. - **0.9 โ 1.0:** Almost all tokens are candidates (more diverse). **The difference from temperature:** Temperature reshapes the probability distribution; Top-P cuts off the tail. They work together! **Try this:** Set temperature=0.8, top_p=0.1 โ focused but not robotic. Then top_p=0.95 โ much more varied.""", "Top-K": """**Top-K** limits the model to only choosing from the K most likely next tokens. - **K=1:** Always picks the single most likely token (greedy decoding). - **K=10-40:** Reasonable range for most tasks. - **K=100+:** Very permissive, can produce unexpected results. **When to use:** Top-K is a "hard cutoff" โ it completely eliminates unlikely tokens. Top-P is "softer" โ it adapts based on probability distribution. **Try this:** Set top_k=1 and temperature=1.0. You'll see temperature has no effect because only 1 token is available!""", "Max Tokens": """**Max Tokens** controls the maximum length of the model's response. - **50-100:** Short answers, ideal for classification, yes/no, single facts. - **200-500:** Medium responses, good for explanations, email drafts. - **500-2000:** Long-form content, articles, detailed analysis. **Tip for prompt engineering:** If you want concise answers, set max_tokens LOW (100-150) AND say in the system prompt "Keep responses brief." The combination is more reliable than either alone. **Try this:** Ask "Explain quantum computing" with max_tokens=50, then max_tokens=500. See how the model adapts!""", "Repeat Penalty": """**Repeat Penalty** discourages the model from repeating the same text. - **1.0:** No penalty (model may repeat itself). - **1.1-1.2:** Mild penalty (default, good for most uses). - **1.3-1.5:** Strong penalty (may produce awkward phrasing to avoid repetition). - **2.0+:** Extreme โ the model will contort its output to never repeat. **When to increase:** If the model gets stuck in loops ("The cat sat. The cat sat. The cat sat..."), increase this value. **Try this:** Set repeat_penalty=1.0 and ask for a long response โ watch for repetition. Then set it to 1.5 and compare.""", "Frequency & Presence Penalty": """**Frequency Penalty** reduces the likelihood of tokens that have already appeared frequently. It penalizes based on HOW OFTEN a token appeared. **Presence Penalty** reduces the likelihood of ANY token that has appeared at least once. It encourages the model to talk about NEW topics. - **Frequency 0.0 โ 0.5:** Subtle reduction of repetition. - **Presence 0.0 โ 0.5:** Encourages topic diversity. **Practical use:** For a sales email, you might want presence_penalty=0.3 to keep the model from fixating on one selling point. **Try this:** Ask "List 10 benefits of our product" with presence_penalty=0 vs presence_penalty=0.8. The higher value will push the model toward more diverse points.""", "n_ctx (Context Window)": """**n_ctx** is the context window size โ how many tokens the model can "see" at once (including both your prompt and its response). - **512:** Very limited. Only short conversations. - **2048:** Good for most single-turn Q&A and moderate conversations. - **4096+:** Needed for long documents or extended chat history. **Important:** n_ctx is set when the server starts (it determines how much RAM/VRAM to allocate). Changing it in the UI sends a request, but the server must be restarted for it to take effect. **Tradeoff:** Larger n_ctx = more memory usage but can handle longer conversations. Your model has a maximum n_ctx it was trained on (e.g., 4096 for Llama 2, 8192+ for some newer models).""", "Stop Sequences": """**Stop Sequences** tell the model to stop generating when it encounters specific text. Common uses: - `"\\nUser:"` โ Stop before the model starts simulating user messages. - `"\\n\\n"` โ Stop at double newlines (keeps responses to one paragraph). - `"<|end|>"` โ Model-specific end tokens. - `"---"` โ Stop before generating separators. **Try this:** Set a stop sequence of `"."` (a period) โ the model will stop after the first sentence! Remove it and it generates a full paragraph.""", "Effective Prompting Patterns": """**Proven patterns for better LLM outputs:** 1. **Few-Shot Examples:** *"Here are examples of good sales emails:* *Example 1: [your example]* *Example 2: [your example]* *Now write a similar email for [new situation]."* 2. **Chain of Thought:** *"Think step by step: First analyze the customer's needs, then identify our best matching product, then craft the pitch."* 3. **Specify the Audience:** *"Write this for a CTO who is technical but also cares about ROI. She has 15 minutes for this meeting."* 4. **Provide Structure:** *"Format your response as: 1) Key Insight, 2) Supporting Evidence, 3) Recommended Action."* 5. **Negative Instructions:** *"Do NOT use jargon. Do NOT mention pricing. Do NOT write more than 3 paragraphs."* 6. **Iterative Refinement:** Start simple, read the output, then refine your prompt based on what you liked and didn't like.""", } # --------------------------------------------------------------------------- # API Communication # --------------------------------------------------------------------------- def check_connection(api_url: str) -> str: """Test the connection to the Flask API.""" try: resp = requests.get(f"{api_url.rstrip('/')}/health", timeout=10) if resp.status_code == 200: data = resp.json() return f"๐ Connected! Model: {data.get('model', 'unknown')}, n_ctx: {data.get('n_ctx', '?')}" return f"โ ๏ธ Server responded with status {resp.status_code}: {resp.text}" except requests.exceptions.ConnectionError: return "๐ Cannot connect. Is the server running? Is the tunnel active?" except requests.exceptions.Timeout: return "๐ Connection timed out. The server might be slow or unreachable." except Exception as e: return f"๐ Error: {str(e)}" def send_chat( message: str, chat_history: list, api_url: str, system_prompt: str, max_tokens: int, temperature: float, top_p: float, top_k: int, repeat_penalty: float, frequency_penalty: float, presence_penalty: float, n_ctx: int, stop_sequences: str, ) -> tuple: """Send a chat message to the Flask API and get a response.""" if not message.strip(): return "", chat_history, "" # Build messages array in OpenAI format messages = [] if system_prompt.strip(): messages.append({"role": "system", "content": system_prompt.strip()}) # Add conversation history for user_msg, assistant_msg in chat_history: if user_msg: messages.append({"role": "user", "content": user_msg}) if assistant_msg: messages.append({"role": "assistant", "content": assistant_msg}) # Add current message messages.append({"role": "user", "content": message.strip()}) # Parse stop sequences stop = [] if stop_sequences.strip(): stop = [s.strip() for s in stop_sequences.split(",") if s.strip()] payload = { "messages": messages, "max_tokens": max_tokens, "temperature": temperature, "top_p": top_p, "top_k": top_k, "repeat_penalty": repeat_penalty, "frequency_penalty": frequency_penalty, "presence_penalty": presence_penalty, "n_ctx": n_ctx, "stop": stop if stop else None, } debug_info = f"**Request Payload:**\n```json\n{json.dumps(payload, indent=2)}\n```" try: resp = requests.post( f"{api_url.rstrip('/')}/chat", json=payload, timeout=120, ) if resp.status_code == 200: data = resp.json() assistant_content = data.get("message", {}).get("content", "") usage = data.get("usage", {}) elapsed = data.get("elapsed_seconds", "?") stats = ( f"๐ **Tokens:** Prompt {usage.get('prompt_tokens', '?')} โ " f"Completion {usage.get('completion_tokens', '?')} โ " f"Total {usage.get('total_tokens', '?')}\n" f"โฑ๏ธ **Time:** {elapsed}s\n" ) full_debug = f"{stats}\n{debug_info}" chat_history.append((message, assistant_content)) return "", chat_history, full_debug else: error_msg = f"๐ API Error ({resp.status_code}): {resp.text}" chat_history.append((message, error_msg)) return "", chat_history, debug_info except requests.exceptions.ConnectionError: error_msg = "๐ Cannot connect to the API. Check if the server is running and the tunnel is active." chat_history.append((message, error_msg)) return "", chat_history, debug_info except requests.exceptions.Timeout: error_msg = "๐ Request timed out (120s). The model might be taking too long." chat_history.append((message, error_msg)) return "", chat_history, debug_info except Exception as e: error_msg = f"๐ Error: {str(e)}" chat_history.append((message, error_msg)) return "", chat_history, debug_info def send_completion( prompt: str, api_url: str, system_prompt: str, max_tokens: int, temperature: float, top_p: float, top_k: int, repeat_penalty: float, frequency_penalty: float, presence_penalty: float, n_ctx: int, stop_sequences: str, ) -> tuple: """Send a raw completion request (no chat history) and get the result.""" if not prompt.strip(): return "", "" stop = [] if stop_sequences.strip(): stop = [s.strip() for s in stop_sequences.split(",") if s.strip()] payload = { "prompt": prompt.strip(), "system_prompt": system_prompt.strip(), "max_tokens": max_tokens, "temperature": temperature, "top_p": top_p, "top_k": top_k, "repeat_penalty": repeat_penalty, "frequency_penalty": frequency_penalty, "presence_penalty": presence_penalty, "n_ctx": n_ctx, "stop": stop if stop else None, } debug_info = f"**Request Payload:**\n```json\n{json.dumps(payload, indent=2)}\n```" try: resp = requests.post( f"{api_url.rstrip('/')}/generate", json=payload, timeout=120, ) if resp.status_code == 200: data = resp.json() text = data.get("text", "") usage = data.get("usage", {}) elapsed = data.get("elapsed_seconds", "?") stats = ( f"๐ **Tokens:** Prompt {usage.get('prompt_tokens', '?')} โ " f"Completion {usage.get('completion_tokens', '?')} โ " f"Total {usage.get('total_tokens', '?')}\n" f"โฑ๏ธ **Time:** {elapsed}s\n" ) return text, f"{stats}\n{debug_info}" else: return f"๐ API Error ({resp.status_code}): {resp.text}", debug_info except Exception as e: return f"๐ Error: {str(e)}", debug_info # --------------------------------------------------------------------------- # Presets for quick experimentation # --------------------------------------------------------------------------- PRESETS = { "๐ Default": { "system_prompt": "You are a helpful, harmless, and honest assistant.", "max_tokens": 512, "temperature": 0.7, "top_p": 0.9, "top_k": 40, "repeat_penalty": 1.1, "frequency_penalty": 0.0, "presence_penalty": 0.0, "stop": "", }, "๐ Factual / Analytical": { "system_prompt": "You are a precise, factual assistant. Always provide accurate information. If you're unsure, say so. Use structured formats like numbered lists and tables when appropriate.", "max_tokens": 300, "temperature": 0.2, "top_p": 0.8, "top_k": 20, "repeat_penalty": 1.15, "frequency_penalty": 0.0, "presence_penalty": 0.0, "stop": "", }, "โ๏ธ Creative Writer": { "system_prompt": "You are a creative and imaginative writer. Be vivid, expressive, and original. Use metaphors, sensory details, and varied sentence structures. Take creative risks.", "max_tokens": 800, "temperature": 1.0, "top_p": 0.95, "top_k": 80, "repeat_penalty": 1.05, "frequency_penalty": 0.2, "presence_penalty": 0.2, "stop": "", }, "๐ Sales Coach": { "system_prompt": "You are a senior sales coach who helps sales representatives improve their pitch, objection handling, and closing techniques. Give specific, actionable advice with examples. Be encouraging but honest about areas for improvement.", "max_tokens": 500, "temperature": 0.6, "top_p": 0.9, "top_k": 40, "repeat_penalty": 1.1, "frequency_penalty": 0.1, "presence_penalty": 0.1, "stop": "", }, "๐ง Step-by-Step Reasoner": { "system_prompt": "You are a logical, step-by-step reasoning assistant. Always break down problems into clear steps. Show your reasoning process. Use 'Step 1:', 'Step 2:', etc. format. Double-check your logic before giving the final answer.", "max_tokens": 600, "temperature": 0.3, "top_p": 0.85, "top_k": 30, "repeat_penalty": 1.1, "frequency_penalty": 0.0, "presence_penalty": 0.0, "stop": "", }, "๐ Concise Responder": { "system_prompt": "You are a concise assistant. Keep ALL responses under 50 words. Be direct and to the point. Never add filler or unnecessary elaboration.", "max_tokens": 80, "temperature": 0.5, "top_p": 0.9, "top_k": 40, "repeat_penalty": 1.15, "frequency_penalty": 0.0, "presence_penalty": 0.0, "stop": "", }, } # --------------------------------------------------------------------------- # Custom Dark Romantic Neon CSS # --------------------------------------------------------------------------- DARK_ROMANTIC_CSS = """ /* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ DARK ROMANTIC NEON THEME Black bg + Neon Pink/Magenta/Purple accents + Hearts โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ */ @import url('https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500;600;700&display=swap'); /* โโ Root overrides โโ */ :root { --neon-pink: #ff2d7b; --neon-magenta: #ff00ff; --neon-rose: #ff6b9d; --neon-purple: #b44dff; --neon-lavender: #d68fff; --dark-bg: #0a0a0a; --dark-surface: #111111; --dark-card: #161616; --dark-input: #1a1a1a; --dark-border: #2a1a24; --text-primary: #f0e6ef; --text-secondary: #b8a0b5; --text-dim: #7a6578; --glow-pink: 0 0 10px rgba(255,45,123,0.3), 0 0 20px rgba(255,45,123,0.15); --glow-purple: 0 0 10px rgba(180,77,255,0.3), 0 0 20px rgba(180,77,255,0.15); } /* โโ Body & overall background โโ */ body, .gradio-container { background: var(--dark-bg) !important; color: var(--text-primary) !important; font-family: 'Quicksand', sans-serif !important; } .main { background: var(--dark-bg) !important; } /* โโ Animated heart background โโ */ .gradio-container::before { content: ''; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(circle at 15% 25%, rgba(255,45,123,0.06) 0%, transparent 50%), radial-gradient(circle at 85% 75%, rgba(180,77,255,0.06) 0%, transparent 50%), radial-gradient(circle at 50% 50%, rgba(255,0,255,0.03) 0%, transparent 70%); pointer-events: none; z-index: 0; } /* โโ Hearts floating animation โโ */ @keyframes floatHeart { 0% { transform: translateY(100vh) rotate(0deg); opacity: 0; } 10% { opacity: 0.15; } 90% { opacity: 0.15; } 100% { transform: translateY(-10vh) rotate(360deg); opacity: 0; } } .gradio-container::after { content: 'โฅ โฅ โฅ โฅ โฅ โฅ โฅ โฅ โฅ โฅ โฅ โฅ โฅ โฅ โฅ'; position: fixed; top: 0; left: 0; right: 0; font-size: 24px; color: var(--neon-pink); letter-spacing: 80px; word-spacing: 120px; animation: floatHeart 25s linear infinite; pointer-events: none; z-index: 0; opacity: 0.08; } /* โโ All panels, cards, containers โโ */ .panel, .card, .block, .gr-panel, .gr-card, .contain .card, .contain .block, [data-testid="block"], .gr-box { background: var(--dark-card) !important; border-color: var(--dark-border) !important; border-radius: 12px !important; } /* โโ Section backgrounds โโ */ section, .gr-group, .gr-form { background: var(--dark-surface) !important; border-color: var(--dark-border) !important; } /* โโ Input & textarea styling โโ */ input[type="text"], textarea, select, .gr-input, .gr-text-input, .gr-textarea, [data-testid="textbox"] input, [data-testid="textbox"] textarea { background: var(--dark-input) !important; color: var(--text-primary) !important; border: 1px solid var(--dark-border) !important; border-radius: 8px !important; caret-color: var(--neon-pink) !important; } input[type="text"]:focus, textarea:focus, select:focus, .gr-input:focus, .gr-text-input:focus, .gr-textarea:focus { border-color: var(--neon-pink) !important; box-shadow: var(--glow-pink) !important; outline: none !important; } /* โโ Slider styling โโ */ input[type="range"], .gr-slider input[type="range"] { accent-color: var(--neon-pink) !important; } .gr-slider .range-wrap .range-data .range-info { color: var(--neon-rose) !important; } /* โโ Dropdown / Select โโ */ .gr-dropdown, select, .gr-select { background: var(--dark-input) !important; color: var(--text-primary) !important; border: 1px solid var(--dark-border) !important; } /* โโ Buttons โโ */ button.primary, .gr-button-primary, .btn-primary { background: linear-gradient(135deg, var(--neon-pink), var(--neon-purple)) !important; color: #ffffff !important; border: none !important; border-radius: 10px !important; font-weight: 600 !important; letter-spacing: 0.5px !important; box-shadow: var(--glow-pink) !important; transition: all 0.3s ease !important; } button.primary:hover, .gr-button-primary:hover, .btn-primary:hover { background: linear-gradient(135deg, var(--neon-rose), var(--neon-magenta)) !important; box-shadow: 0 0 15px rgba(255,45,123,0.5), 0 0 30px rgba(255,0,255,0.3) !important; transform: translateY(-1px) !important; } button.secondary, .gr-button-secondary, .btn-secondary { background: var(--dark-card) !important; color: var(--neon-rose) !important; border: 1px solid var(--neon-pink) !important; border-radius: 10px !important; transition: all 0.3s ease !important; } button.secondary:hover, .gr-button-secondary:hover, .btn-secondary:hover { background: rgba(255,45,123,0.1) !important; box-shadow: var(--glow-pink) !important; } button.stop, .gr-button-stop { background: var(--dark-card) !important; color: #ff4466 !important; border: 1px solid #ff4466 !important; border-radius: 10px !important; } button.stop:hover, .gr-button-stop:hover { background: rgba(255,68,102,0.1) !important; box-shadow: 0 0 10px rgba(255,68,102,0.3) !important; } /* โโ Chatbot area โโ */ .gr-chatbot, [data-testid="chatbot"] { background: var(--dark-input) !important; border: 1px solid var(--dark-border) !important; border-radius: 12px !important; } .gr-chatbot .message.user, [data-testid="chatbot"] .message.user { background: linear-gradient(135deg, rgba(255,45,123,0.15), rgba(180,77,255,0.15)) !important; color: var(--text-primary) !important; border-left: 3px solid var(--neon-pink) !important; border-radius: 0 10px 10px 0 !important; } .gr-chatbot .message.bot, [data-testid="chatbot"] .message.bot, .gr-chatbot .message.assistant, [data-testid="chatbot"] .message.assistant { background: rgba(180,77,255,0.08) !important; color: var(--text-primary) !important; border-left: 3px solid var(--neon-purple) !important; border-radius: 0 10px 10px 0 !important; } /* โโ Labels โโ */ label, .gr-label, [data-testid="label"] { color: var(--neon-rose) !important; font-weight: 600 !important; } /* โโ Info text under controls โโ */ .gr-info, .gr-input-info, [data-testid="info"] { color: var(--text-dim) !important; font-size: 0.85em !important; } /* โโ Markdown text โโ */ .markdown-text, .gr-markdown, .prose { color: var(--text-primary) !important; } .markdown-text h1, .gr-markdown h1, .prose h1, .markdown-text h2, .gr-markdown h2, .prose h2, .markdown-text h3, .gr-markdown h3, .prose h3 { color: var(--neon-rose) !important; border-color: var(--dark-border) !important; } .markdown-text strong, .gr-markdown strong, .prose strong { color: var(--neon-lavender) !important; } .markdown-text code, .gr-markdown code, .prose code { background: var(--dark-input) !important; color: var(--neon-pink) !important; border: 1px solid var(--dark-border) !important; border-radius: 4px !important; } .markdown-text a, .gr-markdown a, .prose a { color: var(--neon-pink) !important; } .markdown-text pre, .gr-markdown pre, .prose pre { background: var(--dark-input) !important; border: 1px solid var(--dark-border) !important; border-radius: 8px !important; } .markdown-text pre code, .gr-markdown pre code, .prose pre code { border: none !important; } /* โโ Horizontal rules โโ */ hr, .gr-hr { border-color: var(--dark-border) !important; background: linear-gradient(90deg, transparent, var(--neon-pink), transparent) !important; height: 1px !important; } /* โโ Scrollbar โโ */ ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: var(--dark-bg) !important; } ::-webkit-scrollbar-thumb { background: var(--neon-pink) !important; border-radius: 4px; opacity: 0.5; } ::-webkit-scrollbar-thumb:hover { background: var(--neon-rose) !important; } /* โโ Tab styling โโ */ .tab-nav, .gr-tab-nav { border-color: var(--dark-border) !important; } .tab-nav button, .gr-tab-nav button { color: var(--text-secondary) !important; } .tab-nav button.selected, .gr-tab-nav button.selected { color: var(--neon-pink) !important; border-color: var(--neon-pink) !important; } /* โโ Title glow effect โโ */ .title-glow { text-shadow: 0 0 10px rgba(255,45,123,0.5), 0 0 20px rgba(255,0,255,0.3); } /* โโ Heart dividers โโ */ .heart-divider { text-align: center; color: var(--neon-pink); font-size: 18px; letter-spacing: 12px; opacity: 0.4; margin: 8px 0; text-shadow: 0 0 8px rgba(255,45,123,0.4); } /* โโ Neon border accent โโ */ .neon-border { border: 1px solid var(--neon-pink) !important; box-shadow: var(--glow-pink) !important; border-radius: 12px !important; padding: 16px !important; background: var(--dark-card) !important; } /* โโ Connection status glow โโ */ #connection-status input, #connection-status textarea { font-family: 'Quicksand', sans-serif !important; } /* โโ API URL monospace โโ */ #api-url input { font-family: 'Courier New', monospace !important; color: var(--neon-lavender) !important; } /* โโ Placeholder text โโ */ ::placeholder { color: var(--text-dim) !important; } /* โโ Row dividers with hearts โโ */ .heart-separator { display: flex; align-items: center; gap: 12px; margin: 16px 0; } .heart-separator::before, .heart-separator::after { content: ''; flex: 1; height: 1px; background: linear-gradient(90deg, transparent, var(--neon-pink), transparent); } /* โโ Tooltip / popup โโ */ .gr-tooltip, .tooltip { background: var(--dark-card) !important; color: var(--text-primary) !important; border: 1px solid var(--neon-pink) !important; } /* โโ Footer โโ */ footer { display: none !important; } /* โโ Gradio built-in theme overrides โโ */ .gap { gap: 8px !important; } /* โโ Accordion โโ */ .gr-accordion, details { background: var(--dark-card) !important; border-color: var(--dark-border) !important; } .gr-accordion summary, details summary { color: var(--neon-rose) !important; } /* โโ Bubble chat layout colors โโ */ .message.bubble.user { background: linear-gradient(135deg, rgba(255,45,123,0.2), rgba(180,77,255,0.15)) !important; } .message.bubble.bot, .message.bubble.assistant { background: rgba(214,143,255,0.1) !important; } """ # --------------------------------------------------------------------------- # Build the Gradio Interface # --------------------------------------------------------------------------- def apply_preset(preset_name: str): """Apply a preset and return all parameter values.""" if preset_name in PRESETS: p = PRESETS[preset_name] return ( p["system_prompt"], p["max_tokens"], p["temperature"], p["top_p"], p["top_k"], p["repeat_penalty"], p["frequency_penalty"], p["presence_penalty"], p["stop"], ) return [gr.update()] * 9 def build_ui(): """Build the full Gradio interface with dark romantic neon theme.""" with gr.Blocks( title="๐ Prompt Engineering Lab", theme=gr.themes.Base( primary_hue="pink", secondary_hue="purple", neutral_hue="stone", ), css=DARK_ROMANTIC_CSS, ) as demo: # ---- Header ---- gr.HTML("""
Learn prompt engineering by experimenting with every LLM parameter โฅ
Multi-turn conversation with memory โฅ
Single-turn, no history โ test prompts in isolation โฅ
Load a preset to see how different settings create different behaviors ๐
Learn what each parameter does ๐
Prompt Engineering Lab ๐ Experiment ยท Learn ยท Master ๐