mgbam commited on
Commit
07976be
·
verified ·
1 Parent(s): 7c66036

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -35
app.py CHANGED
@@ -1,6 +1,5 @@
1
- ## 1. `app.py`
2
- ```python
3
- # app.py: Workshop-in-a-Box Hugging Face Space with TTS and Slide Previews
4
  import os
5
  import json
6
  import tempfile
@@ -10,8 +9,24 @@ import gradio as gr
10
  from agents import Agent, AgentRunner, handoff
11
  from agents.extensions.handoff_prompt import RECOMMENDED_PROMPT_PREFIX
12
 
13
- # Import your TTS/voice API module
14
- from your_tts_module import generate_tts_audio # implement to return path to .mp3/.wav
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
  # --- Multi-Agent Scaffold ---
17
  # 1. Topic Agent
@@ -55,7 +70,7 @@ voice_agent = Agent(
55
  name="Voiceover Agent",
56
  instructions=(
57
  f"{RECOMMENDED_PROMPT_PREFIX}\n"
58
- "Create a 1-2 minute voiceover script. Return JSON with keys 'script' and optionally 'audio_url'."
59
  )
60
  )
61
 
@@ -63,7 +78,7 @@ voice_agent = Agent(
63
  document_orchestrator = Agent(
64
  name="Workshop Orchestrator",
65
  instructions=(
66
- "Invoke sub-agents: topic_agent, content_agent, slide_agent, code_agent, voice_agent (optional); collect outputs."
67
  ),
68
  handoffs=[
69
  handoff(topic_agent, name="outline"),
@@ -76,15 +91,15 @@ document_orchestrator = Agent(
76
 
77
  runner = AgentRunner()
78
 
79
- # --- Helper: Run pipeline and create outputs ---
80
  def build_workshop_bundle(topic: str, audience: str):
81
  prompt = f"Create a {topic} workshop for {audience}."
82
  results = runner.run(document_orchestrator, prompt).outputs
83
 
84
- # TTS audio
85
  voice_info = results.get('voiceover', {})
86
  audio_path = None
87
- if 'script' in voice_info:
88
  audio_path = generate_tts_audio(voice_info['script'])
89
 
90
  # Render slides to HTML
@@ -93,37 +108,56 @@ def build_workshop_bundle(topic: str, audience: str):
93
  template = f.read()
94
  slide_html = template.replace('{{SLIDES_JSON}}', json.dumps(slides_json))
95
 
96
- # Create ZIP
97
- tmp = tempfile.mkdtemp()
98
- zipf_path = os.path.join(tmp, 'workshop_bundle.zip')
99
- with ZipFile(zipf_path, 'w') as z:
100
- for name, data in [
101
- ('workshop_outputs.json', json.dumps(results, indent=2)),
102
- ('slides.json', json.dumps(slides_json, indent=2)),
103
- ('slides.html', slide_html),
104
- ('code_labs.py', results.get('code_labs', ''))
105
- ]:
106
- p = os.path.join(tmp, name)
107
- with open(p, 'w') as f: f.write(data)
108
- z.write(p, arcname=name)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  if audio_path and os.path.exists(audio_path):
110
- z.write(audio_path, arcname=os.path.basename(audio_path))
111
- return slide_html, audio_path, zipf_path
 
112
 
113
  # --- Gradio UI ---
114
  def run_app(topic, audience):
115
- slide_html, audio_path, zip_path = build_workshop_bundle(topic, audience)
116
- return slide_html, audio_path, zip_path
117
 
118
- with gr.Blocks(title='Workshop in a Box') as demo:
119
- gr.Markdown('# 🚀 Workshop in a Box')
120
- topic = gr.Textbox(label='Workshop Topic')
121
- audience = gr.Textbox(label='Audience')
122
  btn = gr.Button('Generate Workshop')
123
- slide_preview = gr.HTML()
124
- audio_player = gr.Audio(interactive=True)
125
- download = gr.File()
126
- btn.click(run_app, [topic, audience], [slide_preview, audio_player, download])
 
 
 
 
127
 
128
  if __name__ == '__main__':
129
  demo.launch()
 
1
+
2
+ # app.py: Workshop-in-a-Box Space with OpenTTS & Live Slide Previews
 
3
  import os
4
  import json
5
  import tempfile
 
9
  from agents import Agent, AgentRunner, handoff
10
  from agents.extensions.handoff_prompt import RECOMMENDED_PROMPT_PREFIX
11
 
12
+ # OpenTTS client
13
+ from open_tts import OpenTTSClient
14
+
15
+ # Initialize OpenTTS with your server URL (set via env var or default localhost)
16
+ opentts = OpenTTSClient(api_url=os.getenv("OPENTTS_API_URL", "http://localhost:5500"))
17
+
18
+ def generate_tts_audio(script: str) -> str:
19
+ """
20
+ Synthesize speech using OpenTTS and save to a temp MP3 file.
21
+ Returns the local file path to the audio.
22
+ """
23
+ # Request synthesis (voice and format can be configured)
24
+ audio_bytes = opentts.synthesize(text=script, voice="alloy", format="mp3")
25
+ # Write to a temp file
26
+ out_path = os.path.join(tempfile.gettempdir(), "voiceover.mp3")
27
+ with open(out_path, "wb") as f:
28
+ f.write(audio_bytes)
29
+ return out_path
30
 
31
  # --- Multi-Agent Scaffold ---
32
  # 1. Topic Agent
 
70
  name="Voiceover Agent",
71
  instructions=(
72
  f"{RECOMMENDED_PROMPT_PREFIX}\n"
73
+ "Create a 1-2 minute voiceover script. Return JSON with keys 'script'."
74
  )
75
  )
76
 
 
78
  document_orchestrator = Agent(
79
  name="Workshop Orchestrator",
80
  instructions=(
81
+ "Invoke: topic_agent, content_agent, slide_agent, code_agent, voice_agent (optional); collect outputs."
82
  ),
83
  handoffs=[
84
  handoff(topic_agent, name="outline"),
 
91
 
92
  runner = AgentRunner()
93
 
94
+ # --- Helper: Run pipeline & bundle outputs ---
95
  def build_workshop_bundle(topic: str, audience: str):
96
  prompt = f"Create a {topic} workshop for {audience}."
97
  results = runner.run(document_orchestrator, prompt).outputs
98
 
99
+ # Synthesize voiceover if script present
100
  voice_info = results.get('voiceover', {})
101
  audio_path = None
102
+ if isinstance(voice_info, dict) and 'script' in voice_info:
103
  audio_path = generate_tts_audio(voice_info['script'])
104
 
105
  # Render slides to HTML
 
108
  template = f.read()
109
  slide_html = template.replace('{{SLIDES_JSON}}', json.dumps(slides_json))
110
 
111
+ # Create a ZIP bundle
112
+ tmpdir = tempfile.mkdtemp()
113
+ zip_path = os.path.join(tmpdir, 'workshop_bundle.zip')
114
+ with ZipFile(zip_path, 'w') as zipf:
115
+ # JSON outputs
116
+ out_json = os.path.join(tmpdir, 'workshop_outputs.json')
117
+ with open(out_json, 'w') as jf:
118
+ jf.write(json.dumps(results, indent=2))
119
+ zipf.write(out_json, 'workshop_outputs.json')
120
+
121
+ # Slides
122
+ slides_file = os.path.join(tmpdir, 'slides.json')
123
+ with open(slides_file, 'w') as sf:
124
+ sf.write(json.dumps(slides_json, indent=2))
125
+ zipf.write(slides_file, 'slides.json')
126
+
127
+ slide_html_file = os.path.join(tmpdir, 'slides.html')
128
+ with open(slide_html_file, 'w') as hf:
129
+ hf.write(slide_html)
130
+ zipf.write(slide_html_file, 'slides.html')
131
+
132
+ # Code labs
133
+ code_file = os.path.join(tmpdir, 'code_labs.py')
134
+ with open(code_file, 'w') as cf:
135
+ cf.write(results.get('code_labs', ''))
136
+ zipf.write(code_file, 'code_labs.py')
137
+
138
+ # Audio
139
  if audio_path and os.path.exists(audio_path):
140
+ zipf.write(audio_path, os.path.basename(audio_path))
141
+
142
+ return slide_html, audio_path, zip_path
143
 
144
  # --- Gradio UI ---
145
  def run_app(topic, audience):
146
+ return build_workshop_bundle(topic, audience)
 
147
 
148
+ with gr.Blocks(title='🚀 Workshop in a Box') as demo:
149
+ gr.Markdown('# Workshop in a Box')
150
+ topic = gr.Textbox(label='Workshop Topic', placeholder='e.g., AI Agents 101')
151
+ audience = gr.Textbox(label='Audience', placeholder='e.g., Product Managers')
152
  btn = gr.Button('Generate Workshop')
153
+ slide_preview = gr.HTML(label='Slide Preview')
154
+ audio_player = gr.Audio(label='Voiceover Preview', interactive=True)
155
+ download = gr.File(label='Download ZIP')
156
+ btn.click(
157
+ fn=run_app,
158
+ inputs=[topic, audience],
159
+ outputs=[slide_preview, audio_player, download]
160
+ )
161
 
162
  if __name__ == '__main__':
163
  demo.launch()