mgbam commited on
Commit
7154b6b
·
verified ·
1 Parent(s): c06d5ff

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -395
app.py CHANGED
@@ -10,6 +10,7 @@ import base64
10
  import textwrap
11
  from dotenv import load_dotenv
12
  from openai import OpenAI # Updated OpenAI client
 
13
 
14
  # Load environment variables
15
  load_dotenv()
@@ -18,6 +19,8 @@ load_dotenv()
18
  openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) if os.getenv("OPENAI_API_KEY") else None
19
  ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
20
 
 
 
21
  # =============================
22
  # UPDATED AGENT IMPLEMENTATION (OpenAI v1.x compatible)
23
  # =============================
@@ -26,25 +29,18 @@ class TopicAgent:
26
  def generate_outline(self, topic, duration, difficulty):
27
  if not openai_client:
28
  return self._mock_outline(topic, duration, difficulty)
29
-
30
  try:
31
  response = openai_client.chat.completions.create(
32
  model="gpt-4-turbo",
33
  messages=[
34
- {
35
- "role": "system",
36
- "content": "You're an expert corporate trainer creating comprehensive AI workshop outlines."
37
- },
38
- {
39
- "role": "user",
40
- "content": (
41
- f"Create a detailed {duration}-hour {difficulty} workshop outline on {topic}. "
42
- "Include: 4-6 modules with specific learning objectives, hands-on exercises, "
43
- "and real-world case studies. Format as JSON with keys: "
44
- "{'topic', 'duration', 'difficulty', 'goals', 'modules': ["
45
- "{'title', 'duration', 'learning_objectives', 'case_study', 'exercises'}]}"
46
- )
47
- }
48
  ],
49
  temperature=0.3,
50
  max_tokens=1500,
@@ -52,9 +48,9 @@ class TopicAgent:
52
  )
53
  return json.loads(response.choices[0].message.content)
54
  except Exception as e:
55
- st.error(f"Outline generation error: {str(e)}")
56
  return self._mock_outline(topic, duration, difficulty)
57
-
58
  def _mock_outline(self, topic, duration, difficulty):
59
  return {
60
  "topic": topic,
@@ -102,25 +98,18 @@ class ContentAgent:
102
  def generate_content(self, outline):
103
  if not openai_client:
104
  return self._mock_content(outline)
105
-
106
  try:
107
  response = openai_client.chat.completions.create(
108
  model="gpt-4-turbo",
109
  messages=[
110
- {
111
- "role": "system",
112
- "content": "You're a corporate training content developer creating detailed workshop materials."
113
- },
114
- {
115
- "role": "user",
116
- "content": (
117
- f"Expand this workshop outline into comprehensive content: {json.dumps(outline)}. "
118
- "For each module, include: detailed script (3-5 paragraphs), speaker notes (bullet points), "
119
- "3 quiz questions with explanations, and exercise instructions. Format as JSON with keys: "
120
- "{'workshop_title', 'modules': [{'title', 'script', 'speaker_notes', 'quiz': ["
121
- "{'question', 'options', 'answer', 'explanation'}], 'exercise_instructions'}]}"
122
- )
123
- }
124
  ],
125
  temperature=0.4,
126
  max_tokens=2000,
@@ -128,9 +117,9 @@ class ContentAgent:
128
  )
129
  return json.loads(response.choices[0].message.content)
130
  except Exception as e:
131
- st.error(f"Content generation error: {str(e)}")
132
  return self._mock_content(outline)
133
-
134
  def _mock_content(self, outline):
135
  return {
136
  "workshop_title": f"Mastering {outline['topic']}",
@@ -144,12 +133,10 @@ class ContentAgent:
144
  "Discuss token limitations and their impact"
145
  ],
146
  "quiz": [
147
- {
148
- "question": "What's the most important element of a good prompt?",
149
- "options": ["Length", "Specificity", "Complexity", "Creativity"],
150
- "answer": "Specificity",
151
- "explanation": "Specific prompts yield more accurate and relevant responses"
152
- }
153
  ],
154
  "exercise_instructions": "Create a prompt that extracts key insights from a financial report..."
155
  }
@@ -160,33 +147,26 @@ class SlideAgent:
160
  def generate_slides(self, content):
161
  if not openai_client:
162
  return self._mock_slides(content)
163
-
164
  try:
