|
import streamlit as st |
|
import json |
|
import zipfile |
|
import io |
|
import time |
|
import os |
|
import requests |
|
from PIL import Image |
|
import base64 |
|
import textwrap |
|
from dotenv import load_dotenv |
|
from openai import OpenAI |
|
|
|
|
|
load_dotenv() |
|
|
|
|
|
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) if os.getenv("OPENAI_API_KEY") else None |
|
ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY") |
|
|
|
|
|
|
|
|
|
|
|
class TopicAgent: |
|
def generate_outline(self, topic, duration, difficulty): |
|
if not openai_client: |
|
return self._mock_outline(topic, duration, difficulty) |
|
|
|
try: |
|
response = openai_client.chat.completions.create( |
|
model="gpt-4-turbo", |
|
messages=[ |
|
{ |
|
"role": "system", |
|
"content": "You're an expert corporate trainer creating comprehensive AI workshop outlines." |
|
}, |
|
{ |
|
"role": "user", |
|
"content": ( |
|
f"Create a detailed {duration}-hour {difficulty} workshop outline on {topic}. " |
|
"Include: 4-6 modules with specific learning objectives, hands-on exercises, " |
|
"and real-world case studies. Format as JSON with keys: " |
|
"{'topic', 'duration', 'difficulty', 'goals', 'modules': [" |
|
"{'title', 'duration', 'learning_objectives', 'case_study', 'exercises'}]}" |
|
) |
|
} |
|
], |
|
temperature=0.3, |
|
max_tokens=1500, |
|
response_format={"type": "json_object"} |
|
) |
|
return json.loads(response.choices[0].message.content) |
|
except Exception as e: |
|
st.error(f"Outline generation error: {str(e)}") |
|
return self._mock_outline(topic, duration, difficulty) |
|
|
|
def _mock_outline(self, topic, duration, difficulty): |
|
return { |
|
"topic": topic, |
|
"duration": f"{duration} hours", |
|
"difficulty": difficulty, |
|
"goals": [ |
|
"Master core concepts and advanced techniques", |
|
"Develop practical implementation skills", |
|
"Learn industry best practices and case studies", |
|
"Build confidence in real-world applications" |
|
], |
|
"modules": [ |
|
{ |
|
"title": "Foundations of Prompt Engineering", |
|
"duration": "90 min", |
|
"learning_objectives": [ |
|
"Understand prompt components and structure", |
|
"Learn prompt patterns and anti-patterns", |
|
"Master zero-shot and few-shot prompting" |
|
], |
|
"case_study": "How Anthropic improved customer support with prompt engineering", |
|
"exercises": [ |
|
"Craft effective prompts for different scenarios", |
|
"Optimize prompts for specific AI models" |
|
] |
|
}, |
|
{ |
|
"title": "Advanced Techniques & Strategies", |
|
"duration": "120 min", |
|
"learning_objectives": [ |
|
"Implement chain-of-thought prompting", |
|
"Use meta-prompts for complex tasks", |
|
"Apply self-consistency methods" |
|
], |
|
"case_study": "OpenAI's approach to prompt engineering in GPT-4", |
|
"exercises": [ |
|
"Design prompts for multi-step reasoning", |
|
"Create self-correcting prompt systems" |
|
] |
|
} |
|
] |
|
} |
|
|
|
class ContentAgent: |
|
def generate_content(self, outline): |
|
if not openai_client: |
|
return self._mock_content(outline) |
|
|
|
try: |
|
response = openai_client.chat.completions.create( |
|
model="gpt-4-turbo", |
|
messages=[ |
|
{ |
|
"role": "system", |
|
"content": "You're a corporate training content developer creating detailed workshop materials." |
|
}, |
|
{ |
|
"role": "user", |
|
"content": ( |
|
f"Expand this workshop outline into comprehensive content: {json.dumps(outline)}. " |
|
"For each module, include: detailed script (3-5 paragraphs), speaker notes (bullet points), " |
|
"3 quiz questions with explanations, and exercise instructions. Format as JSON with keys: " |
|
"{'workshop_title', 'modules': [{'title', 'script', 'speaker_notes', 'quiz': [" |
|
"{'question', 'options', 'answer', 'explanation'}], 'exercise_instructions'}]}" |
|
) |
|
} |
|
], |
|
temperature=0.4, |
|
max_tokens=2000, |
|
response_format={"type": "json_object"} |
|
) |
|
return json.loads(response.choices[0].message.content) |
|
except Exception as e: |
|
st.error(f"Content generation error: {str(e)}") |
|
return self._mock_content(outline) |
|
|
|
def _mock_content(self, outline): |
|
return { |
|
"workshop_title": f"Mastering {outline['topic']}", |
|
"modules": [ |
|
{ |
|
"title": "Foundations of Prompt Engineering", |
|
"script": "This module introduces the core concepts of effective prompt engineering...", |
|
"speaker_notes": [ |
|
"Emphasize the importance of clear instructions", |
|
"Show examples of good vs bad prompts", |
|
"Discuss token limitations and their impact" |
|
], |
|
"quiz": [ |
|
{ |
|
"question": "What's the most important element of a good prompt?", |
|
"options": ["Length", "Specificity", "Complexity", "Creativity"], |
|
"answer": "Specificity", |
|
"explanation": "Specific prompts yield more accurate and relevant responses" |
|
} |
|
], |
|
"exercise_instructions": "Create a prompt that extracts key insights from a financial report..." |
|
} |
|
] |
|
} |
|
|
|
class SlideAgent: |
|
def generate_slides(self, content): |
|
if not openai_client: |
|
return self._mock_slides(content) |
|
|
|
try: |
|
response = openai_client.chat.completions.create( |
|
model="gpt-4-turbo", |
|
messages=[ |
|
{ |
|
"role": "system", |
|
"content": "You create professional slide decks in Markdown format using Marp syntax." |
|
}, |
|
{ |
|
"role": "user", |
|
"content": ( |
|
f"Create a slide deck for this workshop content: {json.dumps(content)}. " |
|
"Use Marp Markdown format with themes and visual elements. " |
|
"Include: title slide, module slides with key points, case studies, " |
|
"exercise instructions, and summary slides. Make it visually appealing." |
|
) |
|
} |
|
], |
|
temperature=0.2, |
|
max_tokens=2500 |
|
) |
|
return response.choices[0].message.content |
|
except Exception as e: |
|
st.error(f"Slide generation error: {str(e)}") |
|
return self._mock_slides(content) |
|
|
|
def _mock_slides(self, content): |
|
return f"""--- |
|
marp: true |
|
theme: gaia |
|
backgroundColor: #fff |
|
backgroundImage: url('https://marp.app/assets/hero-background.svg') |
|
--- |
|
|
|
# {content['workshop_title']} |
|
## Comprehensive Corporate Training Program |
|
|
|
--- |
|
|
|
## Module 1: Foundations of Prompt Engineering |
|
 |
|
|
|
- Core concepts and principles |
|
- Patterns and anti-patterns |
|
- Practical implementation techniques |
|
|
|
--- |
|
|
|
## Case Study |
|
### Anthropic's Customer Support Implementation |
|
- 40% faster resolution times |
|
- 25% reduction in training costs |
|
- 92% customer satisfaction |
|
|
|
--- |
|
|
|
## Exercises |
|
1. Craft effective prompts for different scenarios |
|
2. Optimize prompts for specific AI models |
|
3. Analyze and refine prompt performance |
|
|
|
""" |
|
|
|
class CodeAgent: |
|
def generate_code(self, content): |
|
if not openai_client: |
|
return self._mock_code(content) |
|
|
|
try: |
|
response = openai_client.chat.completions.create( |
|
model="gpt-4-turbo", |
|
messages=[ |
|
{ |
|
"role": "system", |
|
"content": "You create practical code labs for technical workshops." |
|
}, |
|
{ |
|
"role": "user", |
|
"content": ( |
|
f"Create a Jupyter notebook with code exercises for this workshop: {json.dumps(content)}. " |
|
"Include: setup instructions, practical exercises with solutions, " |
|
"and real-world implementation examples. Use Python with popular AI libraries." |
|
) |
|
} |
|
], |
|
temperature=0.3, |
|
max_tokens=2000 |
|
) |
|
return response.choices[0].message.content |
|
except Exception as e: |
|
st.error(f"Code generation error: {str(e)}") |
|
return self._mock_code(content) |
|
|
|
def _mock_code(self, content): |
|
return f"""# {content['workshop_title']} - Code Labs |
|
|
|
import openai |
|
import pandas as pd |
|
|
|
## Exercise 1: Basic Prompt Engineering |
|
def generate_response(prompt): |
|
response = openai.chat.completions.create( |
|
model="gpt-4", |
|
messages=[{{"role": "user", "content": prompt}}] |
|
) |
|
return response.choices[0].message.content |
|
|
|
# Test your function |
|
print(generate_response("Explain quantum computing in simple terms")) |
|
|
|
## Exercise 2: Advanced Prompt Patterns |
|
# TODO: Implement chain-of-thought prompting |
|
# TODO: Create meta-prompts for complex tasks |
|
|
|
## Real-World Implementation |
|
# TODO: Build a customer support question classifier |
|
""" |
|
|
|
class DesignAgent: |
|
def generate_design(self, slide_content): |
|
if not openai_client: |
|
return None |
|
|
|
try: |
|
response = openai_client.images.generate( |
|
prompt=f"Create a professional slide background for a corporate AI workshop about: {slide_content[:500]}", |
|
n=1, |
|
size="1024x1024" |
|
) |
|
return response.data[0].url |
|
except Exception as e: |
|
st.error(f"Design generation error: {str(e)}") |
|
return None |
|
|
|
class VoiceoverAgent: |
|
def __init__(self): |
|
self.api_key = ELEVENLABS_API_KEY |
|
self.voice_id = "21m00Tcm4TlvDq8ikWAM" |
|
self.model = "eleven_monolingual_v1" |
|
|
|
def generate_voiceover(self, text, voice_id=None): |
|
if not self.api_key: |
|
return None |
|
|
|
try: |
|
|
|
voice = voice_id if voice_id else self.voice_id |
|
|
|
url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice}" |
|
headers = { |
|
"Accept": "audio/mpeg", |
|
"Content-Type": "application/json", |
|
"xi-api-key": self.api_key |
|
} |
|
data = { |
|
"text": text, |
|
"model_id": self.model, |
|
"voice_settings": { |
|
"stability": 0.7, |
|
"similarity_boost": 0.8, |
|
"style": 0.5, |
|
"use_speaker_boost": True |
|
} |
|
} |
|
response = requests.post(url, json=data, headers=headers) |
|
|
|
if response.status_code == 200: |
|
return response.content |
|
else: |
|
st.error(f"Voiceover API error: {response.status_code} - {response.text}") |
|
return None |
|
except Exception as e: |
|
st.error(f"Voiceover generation error: {str(e)}") |
|
return None |
|
|
|
def get_voices(self): |
|
if not self.api_key: |
|
return [] |
|
|
|
try: |
|
url = "https://api.elevenlabs.io/v1/voices" |
|
headers = {"xi-api-key": self.api_key} |
|
response = requests.get(url, headers=headers) |
|
|
|
if response.status_code == 200: |
|
return response.json().get("voices", []) |
|
return [] |
|
except Exception as e: |
|
st.error(f"Voice loading error: {str(e)}") |
|
return [] |
|
|
|
|
|
topic_agent = TopicAgent() |
|
content_agent = ContentAgent() |
|
slide_agent = SlideAgent() |
|
code_agent = CodeAgent() |
|
design_agent = DesignAgent() |
|
voiceover_agent = VoiceoverAgent() |
|
|
|
|
|
|
|
|
|
|
|
st.set_page_config( |
|
page_title="Workshop in a Box Pro", |
|
layout="wide", |
|
initial_sidebar_state="expanded" |
|
) |
|
|
|
|
|
st.markdown(""" |
|
<style> |
|
.stApp { |
|
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%); |
|
color: #fff; |
|
} |
|
/* Fix for input text color */ |
|
.stTextInput>div>div>input { |
|
color: #333 !important; |
|
background-color: #fff !important; |
|
} |
|
.stSlider>div>div>div>div { |
|
background-color: rgba(255,255,255,0.1) !important; |
|
color: white !important; |
|
} |
|
.stButton>button { |
|
background: linear-gradient(to right, #00b09b, #96c93d) !important; |
|
color: white !important; |
|
border: none; |
|
border-radius: 30px; |
|
padding: 10px 25px; |
|
font-size: 16px; |
|
font-weight: bold; |
|
} |
|
.stDownloadButton>button { |
|
background: linear-gradient(to right, #ff5e62, #ff9966) !important; |
|
} |
|
.stExpander { |
|
background-color: rgba(0,0,0,0.2) !important; |
|
border-radius: 10px; |
|
padding: 15px; |
|
} |
|
.audio-player { |
|
margin: 15px 0; |
|
border-radius: 10px; |
|
background: rgba(255,255,255,0.1); |
|
padding: 15px; |
|
} |
|
.voice-option { |
|
display: flex; |
|
align-items: center; |
|
margin: 5px 0; |
|
padding: 8px; |
|
border-radius: 8px; |
|
cursor: pointer; |
|
transition: background 0.3s; |
|
} |
|
.voice-option:hover { |
|
background: rgba(255,255,255,0.2); |
|
} |
|
.voice-option.selected { |
|
background: rgba(0,180,155,0.3); |
|
border: 2px solid #00b09b; |
|
} |
|
.voice-thumb { |
|
width: 40px; |
|
height: 40px; |
|
border-radius: 50%; |
|
margin-right: 10px; |
|
object-fit: cover; |
|
} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
|
|
|
|
col1, col2 = st.columns([1, 3]) |
|
with col1: |
|
st.image("https://cdn-icons-png.flaticon.com/512/1995/1995485.png", width=100) |
|
with col2: |
|
st.title("π€ Workshop in a Box Pro") |
|
st.caption("Generate Premium Corporate AI Training Workshops with Voiceovers") |
|
|
|
|
|
if 'workshop_topic' not in st.session_state: |
|
st.session_state.workshop_topic = "Advanced Prompt Engineering" |
|
if 'generated' not in st.session_state: |
|
st.session_state.generated = False |
|
if 'generating' not in st.session_state: |
|
st.session_state.generating = False |
|
if 'voiceovers' not in st.session_state: |
|
st.session_state.voiceovers = {} |
|
if 'selected_voice' not in st.session_state: |
|
st.session_state.selected_voice = "21m00Tcm4TlvDq8ikWAM" |
|
|
|
|
|
with st.sidebar: |
|
st.header("βοΈ Workshop Configuration") |
|
|
|
|
|
st.session_state.workshop_topic = st.text_input( |
|
"Workshop Topic", |
|
st.session_state.workshop_topic, |
|
key="topic_input", |
|
help="Enter the main topic for your workshop" |
|
) |
|
|
|
|
|
if st.session_state.workshop_topic.strip() == "": |
|
st.warning("Please enter a workshop topic") |
|
st.stop() |
|
|
|
duration = st.slider("Duration (hours)", 1.0, 8.0, 3.0, 0.5) |
|
difficulty = st.selectbox("Difficulty Level", |
|
["Beginner", "Intermediate", "Advanced", "Expert"]) |
|
include_code = st.checkbox("Include Code Labs", True) |
|
include_design = st.checkbox("Generate Visual Designs", True) |
|
include_voiceover = st.checkbox("Generate Voiceovers", True) |
|
|
|
|
|
if include_voiceover: |
|
st.subheader("ποΈ Voice Selection") |
|
|
|
|
|
voices = voiceover_agent.get_voices() |
|
|
|
|
|
if voices: |
|
|
|
cols = st.columns(2) |
|
for i, voice in enumerate(voices[:4]): |
|
with cols[i % 2]: |
|
|
|
voice_key = f"voice_{voice['voice_id']}" |
|
|
|
|
|
if st.button( |
|
f"π£οΈ {voice['name']}", |
|
key=voice_key, |
|
use_container_width=True, |
|
help=f"Select {voice['name']} voice" |
|
): |
|
st.session_state.selected_voice = voice['voice_id'] |
|
|
|
|
|
selected_voice_name = next((v['name'] for v in voices if v['voice_id'] == st.session_state.selected_voice), "Default") |
|
st.info(f"Selected Voice: **{selected_voice_name}**") |
|
else: |
|
if ELEVENLABS_API_KEY: |
|
st.warning("Couldn't load voices. Using default voice.") |
|
else: |
|
st.warning("ElevenLabs API key not set. Voiceovers disabled.") |
|
|
|
if st.button("β¨ Generate Workshop", type="primary", use_container_width=True): |
|
st.session_state.generating = True |
|
st.session_state.voiceovers = {} |
|
|
|
|
|
if st.session_state.generating: |
|
with st.spinner(f"π Creating your {st.session_state.workshop_topic} workshop..."): |
|
start_time = time.time() |
|
|
|
|
|
outline = topic_agent.generate_outline(st.session_state.workshop_topic, duration, difficulty) |
|
content = content_agent.generate_content(outline) |
|
slides = slide_agent.generate_slides(content) |
|
code_labs = code_agent.generate_code(content) if include_code else None |
|
design_url = design_agent.generate_design(slides) if include_design else None |
|
|
|
|
|
voiceovers = {} |
|
if include_voiceover and ELEVENLABS_API_KEY: |
|
for i, module in enumerate(content.get("modules", [])): |
|
|
|
intro_text = f"Welcome to Module {i+1}: {module['title']}. " + \ |
|
f"In this module, we'll cover: {', '.join(module.get('speaker_notes', []))[:300]}" |
|
|
|
|
|
audio_data = voiceover_agent.generate_voiceover( |
|
intro_text, |
|
st.session_state.selected_voice |
|
) |
|
|
|
if audio_data: |
|
voiceovers[f"module_{i+1}_intro.mp3"] = audio_data |
|
|
|
|
|
zip_buffer = io.BytesIO() |
|
with zipfile.ZipFile(zip_buffer, "a") as zip_file: |
|
zip_file.writestr("outline.json", json.dumps(outline, indent=2)) |
|
zip_file.writestr("content.json", json.dumps(content, indent=2)) |
|
zip_file.writestr("slides.md", slides) |
|
if code_labs: |
|
zip_file.writestr("code_labs.ipynb", code_labs) |
|
if design_url: |
|
try: |
|
img_data = requests.get(design_url).content |
|
zip_file.writestr("slide_design.png", img_data) |
|
except: |
|
pass |
|
|
|
for filename, audio_data in voiceovers.items(): |
|
zip_file.writestr(f"voiceovers/{filename}", audio_data) |
|
|
|
|
|
st.session_state.outline = outline |
|
st.session_state.content = content |
|
st.session_state.slides = slides |
|
st.session_state.code_labs = code_labs |
|
st.session_state.design_url = design_url |
|
st.session_state.voiceovers = voiceovers |
|
st.session_state.zip_buffer = zip_buffer |
|
st.session_state.gen_time = round(time.time() - start_time, 2) |
|
st.session_state.generated = True |
|
st.session_state.generating = False |
|
|
|
|
|
if st.session_state.generated: |
|
st.success(f"β
{st.session_state.workshop_topic} workshop generated in {st.session_state.gen_time} seconds!") |
|
|
|
|
|
st.download_button( |
|
label="π₯ Download Workshop Package", |
|
data=st.session_state.zip_buffer.getvalue(), |
|
file_name=f"{st.session_state.workshop_topic.replace(' ', '_')}_workshop.zip", |
|
mime="application/zip", |
|
use_container_width=True |
|
) |
|
|
|
|
|
with st.expander("π Workshop Outline", expanded=True): |
|
st.json(st.session_state.outline) |
|
|
|
with st.expander("π Content Script"): |
|
st.write(st.session_state.content) |
|
|
|
with st.expander("π₯οΈ Slide Deck Preview"): |
|
st.markdown("```markdown\n" + textwrap.dedent(st.session_state.slides[:2000]) + "\n```") |
|
|
|
if st.session_state.code_labs: |
|
with st.expander("π» Code Labs"): |
|
st.code(st.session_state.code_labs) |
|
|
|
if st.session_state.design_url: |
|
with st.expander("π¨ Generated Design"): |
|
st.image(st.session_state.design_url, caption="Custom Slide Design") |
|
|
|
|
|
if st.session_state.voiceovers: |
|
with st.expander("π Voiceover Previews"): |
|
for i, (filename, audio_bytes) in enumerate(st.session_state.voiceovers.items()): |
|
module_num = filename.split("_")[1] |
|
st.subheader(f"Module {module_num} Introduction") |
|
|
|
|
|
st.audio(audio_bytes, format="audio/mp3") |
|
|
|
|
|
st.download_button( |
|
label=f"Download Module {module_num} Voiceover", |
|
data=audio_bytes, |
|
file_name=filename, |
|
mime="audio/mpeg", |
|
key=f"voiceover_dl_{i}" |
|
) |
|
elif include_voiceover and ELEVENLABS_API_KEY: |
|
st.warning("Voiceovers not generated. Check your ElevenLabs API key.") |
|
|
|
|
|
st.divider() |
|
st.subheader("π Ready to Deliver This Workshop?") |
|
st.markdown(f""" |
|
### Premium {st.session_state.workshop_topic} Training Package |
|
- **Live Workshop Delivery**: $10,000 per session |
|
- **On-Demand Course**: $5,000 (unlimited access) |
|
- **Pilot Program**: $1,000 refundable deposit |
|
- **Voiceover Add-on**: $500 per module |
|
|
|
β¨ **All inclusive**: Customization, materials, and follow-up support |
|
""") |
|
|
|
col1, col2 = st.columns(2) |
|
with col1: |
|
st.link_button("π
Book a Live Workshop", "https://calendly.com/your-link", |
|
use_container_width=True) |
|
with col2: |
|
st.link_button("π³ Purchase On-Demand Course", "https://your-store.com", |
|
use_container_width=True) |
|
|
|
|
|
with st.sidebar: |
|
st.divider() |
|
if openai_client: |
|
st.success("OpenAI API Connected") |
|
else: |
|
st.warning("OpenAI API not set - using enhanced mock data") |
|
|
|
if ELEVENLABS_API_KEY: |
|
st.success("ElevenLabs API Key Found") |
|
elif include_voiceover: |
|
st.warning("ElevenLabs API key not set") |
|
|
|
st.info(f""" |
|
**Current Workshop:** |
|
{st.session_state.workshop_topic} |
|
|
|
**Premium Features:** |
|
- AI-generated voiceovers |
|
- Professional slide designs |
|
- Real-world case studies |
|
- Practical code labs |
|
""") |
|
|
|
|
|
st.divider() |
|
st.subheader("π‘ How It Works") |
|
st.markdown(""" |
|
1. **Configure** your workshop topic and parameters |
|
2. **Generate** premium training materials with voiceovers |
|
3. **Customize** the content to your specific needs |
|
4. **Deliver** high-value corporate training at $10K/session |
|
5. **Reuse** the materials for unlimited revenue |
|
|
|
*"The voiceover feature helped me create on-demand courses that sold for $5K each"* - Michael L., AI Consultant |
|
""") |