Spaces:
Sleeping
Sleeping
import os | |
import requests | |
import gradio as gr | |
import re | |
# === API SETUP === | |
GROQ_API_KEY = "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" # Bạn nên dùng biến môi trường | |
GROQ_API_URL = "https://api.groq.com/openai/v1/chat/completions" | |
HEADERS = { | |
"Authorization": f"Bearer {GROQ_API_KEY}", | |
"Content-Type": "application/json" | |
} | |
# === BLOCKED TOPICS === | |
BLOCKED_KEYWORDS = [ | |
"sex", "drugs", "violence", "suicide", "death", "kill", "murder", "gun", | |
"abuse", "politics", "terror", "crime", "war", "religion", "racism", | |
"nude", "adult", "nsfw" | |
] | |
def is_safe_topic(topic: str) -> bool: | |
topic_lower = topic.lower() | |
return not any(bad_word in topic_lower for bad_word in BLOCKED_KEYWORDS) | |
# === PODCAST GENERATION === | |
def generate_educational_podcast(topic: str, language: str, model: str = "llama3-70b-8192") -> str: | |
prompt = f""" | |
You are a scriptwriter for an educational podcast for students in grades 8 to 12. | |
Create a short and engaging podcast script in **{language}** on the topic: "{topic}". | |
The two hosts are named Ali and Talha. Ali starts the conversation. | |
They should have a back-and-forth conversation about the topic. | |
The tone should be friendly, easy to understand, and informative. | |
Avoid music or sound effects. Keep the total length under 800 words. | |
Only write their dialogue and a few narration lines if needed. Do NOT use Host 1/2 or generic names. | |
""" | |
data = { | |
"model": model, | |
"messages": [ | |
{"role": "system", "content": "You are a creative and age-appropriate educational podcast writer."}, | |
{"role": "user", "content": prompt.strip()} | |
], | |
"temperature": 0.75, | |
"max_tokens": 1024 | |
} | |
response = requests.post(GROQ_API_URL, headers=HEADERS, json=data) | |
if response.status_code == 200: | |
return response.json()["choices"][0]["message"]["content"].strip() | |
else: | |
return f"<b>Error {response.status_code}</b>: {response.text}" | |
# === SCRIPT FORMATTING === | |
def format_script(script: str) -> str: | |
script = re.sub(r'\*\*(.*?)\*\*', r'\1', script) | |
script = re.sub(r'(?i)^.*(music|sound effect).*$','', script, flags=re.MULTILINE) | |
script = script.replace("Host 1:", "Ali:").replace("Host 2:", "Talha:") | |
script = re.sub(r'\b[Aa]lex:', 'Ali:', script) | |
script = re.sub(r'\b[Mm]aya:', 'Talha:', script) | |
lines = script.strip().split("\n") | |
formatted = "" | |
for line in lines: | |
line = line.strip() | |
if not line: | |
continue | |
if line.startswith("Ali:"): | |
content = line.replace("Ali:", "").strip() | |
formatted += f"<div class='host1'>🎙️ <b>Ali:</b> {content}</div>\n" | |
elif line.startswith("Talha:"): | |
content = line.replace("Talha:", "").strip() | |
formatted += f"<div class='host2'>🎧 <b>Talha:</b> {content}</div>\n" | |
return formatted | |
# === GRADIO UI === | |
custom_css = """ | |
.host1, .host2 { | |
border-radius: 16px; | |
padding: 14px; | |
margin: 16px 0; | |
box-shadow: 0 4px 10px rgba(255,255,255,0.2); | |
font-size: 16px; | |
line-height: 1.6; | |
color: #ffffff; | |
} | |
.host1 { | |
background: linear-gradient(135deg, #4b6cb7, #182848); | |
} | |
.host2 { | |
background: linear-gradient(135deg, #2c3e50, #4ca1af); | |
} | |
""" | |
def generate(topic, language): | |
if not is_safe_topic(topic): | |
return "<b style='color:red;'>⚠️ Restricted content. Please enter an appropriate educational topic.</b>" | |
raw_script = generate_educational_podcast(topic, language) | |
return format_script(raw_script) | |
with gr.Blocks(css=custom_css) as demo: | |
gr.Markdown("## 🎙️ Educational Podcast Generator for Students") | |
gr.Markdown("Enter a topic and choose your language to generate a friendly podcast between Ali and Talha.") | |
topic_input = gr.Textbox(label="Enter educational topic") | |
lang_input = gr.Dropdown( | |
choices=["English", "Vietnamese", "Spanish", "French", "Japanese"], | |
value="English", | |
label="Select output language" | |
) | |
generate_btn = gr.Button("🎧 Generate Podcast") | |
output_box = gr.HTML() | |
generate_btn.click(fn=generate, inputs=[topic_input, lang_input], outputs=output_box) | |
demo.launch() | |