naso / app.py
mgbam's picture
Update app.py
c679f41 verified
raw
history blame
5.37 kB
## 1. `app.py`
import os
import json
import tempfile
from zipfile import ZipFile
import gradio as gr
from agents import Agent, AgentRunner, handoff
from agents.extensions.handoff_prompt import RECOMMENDED_PROMPT_PREFIX
# === Coqui TTS Integration ===
from TTS.api import TTS
# Initialize Coqui TTS (choose a model)
# Using Tacotron2-DDC model from LJSpeech
tts = TTS(
model_name="tts_models/en/ljspeech/tacotron2-DDC",
progress_bar=False,
gpu=False
)
def generate_tts_audio(script: str) -> str:
"""
Synthesize speech using Coqui TTS and save to a WAV file.
Returns the local file path to the audio.
"""
# Determine output path in temp directory
out_path = os.path.join(tempfile.gettempdir(), "voiceover.wav")
# Render the speech to the file
tts.tts_to_file(text=script, file_path=out_path)
return out_path
# --- Multi-Agent Scaffold ---
# 1. Topic Agent
topic_agent = Agent(
name="Topic Agent",
instructions=(
f"{RECOMMENDED_PROMPT_PREFIX}\n"
"You are given a workshop topic and audience. Draft a structured learning path: goals, 4 modules, and a hands-on exercise for each."
)
)
# 2. Content Agent
content_agent = Agent(
name="Content Agent",
instructions=(
f"{RECOMMENDED_PROMPT_PREFIX}\n"
"Convert the outline into detailed module scripts, speaker notes, and 3 quiz questions per module."
)
)
# 3. Slide Agent
slide_agent = Agent(
name="Slide Agent",
instructions=(
f"{RECOMMENDED_PROMPT_PREFIX}\n"
"Given module content, produce slide JSON with title, bullet points, and design hints."
)
)
# 4. Code Agent
code_agent = Agent(
name="Code Agent",
instructions=(
f"{RECOMMENDED_PROMPT_PREFIX}\n"
"Generate runnable Python code snippets or a Colab notebook for hands-on labs in each module."
)
)
# 5. Voiceover Agent (Optional)
voice_agent = Agent(
name="Voiceover Agent",
instructions=(
f"{RECOMMENDED_PROMPT_PREFIX}\n"
"Create a 1-2 minute voiceover script. Return JSON with key 'script'."
)
)
# Orchestrator: sequences agents
document_orchestrator = Agent(
name="Workshop Orchestrator",
instructions=(
"Invoke: topic_agent, content_agent, slide_agent, code_agent, voice_agent (optional); collect outputs."
),
handoffs=[
handoff(topic_agent, name="outline"),
handoff(content_agent, name="content"),
handoff(slide_agent, name="slides"),
handoff(code_agent, name="code_labs"),
handoff(voice_agent, name="voiceover", optional=True),
]
)
runner = AgentRunner()
# --- Helper: Run pipeline & bundle outputs ---
def build_workshop_bundle(topic: str, audience: str):
prompt = f"Create a {topic} workshop for {audience}."
results = runner.run(document_orchestrator, prompt).outputs
# Synthesize voiceover if script present
voice_info = results.get('voiceover', {})
audio_path = None
if isinstance(voice_info, dict) and 'script' in voice_info:
audio_path = generate_tts_audio(voice_info['script'])
# Render slides to HTML
slides_json = results.get('slides', {})
with open('static/slides_template.html') as f:
template = f.read()
slide_html = template.replace('{{SLIDES_JSON}}', json.dumps(slides_json))
# Create a ZIP bundle
tmpdir = tempfile.mkdtemp()
zip_path = os.path.join(tmpdir, 'workshop_bundle.zip')
with ZipFile(zip_path, 'w') as zipf:
# JSON outputs
out_json = os.path.join(tmpdir, 'workshop_outputs.json')
with open(out_json, 'w') as jf:
jf.write(json.dumps(results, indent=2))
zipf.write(out_json, 'workshop_outputs.json')
# Slides JSON & HTML
slide_json_file = os.path.join(tmpdir, 'slides.json')
with open(slide_json_file, 'w') as sf:
sf.write(json.dumps(slides_json, indent=2))
zipf.write(slide_json_file, 'slides.json')
slide_html_file = os.path.join(tmpdir, 'slides.html')
with open(slide_html_file, 'w') as hf:
hf.write(slide_html)
zipf.write(slide_html_file, 'slides.html')
# Code labs
code_file = os.path.join(tmpdir, 'code_labs.py')
with open(code_file, 'w') as cf:
cf.write(results.get('code_labs', ''))
zipf.write(code_file, 'code_labs.py')
# Audio
if audio_path and os.path.exists(audio_path):
zipf.write(audio_path, os.path.basename(audio_path))
return slide_html, audio_path, zip_path
# --- Gradio UI ---
def run_app(topic, audience):
slide_html, audio_path, zip_path = build_workshop_bundle(topic, audience)
return slide_html, audio_path, zip_path
with gr.Blocks(title='πŸš€ Workshop in a Box') as demo:
gr.Markdown('# Workshop in a Box')
topic = gr.Textbox(label='Workshop Topic', placeholder='e.g., AI Agents 101')
audience = gr.Textbox(label='Audience', placeholder='e.g., Product Managers')
btn = gr.Button('Generate Workshop')
slide_preview = gr.HTML(label='Slide Preview')
audio_player = gr.Audio(label='Voiceover Preview', interactive=True)
download = gr.File(label='Download ZIP')
btn.click(
fn=run_app,
inputs=[topic, audience],
outputs=[slide_preview, audio_player, download]
)
if __name__ == '__main__':
demo.launch()