mgbam commited on
Commit
b80eb6b
·
verified ·
1 Parent(s): 6a42c78

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +51 -100
app.py CHANGED
@@ -1,19 +1,14 @@
1
- ## 1. `app.py`
2
-
3
  import os
4
  import json
5
  import tempfile
6
  from zipfile import ZipFile
7
 
8
  import gradio as gr
9
- from agents import Agent, AgentRunner, handoff
10
  from agents.extensions.handoff_prompt import RECOMMENDED_PROMPT_PREFIX
11
-
12
- # === Coqui TTS Integration ===
13
  from TTS.api import TTS
14
 
15
- # Initialize Coqui TTS (choose a model)
16
- # Using Tacotron2-DDC model from LJSpeech
17
  tts = TTS(
18
  model_name="tts_models/en/ljspeech/tacotron2-DDC",
19
  progress_bar=False,
@@ -25,64 +20,41 @@ def generate_tts_audio(script: str) -> str:
25
  Synthesize speech using Coqui TTS and save to a WAV file.
26
  Returns the local file path to the audio.
27
  """
28
- # Determine output path in temp directory
29
  out_path = os.path.join(tempfile.gettempdir(), "voiceover.wav")
30
- # Render the speech to the file
31
  tts.tts_to_file(text=script, file_path=out_path)
32
  return out_path
33
 
34
- # --- Multi-Agent Scaffold ---
35
- # 1. Topic Agent
36
  topic_agent = Agent(
37
  name="Topic Agent",
38
- instructions=(
39
- f"{RECOMMENDED_PROMPT_PREFIX}\n"
40
- "You are given a workshop topic and audience. Draft a structured learning path: goals, 4 modules, and a hands-on exercise for each."
41
- )
42
  )
43
-
44
- # 2. Content Agent
45
  content_agent = Agent(
46
  name="Content Agent",
47
- instructions=(
48
- f"{RECOMMENDED_PROMPT_PREFIX}\n"
49
- "Convert the outline into detailed module scripts, speaker notes, and 3 quiz questions per module."
50
- )
51
  )
52
-
53
- # 3. Slide Agent
54
  slide_agent = Agent(
55
  name="Slide Agent",
56
- instructions=(
57
- f"{RECOMMENDED_PROMPT_PREFIX}\n"
58
- "Given module content, produce slide JSON with title, bullet points, and design hints."
59
- )
60
  )
61
-
62
- # 4. Code Agent
63
  code_agent = Agent(
64
  name="Code Agent",
65
- instructions=(
66
- f"{RECOMMENDED_PROMPT_PREFIX}\n"
67
- "Generate runnable Python code snippets or a Colab notebook for hands-on labs in each module."
68
- )
69
  )
70
-
71
- # 5. Voiceover Agent (Optional)
72
  voice_agent = Agent(
73
  name="Voiceover Agent",
74
- instructions=(
75
- f"{RECOMMENDED_PROMPT_PREFIX}\n"
76
- "Create a 1-2 minute voiceover script. Return JSON with key 'script'."
77
- )
78
  )
79
 
80
- # Orchestrator: sequences agents
81
  document_orchestrator = Agent(
82
  name="Workshop Orchestrator",
83
- instructions=(
84
- "Invoke: topic_agent, content_agent, slide_agent, code_agent, voice_agent (optional); collect outputs."
85
- ),
86
  handoffs=[
87
  handoff(topic_agent, name="outline"),
88
  handoff(content_agent, name="content"),
@@ -92,76 +64,55 @@ document_orchestrator = Agent(
92
  ]
93
  )
94
 
95
- runner = AgentRunner()
96
 
97
- # --- Helper: Run pipeline & bundle outputs ---
98
  def build_workshop_bundle(topic: str, audience: str):
99
  prompt = f"Create a {topic} workshop for {audience}."
100
  results = runner.run(document_orchestrator, prompt).outputs
101
 
102
- # Synthesize voiceover if script present
103
- voice_info = results.get('voiceover', {})
104
  audio_path = None
105
- if isinstance(voice_info, dict) and 'script' in voice_info:
106
- audio_path = generate_tts_audio(voice_info['script'])
107
 
108
- # Render slides to HTML
109
- slides_json = results.get('slides', {})
110
- with open('static/slides_template.html') as f:
111
  template = f.read()
112
- slide_html = template.replace('{{SLIDES_JSON}}', json.dumps(slides_json))
113
 
114
- # Create a ZIP bundle
115
  tmpdir = tempfile.mkdtemp()
116
- zip_path = os.path.join(tmpdir, 'workshop_bundle.zip')
117
- with ZipFile(zip_path, 'w') as zipf:
118
- # JSON outputs
119
- out_json = os.path.join(tmpdir, 'workshop_outputs.json')
120
- with open(out_json, 'w') as jf:
121
- jf.write(json.dumps(results, indent=2))
122
- zipf.write(out_json, 'workshop_outputs.json')
123
-
124
- # Slides JSON & HTML
125
- slide_json_file = os.path.join(tmpdir, 'slides.json')
126
- with open(slide_json_file, 'w') as sf:
127
- sf.write(json.dumps(slides_json, indent=2))
128
- zipf.write(slide_json_file, 'slides.json')
129
-
130
- slide_html_file = os.path.join(tmpdir, 'slides.html')
131
- with open(slide_html_file, 'w') as hf:
132
- hf.write(slide_html)
133
- zipf.write(slide_html_file, 'slides.html')
134
-
135
- # Code labs
136
- code_file = os.path.join(tmpdir, 'code_labs.py')
137
- with open(code_file, 'w') as cf:
138
- cf.write(results.get('code_labs', ''))
139
- zipf.write(code_file, 'code_labs.py')
140
-
141
- # Audio
142
  if audio_path and os.path.exists(audio_path):
143
  zipf.write(audio_path, os.path.basename(audio_path))
144
-
145
  return slide_html, audio_path, zip_path
146
 
147
- # --- Gradio UI ---
148
  def run_app(topic, audience):
149
- slide_html, audio_path, zip_path = build_workshop_bundle(topic, audience)
150
- return slide_html, audio_path, zip_path
151
-
152
- with gr.Blocks(title='🚀 Workshop in a Box') as demo:
153
- gr.Markdown('# Workshop in a Box')
154
- topic = gr.Textbox(label='Workshop Topic', placeholder='e.g., AI Agents 101')
155
- audience = gr.Textbox(label='Audience', placeholder='e.g., Product Managers')
156
- btn = gr.Button('Generate Workshop')
157
- slide_preview = gr.HTML(label='Slide Preview')
158
- audio_player = gr.Audio(label='Voiceover Preview', interactive=True)
159
- download = gr.File(label='Download ZIP')
160
- btn.click(
161
- fn=run_app,
162
- inputs=[topic, audience],
163
- outputs=[slide_preview, audio_player, download]
164
- )
165
-
166
- if __name__ == '__main__':
167
  demo.launch()
 
 
 
1
  import os
2
  import json
3
  import tempfile
4
  from zipfile import ZipFile
5
 
6
  import gradio as gr
7
+ from agents import Agent, handoff, Runner
8
  from agents.extensions.handoff_prompt import RECOMMENDED_PROMPT_PREFIX
 
 
9
  from TTS.api import TTS
10
 
11
+ # Initialize Coqui TTS (Tacotron2-DDC)
 
12
  tts = TTS(
13
  model_name="tts_models/en/ljspeech/tacotron2-DDC",
14
  progress_bar=False,
 
20
  Synthesize speech using Coqui TTS and save to a WAV file.
21
  Returns the local file path to the audio.
22
  """
 
23
  out_path = os.path.join(tempfile.gettempdir(), "voiceover.wav")
 
24
  tts.tts_to_file(text=script, file_path=out_path)
25
  return out_path
26
 
27
+ # Agents definitions
 
28
  topic_agent = Agent(
29
  name="Topic Agent",
30
+ instructions=f"{RECOMMENDED_PROMPT_PREFIX}\n"
31
+ "You are given a workshop topic and audience. Draft a structured learning path: goals, 4 modules, and a hands-on exercise for each."
 
 
32
  )
 
 
33
  content_agent = Agent(
34
  name="Content Agent",
35
+ instructions=f"{RECOMMENDED_PROMPT_PREFIX}\n"
36
+ "Convert the outline into detailed module scripts, speaker notes, and 3 quiz questions per module."
 
 
37
  )
 
 
38
  slide_agent = Agent(
39
  name="Slide Agent",
40
+ instructions=f"{RECOMMENDED_PROMPT_PREFIX}\n"
41
+ "Given module content, produce slide JSON with title, bullet points, and design hints."
 
 
42
  )
 
 
43
  code_agent = Agent(
44
  name="Code Agent",
45
+ instructions=f"{RECOMMENDED_PROMPT_PREFIX}\n"
46
+ "Generate runnable Python code snippets or a Colab notebook for hands-on labs in each module."
 
 
47
  )
 
 
48
  voice_agent = Agent(
49
  name="Voiceover Agent",
50
+ instructions=f"{RECOMMENDED_PROMPT_PREFIX}\n"
51
+ "Create a 1-2 minute voiceover script. Return JSON with key 'script'."
 
 
52
  )
53
 
54
+ # Orchestrator
55
  document_orchestrator = Agent(
56
  name="Workshop Orchestrator",
57
+ instructions="Invoke: topic_agent, content_agent, slide_agent, code_agent, voice_agent (optional); collect outputs.",
 
 
58
  handoffs=[
59
  handoff(topic_agent, name="outline"),
60
  handoff(content_agent, name="content"),
 
64
  ]
65
  )
66
 
67
+ runner = Runner()
68
 
 
69
  def build_workshop_bundle(topic: str, audience: str):
70
  prompt = f"Create a {topic} workshop for {audience}."
71
  results = runner.run(document_orchestrator, prompt).outputs
72
 
73
+ # Synthesize voiceover
74
+ voice_info = results.get("voiceover", {})
75
  audio_path = None
76
+ if isinstance(voice_info, dict) and "script" in voice_info:
77
+ audio_path = generate_tts_audio(voice_info["script"])
78
 
79
+ # Render slides
80
+ slides_json = results.get("slides", {})
81
+ with open("static/slides_template.html") as f:
82
  template = f.read()
83
+ slide_html = template.replace("{{SLIDES_JSON}}", json.dumps(slides_json))
84
 
85
+ # Bundle into ZIP
86
  tmpdir = tempfile.mkdtemp()
87
+ zip_path = os.path.join(tmpdir, "workshop_bundle.zip")
88
+ with ZipFile(zip_path, "w") as zipf:
89
+ for name, content in [
90
+ ("workshop_outputs.json", json.dumps(results, indent=2)),
91
+ ("slides.json", json.dumps(slides_json, indent=2)),
92
+ ("slides.html", slide_html),
93
+ ("code_labs.py", results.get("code_labs", "")),
94
+ ]:
95
+ p = os.path.join(tmpdir, name)
96
+ with open(p, "w") as file:
97
+ file.write(content)
98
+ zipf.write(p, arcname=name)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  if audio_path and os.path.exists(audio_path):
100
  zipf.write(audio_path, os.path.basename(audio_path))
 
101
  return slide_html, audio_path, zip_path
102
 
103
+ # Gradio UI
104
  def run_app(topic, audience):
105
+ return build_workshop_bundle(topic, audience)
106
+
107
+ with gr.Blocks(title="🚀 Workshop in a Box") as demo:
108
+ gr.Markdown("# Workshop in a Box")
109
+ topic = gr.Textbox(label="Workshop Topic", placeholder="e.g., AI Agents 101")
110
+ audience = gr.Textbox(label="Audience", placeholder="e.g., Product Managers")
111
+ btn = gr.Button("Generate Workshop")
112
+ slide_preview = gr.HTML(label="Slide Preview")
113
+ audio_player = gr.Audio(label="Voiceover Preview", interactive=True)
114
+ download = gr.File(label="Download ZIP")
115
+ btn.click(fn=run_app, inputs=[topic, audience], outputs=[slide_preview, audio_player, download])
116
+
117
+ if __name__ == "__main__":
 
 
 
 
 
118
  demo.launch()