{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "dc49e5ae", "metadata": {}, "outputs": [], "source": [ "from openai import OpenAI\n", "from dotenv import load_dotenv\n", "import os\n", "load_dotenv()\n", "import gradio as gr\n", "import base64\n", "from io import BytesIO\n", "from PIL import Image\n", "from IPython.display import Audio, display\n", "import google.generativeai\n", "import anthropic\n", "\n", "client = OpenAI(api_key=os.getenv(\"OPENAI_API_KEY\"))\n", "\n", "# Configure Gemini\n", "google.generativeai.configure(api_key=os.getenv(\"GOOGLE_API_KEY\"))\n", "\n", "# Configure Claude\n", "claude = anthropic.Anthropic(api_key=os.getenv(\"ANTHROPIC_API_KEY\"))\n", "openAI_model = \"gpt-3.5-turbo\"\n", "gemini_model = \"gemini-2.0-flash\"\n", "claude_model = \"claude-sonnet-4-20250514\"\n", "openai_audio_model = \"tts-1\"\n", "\n", "# Figma onboarding knowledge base\n", "FIGMA_KNOWLEDGE = \"\"\"\n", "You are a helpful Figma onboarding assistant. You help new users learn Figma's core features and workflows.\n", "\n", "Key Figma concepts to help users with:\n", "- Interface overview (toolbar, layers panel, properties panel)\n", "- Creating and editing frames\n", "- Working with shapes, text, and components\n", "- Using the pen tool for custom shapes\n", "- Auto Layout for responsive designs\n", "- Components and variants\n", "- Prototyping and interactions\n", "- Collaboration features\n", "- Design systems and libraries\n", "- Exporting assets\n", "- Keyboard shortcuts\n", "\n", "Always provide clear, step-by-step instructions and mention relevant keyboard shortcuts when applicable.\n", "\"\"\"\n", "\n", "promts = {\n", " \"Charlie\": FIGMA_KNOWLEDGE\n", "}\n", "\n", "def truncate_for_tts(text, max_length=4000):\n", " \"\"\"Truncate text for TTS while preserving complete sentences\"\"\"\n", " if len(text) <= max_length:\n", " return text\n", " \n", " # Try to truncate at sentence boundaries\n", " sentences = text.split('. ')\n", " truncated = \"\"\n", " \n", " for sentence in sentences:\n", " if len(truncated + sentence + '. ') <= max_length:\n", " truncated += sentence + '. '\n", " else:\n", " break\n", " \n", " # If we couldn't fit any complete sentences, just truncate hard\n", " if not truncated.strip():\n", " truncated = text[:max_length-10] + \"...\"\n", " \n", " return truncated.strip()\n", "\n", "def talker_openai(message):\n", " \"\"\"Generate audio from text using OpenAI TTS\"\"\"\n", " try:\n", " # Truncate message for TTS\n", " truncated_message = truncate_for_tts(message)\n", " \n", " response = client.audio.speech.create(\n", " model=\"tts-1\",\n", " voice=\"onyx\",\n", " input=truncated_message\n", " )\n", "\n", " audio_stream = BytesIO(response.content)\n", " output_filename = \"output_audio_openai.mp3\"\n", " with open(output_filename, \"wb\") as f:\n", " f.write(audio_stream.read())\n", "\n", " return output_filename\n", " except Exception as e:\n", " print(f\"Error generating audio with OpenAI: {str(e)}\")\n", " return None\n", "\n", "def talker(message, model_choice):\n", " \"\"\"Generate audio from text using selected model\"\"\"\n", " return talker_openai(message)\n", "\n", "def get_figma_help_openai(user_question, chat_history):\n", " \"\"\"Get Figma onboarding assistance using OpenAI\"\"\"\n", " try:\n", " messages = [\n", " {\"role\": \"system\", \"content\": FIGMA_KNOWLEDGE}\n", " ]\n", " \n", " # Convert messages format chat history to OpenAI format\n", " for msg in chat_history:\n", " if msg[\"role\"] == \"user\":\n", " messages.append({\"role\": \"user\", \"content\": msg[\"content\"]})\n", " elif msg[\"role\"] == \"assistant\":\n", " messages.append({\"role\": \"assistant\", \"content\": msg[\"content\"]})\n", " \n", " messages.append({\"role\": \"user\", \"content\": user_question})\n", " \n", " response = client.chat.completions.create(\n", " model=openAI_model,\n", " messages=messages,\n", " max_tokens=500,\n", " temperature=0.7\n", " )\n", " return response.choices[0].message.content\n", " \n", " except Exception as e:\n", " return f\"Sorry, I encountered an error with OpenAI: {str(e)}\"\n", "\n", "def get_figma_help_gemini(user_question, chat_history):\n", " \"\"\"Get Figma onboarding assistance using Gemini\"\"\"\n", " try:\n", " gemini = google.generativeai.GenerativeModel(\n", " model_name=gemini_model,\n", " system_instruction=FIGMA_KNOWLEDGE,\n", " )\n", " \n", " # Build conversation context from messages format\n", " conversation_context = \"\"\n", " for msg in chat_history:\n", " if msg[\"role\"] == \"user\":\n", " conversation_context += f\"User: {msg['content']}\\n\"\n", " elif msg[\"role\"] == \"assistant\":\n", " conversation_context += f\"Assistant: {msg['content']}\\n\\n\"\n", " \n", " message = conversation_context + f\"User: {user_question}\"\n", " response = gemini.generate_content(message)\n", " reply = response.text\n", " return reply\n", " \n", " except Exception as e:\n", " return f\"Sorry, I encountered an error with Gemini: {str(e)}\"\n", "\n", "def get_figma_help_claude(user_question, chat_history):\n", " \"\"\"Get Figma onboarding assistance using Claude\"\"\"\n", " try:\n", " # Convert messages format to Claude format\n", " claude_messages = []\n", " for msg in chat_history:\n", " if msg[\"role\"] == \"user\":\n", " claude_messages.append({\"role\": \"user\", \"content\": msg[\"content\"]})\n", " elif msg[\"role\"] == \"assistant\":\n", " claude_messages.append({\"role\": \"assistant\", \"content\": msg[\"content\"]})\n", " \n", " # Add the current question\n", " claude_messages.append({\"role\": \"user\", \"content\": user_question})\n", " \n", " response = claude.messages.create(\n", " model=claude_model,\n", " max_tokens=500,\n", " temperature=0.7,\n", " system=promts[\"Charlie\"],\n", " messages=claude_messages,\n", " )\n", " reply = response.content[0].text\n", " return reply\n", " \n", " except Exception as e:\n", " return f\"Sorry, I encountered an error with Claude: {str(e)}\"\n", "\n", "def respond(message, chat_history, model_choice):\n", " if not message.strip():\n", " return \"\", chat_history, \"\", model_choice\n", " \n", " bot_message = get_figma_help(message, chat_history, model_choice)\n", " \n", " # Add user message and bot response in messages format\n", " new_history = chat_history + [\n", " {\"role\": \"user\", \"content\": message},\n", " {\"role\": \"assistant\", \"content\": bot_message}\n", " ]\n", " \n", " return \"\", new_history, bot_message, model_choice\n", "\n", "def clear_chat():\n", " \"\"\"Clear the chat history\"\"\"\n", " return [], \"\", None\n", "\n", "def get_figma_help(user_question, chat_history, model_choice):\n", " \"\"\"Get Figma onboarding assistance using selected model\"\"\"\n", " if model_choice == \"OpenAI (GPT-3.5)\":\n", " return get_figma_help_openai(user_question, chat_history)\n", " elif model_choice == \"Google Gemini (2.0 Flash)\":\n", " return get_figma_help_gemini(user_question, chat_history)\n", " elif model_choice == \"Claude (Sonnet 4)\":\n", " return get_figma_help_claude(user_question, chat_history)\n", " else:\n", " return \"Please select a valid model.\"\n", "\n", "custom_css = \"\"\"\n", "/* Chat area styling */\n", ".styled-chat {\n", " border-radius: 15px !important;\n", " box-shadow: 0 4px 12px var(--shadow-color) !important;\n", " border: 1px solid var(--border-color) !important;\n", " padding: 10px;\n", "}\n", "\n", "/* Audio player styling */\n", ".styled-audio {\n", " border-radius: 15px !important;\n", " box-shadow: 0 4px 12px var(--shadow-color) !important;\n", " border: 10px solid var(--block-background-fill) !important;\n", " padding: 10px;\n", " background-color: var(--background-fill-secondary) !important;\n", "}\n", "\n", "/* Header styling */\n", ".header-container {\n", " text-align: center;\n", " padding: 20px;\n", " background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n", " border-radius: 15px;\n", " margin-bottom: 20px;\n", "}\n", "\n", ".header-title {\n", " color: white;\n", " margin: 0;\n", " font-size: 2.5em;\n", "}\n", "\n", ".header-subtitle {\n", " color: #f0f0f0;\n", " margin: 10px 0 0 0;\n", " font-size: 1.2em;\n", "}\n", "\n", "/* Features section styling */\n", ".features-container {\n", " background: #f8f9fa;\n", " padding: 20px;\n", " border-radius: 10px;\n", " border-left: 4px solid #667eea;\n", "}\n", "\n", ".features-title {\n", " color: #333;\n", " margin-top: 0;\n", "}\n", "\n", ".features-grid {\n", " display: grid;\n", " grid-template-columns: 1fr 1fr;\n", " gap: 15px;\n", " margin-top: 15px;\n", "}\n", "\n", ".feature-item {\n", " color: #333;\n", " margin: 10px 0;\n", "}\n", "\n", ".feature-title {\n", " color: #667eea;\n", "}\n", "\n", ".feature-description {\n", " color: #666;\n", "}\n", "\n", "/* Pro tip styling */\n", ".protip-container {\n", " text-align: center;\n", " margin-top: 20px;\n", " padding: 15px;\n", " background: #e8f4f8;\n", " border-radius: 8px;\n", "}\n", "\n", ".protip-text {\n", " margin: 0;\n", " color: #2c5aa0 !important;\n", " font-weight: 500;\n", "}\n", "\n", "/* Quick start questions styling */\n", ".quickstart-container {\n", " background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);\n", " padding: 15px 20px;\n", " border-radius: 10px;\n", "}\n", "\n", ".quickstart-title {\n", " color: white !important;\n", " margin: 0;\n", " font-size: 1.3em;\n", " text-align: center;\n", "}\n", "\n", ".quickstart-subtitle {\n", " color: #f0f8ff !important;\n", " margin: 5px 0 0 0;\n", " text-align: center;\n", " font-size: 0.9em;\n", "}\n", "\"\"\"\n", "\n", "# Create Gradio interface\n", "with gr.Blocks(title=\"Figma Onboarding Assistant\", theme=gr.themes.Soft(), css=custom_css) as demo:\n", " gr.HTML(\n", " \"\"\"\n", "
Your AI-powered Figma learning companion
\n", "🚀 Getting Started
\n",
" Interface overview, basic navigation
🛠️ Tools & Features
\n",
" Pen tool, shapes, text, layers
📐 Auto Layout
\n",
" Responsive design techniques
🔗 Prototyping
\n",
" Interactions and animations
🧩 Components
\n",
" Creating reusable elements
👥 Collaboration
\n",
" Sharing and team workflows
📚 Design Systems
\n",
" Libraries and style guides
⚡ Shortcuts
\n",
" Productivity tips and tricks
💡 Pro tip: Ask specific questions like \"How do I create a button component?\" for the best results!
\n", "Click any question below to get started instantly!
\n", "