165
  response = openai_client.chat.completions.create(
166
  model="gpt-4-turbo",
167
  messages=[
168
- {
169
- "role": "system",
170
- "content": "You create professional slide decks in Markdown format using Marp syntax."
171
- },
172
- {
173
- "role": "user",
174
- "content": (
175
- f"Create a slide deck for this workshop content: {json.dumps(content)}. "
176
- "Use Marp Markdown format with themes and visual elements. "
177
- "Include: title slide, module slides with key points, case studies, "
178
- "exercise instructions, and summary slides. Make it visually appealing."
179
- )
180
- }
181
  ],
182
  temperature=0.2,
183
  max_tokens=2500
184
  )
185
  return response.choices[0].message.content
186
  except Exception as e:
187
- st.error(f"Slide generation error: {str(e)}")
188
  return self._mock_slides(content)
189
-
190
  def _mock_slides(self, content):
191
  return f"""---
192
  marp: true
@@ -221,41 +201,34 @@ backgroundImage: url('https://marp.app/assets/hero-background.svg')
221
  1. Craft effective prompts for different scenarios
222
  2. Optimize prompts for specific AI models
223
  3. Analyze and refine prompt performance
224
-
225
  """
226
 
227
  class CodeAgent:
228
  def generate_code(self, content):
229
  if not openai_client:
230
  return self._mock_code(content)
231
-
232
  try:
233
  response = openai_client.chat.completions.create(
234
  model="gpt-4-turbo",
235
  messages=[
236
- {
237
- "role": "system",
238
- "content": "You create practical code labs for technical workshops."
239
- },
240
- {
241
- "role": "user",
242
- "content": (
243
- f"Create a Jupyter notebook with code exercises for this workshop: {json.dumps(content)}. "
244
- "Include: setup instructions, practical exercises with solutions, "
245
- "and real-world implementation examples. Use Python with popular AI libraries."
246
- )
247
- }
248
  ],
249
  temperature=0.3,
250
  max_tokens=2000
251
  )
252
  return response.choices[0].message.content
253
  except Exception as e:
254
- st.error(f"Code generation error: {str(e)}")
255
  return self._mock_code(content)
256
-
257
  def _mock_code(self, content):
258
- return f"""# {content['workshop_title']} - Code Labs
 
259
 
260
  import openai
261
  import pandas as pd
@@ -264,11 +237,10 @@ import pandas as pd
264
  def generate_response(prompt):
265
  response = openai.chat.completions.create(
266
  model="gpt-4",
267
- messages=[{{"role": "user", "content": prompt}}]
268
  )
269
  return response.choices[0].message.content
270
 
271
- # Test your function
272
  print(generate_response("Explain quantum computing in simple terms"))
273
 
274
  ## Exercise 2: Advanced Prompt Patterns
@@ -283,7 +255,6 @@ class DesignAgent:
283
  def generate_design(self, slide_content):
284
  if not openai_client:
285
  return None
286
-
287
  try:
288
  response = openai_client.images.generate(
289
  prompt=f"Create a professional slide background for a corporate AI workshop about: {slide_content[:500]}",
@@ -292,65 +263,45 @@ class DesignAgent:
292
  )
293
  return response.data[0].url
294
  except Exception as e:
295
- st.error(f"Design generation error: {str(e)}")
296
  return None
297
 
298
  class VoiceoverAgent:
299
  def __init__(self):
300
- self.api_key = ELEVENLABS_API_KEY
301
- self.voice_id = "9BWtsMINqrJLrRacOk9x" # Default voice ID
302
- self.model = "eleven_monolingual_v1"
303
-
 
 
 
 
 
 
 
 
 
 
304
  def generate_voiceover(self, text, voice_id=None):
305
- if not self.api_key:
306
  return None
307
-
308
  try:
309
- # Use custom voice if provided, otherwise use default
310
- voice = voice_id if voice_id else self.voice_id
311
-
312
- url = f"https://api.elevenlabs.io/v1/text-to-speech/{voice}"
313
- headers = {
314
- "Accept": "audio/mpeg",
315
- "Content-Type": "application/json",
316
- "xi-api-key": self.api_key
317
- }
318
- data = {
319
- "text": text,
320
- "model_id": self.model,
321
- "voice_settings": {
322
  "stability": 0.7,
323
  "similarity_boost": 0.8,
324
  "style": 0.5,
325
  "use_speaker_boost": True
326
  }
327
- }
328
- response = requests.post(url, json=data, headers=headers)
329
-
330
- if response.status_code == 200:
331
- return response.content
332
- else:
333
- st.error(f"Voiceover API error: {response.status_code} - {response.text}")
334
- return None
335
  except Exception as e:
336
- st.error(f"Voiceover generation error: {str(e)}")
337
  return None
338
-
339
- def get_voices(self):
340
- if not self.api_key:
341
- return []
342
-
343
- try:
344
- url = "https://api.elevenlabs.io/v1/voices"
345
- headers = {"xi-api-key": self.api_key}
346
- response = requests.get(url, headers=headers)
347
-
348
- if response.status_code == 200:
349
- return response.json().get("voices", [])
350
- return []
351
- except Exception as e:
352
- st.error(f"Voice loading error: {str(e)}")
353
- return []
354
 
355
  # Initialize agents
356
  topic_agent = TopicAgent()
@@ -370,14 +321,13 @@ st.set_page_config(
370
  initial_sidebar_state="expanded"
371
  )
372
 
373
- # Custom CSS with fixed input styling
374
  st.markdown("""
375
  <style>
376
  .stApp {
377
  background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
378
  color: #fff;
379
  }
380
- /* Fix for input text color */
381
  .stTextInput>div>div>input {
382
  color: #333 !important;
383
  background-color: #fff !important;
@@ -413,275 +363,4 @@ st.markdown("""
413
  display: flex;
414
  align-items: center;
415
  margin: 5px 0;
416
- padding: 8px;
417
- border-radius: 8px;
418
- cursor: pointer;
419
- transition: background 0.3s;
420
- }
421
- .voice-option:hover {
422
- background: rgba(255,255,255,0.2);
423
- }
424
- .voice-option.selected {
425
- background: rgba(0,180,155,0.3);
426
- border: 2px solid #00b09b;
427
- }
428
- .voice-thumb {
429
- width: 40px;
430
- height: 40px;
431
- border-radius: 50%;
432
- margin-right: 10px;
433
- object-fit: cover;
434
- }
435
- </style>
436
- """, unsafe_allow_html=True)
437
-
438
- # Header
439
- col1, col2 = st.columns([1, 3])
440
- with col1:
441
- st.image("https://cdn-icons-png.flaticon.com/512/1995/1995485.png", width=100)
442
- with col2:
443
- st.title("🤖 Workshop in a Box Pro")
444
- st.caption("Generate Premium Corporate AI Training Workshops with Voiceovers")
445
-
446
- # Initialize session state
447
- if 'workshop_topic' not in st.session_state:
448
- st.session_state.workshop_topic = "Advanced Prompt Engineering"
449
- if 'generated' not in st.session_state:
450
- st.session_state.generated = False
451
- if 'generating' not in st.session_state:
452
- st.session_state.generating = False
453
- if 'voiceovers' not in st.session_state:
454
- st.session_state.voiceovers = {}
455
- if 'selected_voice' not in st.session_state:
456
- st.session_state.selected_voice = "21m00Tcm4TlvDq8ikWAM" # Default voice ID
457
-
458
- # Sidebar configuration
459
- with st.sidebar:
460
- st.header("⚙️ Workshop Configuration")
461
-
462
- # Workshop topic input with session state
463
- st.session_state.workshop_topic = st.text_input(
464
- "Workshop Topic",
465
- st.session_state.workshop_topic,
466
- key="topic_input",
467
- help="Enter the main topic for your workshop"
468
- )
469
-
470
- # Validate topic input
471
- if st.session_state.workshop_topic.strip() == "":
472
- st.warning("Please enter a workshop topic")
473
- st.stop()
474
-
475
- duration = st.slider("Duration (hours)", 1.0, 8.0, 3.0, 0.5)
476
- difficulty = st.selectbox("Difficulty Level",
477
- ["Beginner", "Intermediate", "Advanced", "Expert"])
478
- include_code = st.checkbox("Include Code Labs", True)
479
- include_design = st.checkbox("Generate Visual Designs", True)
480
- include_voiceover = st.checkbox("Generate Voiceovers", True)
481
-
482
- # Voice selection
483
- if include_voiceover:
484
- st.subheader("🎙️ Voice Selection")
485
-
486
- # Get available voices
487
- voices = voiceover_agent.get_voices()
488
-
489
- # If we have voices, let the user select one
490
- if voices:
491
- # Create 2 columns for voice selection
492
- cols = st.columns(2)
493
- for i, voice in enumerate(voices[:4]): # Show first 4 voices
494
- with cols[i % 2]:
495
- # Create a unique key for each voice button
496
- voice_key = f"voice_{voice['voice_id']}"
497
-
498
- # Display voice option
499
- if st.button(
500
- f"🗣️ {voice['name']}",
501
- key=voice_key,
502
- use_container_width=True,
503
- help=f"Select {voice['name']} voice"
504
- ):
505
- st.session_state.selected_voice = voice['voice_id']
506
-
507
- # Show which voice is currently selected
508
- selected_voice_name = next((v['name'] for v in voices if v['voice_id'] == st.session_state.selected_voice), "Default")
509
- st.info(f"Selected Voice: **{selected_voice_name}**")
510
- else:
511
- if ELEVENLABS_API_KEY:
512
- st.warning("Couldn't load voices. Using default voice.")
513
- else:
514
- st.warning("ElevenLabs API key not set. Voiceovers disabled.")
515
-
516
- if st.button("✨ Generate Workshop", type="primary", use_container_width=True):
517
- st.session_state.generating = True
518
- st.session_state.voiceovers = {} # Reset previous voiceovers
519
-
520
- # Generation pipeline
521
- if st.session_state.generating:
522
- with st.spinner(f"🚀 Creating your {st.session_state.workshop_topic} workshop..."):
523
- start_time = time.time()
524
-
525
- # Agent pipeline
526
- outline = topic_agent.generate_outline(st.session_state.workshop_topic, duration, difficulty)
527
- content = content_agent.generate_content(outline)
528
- slides = slide_agent.generate_slides(content)
529
- code_labs = code_agent.generate_code(content) if include_code else None
530
- design_url = design_agent.generate_design(slides) if include_design else None
531
-
532
- # Generate voiceovers if enabled
533
- voiceovers = {}
534
- if include_voiceover and ELEVENLABS_API_KEY:
535
- for i, module in enumerate(content.get("modules", [])):
536
- # Create a short intro for each module
537
- intro_text = f"Welcome to Module {i+1}: {module['title']}. " + \
538
- f"In this module, we'll cover: {', '.join(module.get('speaker_notes', []))[:300]}"
539
-
540
- # Generate voiceover
541
- audio_data = voiceover_agent.generate_voiceover(
542
- intro_text,
543
- st.session_state.selected_voice
544
- )
545
-
546
- if audio_data:
547
- voiceovers[f"module_{i+1}_intro.mp3"] = audio_data
548
-
549
- # Prepare download package
550
- zip_buffer = io.BytesIO()
551
- with zipfile.ZipFile(zip_buffer, "a") as zip_file:
552
- zip_file.writestr("outline.json", json.dumps(outline, indent=2))
553
- zip_file.writestr("content.json", json.dumps(content, indent=2))
554
- zip_file.writestr("slides.md", slides)
555
- if code_labs:
556
- zip_file.writestr("code_labs.ipynb", code_labs)
557
- if design_url:
558
- try:
559
- img_data = requests.get(design_url).content
560
- zip_file.writestr("slide_design.png", img_data)
561
- except:
562
- pass
563
- # Add voiceovers to ZIP
564
- for filename, audio_data in voiceovers.items():
565
- zip_file.writestr(f"voiceovers/{filename}", audio_data)
566
-
567
- # Store results
568
- st.session_state.outline = outline
569
- st.session_state.content = content
570
- st.session_state.slides = slides
571
- st.session_state.code_labs = code_labs
572
- st.session_state.design_url = design_url
573
- st.session_state.voiceovers = voiceovers
574
- st.session_state.zip_buffer = zip_buffer
575
- st.session_state.gen_time = round(time.time() - start_time, 2)
576
- st.session_state.generated = True
577
- st.session_state.generating = False
578
-
579
- # Results display
580
- if st.session_state.generated:
581
- st.success(f"✅ {st.session_state.workshop_topic} workshop generated in {st.session_state.gen_time} seconds!")
582
-
583
- # Download button
584
- st.download_button(
585
- label="📥 Download Workshop Package",
586
- data=st.session_state.zip_buffer.getvalue(),
587
- file_name=f"{st.session_state.workshop_topic.replace(' ', '_')}_workshop.zip",
588
- mime="application/zip",
589
- use_container_width=True
590
- )
591
-
592
- # Preview sections
593
- with st.expander("📝 Workshop Outline", expanded=True):
594
- st.json(st.session_state.outline)
595
-
596
- with st.expander("📄 Content Script"):
597
- st.write(st.session_state.content)
598
-
599
- with st.expander("🖥️ Slide Deck Preview"):
600
- st.markdown("```markdown\n" + textwrap.dedent(st.session_state.slides[:2000]) + "\n```")
601
-
602
- if st.session_state.code_labs:
603
- with st.expander("💻 Code Labs"):
604
- st.code(st.session_state.code_labs)
605
-
606
- if st.session_state.design_url:
607
- with st.expander("🎨 Generated Design"):
608
- st.image(st.session_state.design_url, caption="Custom Slide Design")
609
-
610
- # Voiceover player
611
- if st.session_state.voiceovers:
612
- with st.expander("🔊 Voiceover Previews"):
613
- for i, (filename, audio_bytes) in enumerate(st.session_state.voiceovers.items()):
614
- module_num = filename.split("_")[1]
615
- st.subheader(f"Module {module_num} Introduction")
616
-
617
- # Create an audio player for each voiceover
618
- st.audio(audio_bytes, format="audio/mp3")
619
-
620
- # Add download button for individual voiceover
621
- st.download_button(
622
- label=f"Download Module {module_num} Voiceover",
623
- data=audio_bytes,
624
- file_name=filename,
625
- mime="audio/mpeg",
626
- key=f"voiceover_dl_{i}"
627
- )
628
- elif include_voiceover and ELEVENLABS_API_KEY:
629
- st.warning("Voiceovers not generated. Check your ElevenLabs API key.")
630
-
631
- # Sales and booking section
632
- st.divider()
633
- st.subheader("🚀 Ready to Deliver This Workshop?")
634
- st.markdown(f"""
635
- ### Premium {st.session_state.workshop_topic} Training Package
636
- - **Live Workshop Delivery**: $10,000 per session
637
- - **On-Demand Course**: $5,000 (unlimited access)
638
- - **Pilot Program**: $1,000 refundable deposit
639
- - **Voiceover Add-on**: $500 per module
640
-
641
- ✨ **All inclusive**: Customization, materials, and follow-up support
642
- """)
643
-
644
- col1, col2 = st.columns(2)
645
- with col1:
646
- st.link_button("📅 Book a Live Workshop", "https://calendly.com/your-link",
647
- use_container_width=True)
648
- with col2:
649
- st.link_button("💳 Purchase On-Demand Course", "https://your-store.com",
650
- use_container_width=True)
651
-
652
- # Debug info
653
- with st.sidebar:
654
- st.divider()
655
- if openai_client:
656
- st.success("OpenAI API Connected")
657
- else:
658
- st.warning("OpenAI API not set - using enhanced mock data")
659
-
660
- if ELEVENLABS_API_KEY:
661
- st.success("ElevenLabs API Key Found")
662
- elif include_voiceover:
663
- st.warning("ElevenLabs API key not set")
664
-
665
- st.info(f"""
666
- **Current Workshop:**
667
- {st.session_state.workshop_topic}
668
-
669
- **Premium Features:**
670
- - AI-generated voiceovers
671
- - Professional slide designs
672
- - Real-world case studies
673
- - Practical code labs
674
- """)
675
-
676
- # How it works section
677
- st.divider()
678
- st.subheader("💡 How It Works")
679
- st.markdown("""
680
- 1. **Configure** your workshop topic and parameters
681
- 2. **Generate** premium training materials with voiceovers
682
- 3. **Customize** the content to your specific needs
683
- 4. **Deliver** high-value corporate training at $10K/session
684
- 5. **Reuse** the materials for unlimited revenue
685
-
686
- *"The voiceover feature helped me create on-demand courses that sold for $5K each"* - Michael L., AI Consultant
687
- """)
 
10
  import textwrap
11
  from dotenv import load_dotenv
12
  from openai import OpenAI # Updated OpenAI client
13
+ from elevenlabs import ElevenLabs # Official ElevenLabs SDK import
14
 
15
  # Load environment variables
16
  load_dotenv()
 
19
  openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) if os.getenv("OPENAI_API_KEY") else None
20
  ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
21
 
22
+ eleven_client = ElevenLabs(api_key=ELEVENLABS_API_KEY) if ELEVENLABS_API_KEY else None
23
+
24
  # =============================
25
  # UPDATED AGENT IMPLEMENTATION (OpenAI v1.x compatible)
26
  # =============================
 
29
  def generate_outline(self, topic, duration, difficulty):
30
  if not openai_client:
31
  return self._mock_outline(topic, duration, difficulty)
 
32
  try:
33
  response = openai_client.chat.completions.create(
34
  model="gpt-4-turbo",
35
  messages=[
36
+ {"role": "system", "content": "You're an expert corporate trainer creating comprehensive AI workshop outlines."},
37
+ {"role": "user", "content": (
38
+ f"Create a detailed {duration}-hour {difficulty} workshop outline on {topic}. "
39
+ "Include: 4-6 modules with specific learning objectives, hands-on exercises, "
40
+ "and real-world case studies. Format as JSON with keys: "
41
+ "{'topic', 'duration', 'difficulty', 'goals', 'modules': ["
42
+ "{'title', 'duration', 'learning_objectives', 'case_study', 'exercises'}]}"
43
+ )}
 
 
 
 
 
 
44
  ],
45
  temperature=0.3,
46
  max_tokens=1500,
 
48
  )
49
  return json.loads(response.choices[0].message.content)
50
  except Exception as e:
51
+ st.error(f"Outline generation error: {e}")
52
  return self._mock_outline(topic, duration, difficulty)
53
+
54
  def _mock_outline(self, topic, duration, difficulty):
55
  return {
56
  "topic": topic,
 
98
  def generate_content(self, outline):
99
  if not openai_client:
100
  return self._mock_content(outline)
 
101
  try:
102
  response = openai_client.chat.completions.create(
103
  model="gpt-4-turbo",
104
  messages=[
105
+ {"role": "system", "content": "You're a corporate training content developer creating detailed workshop materials."},
106
+ {"role": "user", "content": (
107
+ f"Expand this workshop outline into comprehensive content: {json.dumps(outline)}. "
108
+ "For each module, include: detailed script (3-5 paragraphs), speaker notes (bullet points), "
109
+ "3 quiz questions with explanations, and exercise instructions. Format as JSON with keys: "
110
+ "{'workshop_title', 'modules': [{'title', 'script', 'speaker_notes', 'quiz': ["
111
+ "{'question', 'options', 'answer', 'explanation'}], 'exercise_instructions'}]}"
112
+ )}
 
 
 
 
 
 
113
  ],
114
  temperature=0.4,
115
  max_tokens=2000,
 
117
  )
118
  return json.loads(response.choices[0].message.content)
119
  except Exception as e:
120
+ st.error(f"Content generation error: {e}")
121
  return self._mock_content(outline)
122
+
123
  def _mock_content(self, outline):
124
  return {
125
  "workshop_title": f"Mastering {outline['topic']}",
 
133
  "Discuss token limitations and their impact"
134
  ],
135
  "quiz": [
136
+ {"question": "What's the most important element of a good prompt?",
137
+ "options": ["Length", "Specificity", "Complexity", "Creativity"],
138
+ "answer": "Specificity",
139
+ "explanation": "Specific prompts yield more accurate and relevant responses"}
 
 
140
  ],
141
  "exercise_instructions": "Create a prompt that extracts key insights from a financial report..."
142
  }
 
147
  def generate_slides(self, content):
148
  if not openai_client:
149
  return self._mock_slides(content)
 
150
  try:
151
  response = openai_client.chat.completions.create(
152
  model="gpt-4-turbo",
153
  messages=[
154
+ {"role": "system", "content": "You create professional slide decks in Markdown format using Marp syntax."},
155
+ {"role": "user", "content": (
156
+ f"Create a slide deck for this workshop content: {json.dumps(content)}. "
157
+ "Use Marp Markdown format with themes and visual elements. "
158
+ "Include: title slide, module slides with key points, case studies, "
159
+ "exercise instructions, and summary slides. Make it visually appealing."
160
+ )}
 
 
 
 
 
 
161
  ],
162
  temperature=0.2,
163
  max_tokens=2500
164
  )
165
  return response.choices[0].message.content
166
  except Exception as e:
167
+ st.error(f"Slide generation error: {e}")
168
  return self._mock_slides(content)
169
+
170
  def _mock_slides(self, content):
171
  return f"""---
172
  marp: true
 
201
  1. Craft effective prompts for different scenarios
202
  2. Optimize prompts for specific AI models
203
  3. Analyze and refine prompt performance
 
204
  """
205
 
206
  class CodeAgent:
207
  def generate_code(self, content):
208
  if not openai_client:
209
  return self._mock_code(content)
 
210
  try:
211
  response = openai_client.chat.completions.create(
212
  model="gpt-4-turbo",
213
  messages=[
214
+ {"role": "system", "content": "You create practical code labs for technical workshops."},
215
+ {"role": "user", "content": (
216
+ f"Create a Jupyter notebook with code exercises for this workshop: {json.dumps(content)}. "
217
+ "Include: setup instructions, practical exercises with solutions, "
218
+ "and real-world implementation examples. Use Python with popular AI libraries."
219
+ )}
 
 
 
 
 
 
220
  ],
221
  temperature=0.3,
222
  max_tokens=2000
223
  )
224
  return response.choices[0].message.content
225
  except Exception as e:
226
+ st.error(f"Code generation error: {e}")
227
  return self._mock_code(content)
228
+
229
  def _mock_code(self, content):
230
+ return f"""
231
+ # {content['workshop_title']} - Code Labs
232
 
233
  import openai
234
  import pandas as pd
 
237
  def generate_response(prompt):
238
  response = openai.chat.completions.create(
239
  model="gpt-4",
240
+ messages=[{"role": "user", "content": prompt}]
241
  )
242
  return response.choices[0].message.content
243
 
 
244
  print(generate_response("Explain quantum computing in simple terms"))
245
 
246
  ## Exercise 2: Advanced Prompt Patterns
 
255
  def generate_design(self, slide_content):
256
  if not openai_client:
257
  return None
 
258
  try:
259
  response = openai_client.images.generate(
260
  prompt=f"Create a professional slide background for a corporate AI workshop about: {slide_content[:500]}",
 
263
  )
264
  return response.data[0].url
265
  except Exception as e:
266
+ st.error(f"Design generation error: {e}")
267
  return None
268
 
269
  class VoiceoverAgent:
270
  def __init__(self):
271
+ self.client = eleven_client
272
+ self.default_voice_id = "9BWtsMINqrJLrRacOk9x" # Default fallback voice
273
+ self.model_id = "eleven_monolingual_v1"
274
+
275
+ def get_voices(self):
276
+ if not self.client:
277
+ return []
278
+ try:
279
+ voices = self.client.voices.list()
280
+ return [{"voice_id": v.voice_id, "name": v.name} for v in voices]
281
+ except Exception as e:
282
+ st.error(f"Voice loading error: {e}")
283
+ return []
284
+
285
  def generate_voiceover(self, text, voice_id=None):
286
+ if not self.client:
287
  return None
 
288
  try:
289
+ vid = voice_id or self.default_voice_id
290
+ audio = self.client.text_to_speech.convert(
291
+ text=text,
292
+ voice_id=vid,
293
+ model_id=self.model_id,
294
+ voice_settings={
 
 
 
 
 
 
 
295
  "stability": 0.7,
296
  "similarity_boost": 0.8,
297
  "style": 0.5,
298
  "use_speaker_boost": True
299
  }
300
+ )
301
+ return audio
 
 
 
 
 
 
302
  except Exception as e:
303
+ st.error(f"Voiceover generation error: {e}")
304
  return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
 
306
  # Initialize agents
307
  topic_agent = TopicAgent()
 
321
  initial_sidebar_state="expanded"
322
  )
323
 
324
+ # Custom CSS
325
  st.markdown("""
326
  <style>
327
  .stApp {
328
  background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
329
  color: #fff;
330
  }
 
331
  .stTextInput>div>div>input {
332
  color: #333 !important;
333
  background-color: #fff !important;
 
363
  display: flex;
364
  align-items: center;
365
  margin: 5px 0;
366
+ padding