Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import requests | |
| import json | |
| import re | |
| import os | |
| # Groq API configuration - will be set via Hugging Face secrets | |
| GROQ_API_KEY = os.environ.get("GROQ_API_KEY") | |
| GROQ_API_URL = "https://api.groq.com/openai/v1/chat/completions" | |
| def generate_story(age, theme, language): | |
| # Check if API key is available | |
| if not GROQ_API_KEY: | |
| return "β Please set your GROQ_API_KEY in Hugging Face Space secrets to generate stories." | |
| age_i = int(age) | |
| if age_i <= 6: | |
| length = "300 words" | |
| elif age_i <= 9: | |
| length = "600 words" | |
| else: | |
| length = "1000 words" | |
| # Prepare the request payload for Groq API | |
| payload = { | |
| "messages": [ | |
| { | |
| "role": "system", | |
| "content": "You write age-appropriate stories with complete endings and a moral." | |
| }, | |
| { | |
| "role": "user", | |
| "content": ( | |
| f"Write a complete story for a {age}-year-old child. " | |
| f"Theme: {theme}. Language: {language}. Length about {length}. " | |
| "End with a clear moral of the story." | |
| ) | |
| } | |
| ], | |
| "model": "llama-3.1-8b-instant", | |
| "max_tokens": 2000, | |
| "temperature": 0.8 | |
| } | |
| headers = { | |
| "Authorization": f"Bearer {GROQ_API_KEY}", | |
| "Content-Type": "application/json" | |
| } | |
| try: | |
| response = requests.post(GROQ_API_URL, json=payload, headers=headers) | |
| response.raise_for_status() | |
| data = response.json() | |
| story = data["choices"][0]["message"]["content"].strip() | |
| return story | |
| except Exception as e: | |
| return f"Error generating story: {str(e)}\n\nPlease check your API key and try again." | |
| def story_to_speech(story, language_code='en'): | |
| try: | |
| # For Hugging Face deployment, we'll use a simple audio generation | |
| # Note: gTTS might not work reliably on Hugging Face, so we provide alternative | |
| from gtts import gTTS | |
| tts = gTTS(text=story, lang=language_code) | |
| filename = "story.mp3" | |
| tts.save(filename) | |
| return filename | |
| except Exception as e: | |
| # Fallback: Return a message about audio being unavailable | |
| print(f"TTS Error: {e}") | |
| return None | |
| def create_story_interface(age, theme, language, tts_option): | |
| story = generate_story(age, theme, language) | |
| # Remove Markdown symbols (*, #, _, etc.) to prevent asterisks showing up | |
| story = re.sub(r'[*_#`~]', '', story) | |
| # Split first line as title | |
| lines = story.split("\n", 1) | |
| if len(lines) > 1: | |
| title, rest_of_story = lines[0], lines[1] | |
| else: | |
| title, rest_of_story = lines[0], "" | |
| if language.lower().startswith("u"): # Urdu | |
| story_html = ( | |
| f'<div style="text-align:center; font-size:1.3em; direction:rtl; margin-bottom:5px;">{title}</div>' | |
| f'<div style="font-size:1.2em; direction:rtl; text-align:right;">{rest_of_story}</div>' | |
| ) | |
| lang_code = "ur" | |
| else: # English | |
| story_html = ( | |
| f'<div style="text-align:center; font-size:1.3em; direction:ltr; margin-bottom:5px;">{title}</div>' | |
| f'<div style="font-size:1.2em; direction:ltr; text-align:left;">{rest_of_story}</div>' | |
| ) | |
| lang_code = "en" | |
| # Generate audio if TTS is enabled | |
| audio_file = story_to_speech(story, lang_code) if tts_option else None | |
| return story, audio_file | |
| # Age options | |
| age_options = [str(i) for i in range(3, 13)] | |
| # Theme options | |
| theme_options = [ | |
| "Adventure", "Animals", "Fantasy", "Educational", | |
| "Friendship", "Magic", "Science", "Mystery", | |
| "Space", "Nature", "Kindness", "Courage" | |
| ] | |
| language_options = ["English", "Urdu"] | |
| # Custom CSS for child-friendly interface | |
| custom_css = """ | |
| @import url('https://fonts.googleapis.com/css2?family=Comic+Neue:wght@400;700&display=swap'); | |
| .gradio-container { | |
| font-family: 'Comic Neue', cursive !important; | |
| background: linear-gradient(135deg, #ffafbd, #ffc3a0) !important; | |
| padding-top: 10px !important; | |
| } | |
| .main-header { | |
| text-align: center; | |
| font-weight: bold !important; | |
| font-size: 3.2em !important; | |
| margin-top: 40px !important; | |
| margin-bottom: 20px !important; | |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.1); | |
| color: #12979B; | |
| } | |
| .story-container { | |
| background:#fff5ee; | |
| border-radius: 20px; | |
| padding: 25px; | |
| border: 5px solid #FFD166; | |
| box-shadow: 0 8px 25px rgba(0,0,0,0.1); | |
| min-height: 400px; | |
| margin-top: 20px !important; | |
| } | |
| .control-panel { | |
| background: #fff5ee; | |
| border-radius: 15px; | |
| padding: 20px; | |
| border: 3px dashed #4ECDC4; | |
| font-size: 1.2em !important; | |
| font-weight: 600; | |
| margin-top: 20px !important; | |
| } | |
| .generate-btn { | |
| background: linear-gradient(45deg, #FF6B6B, #FF9E7D) !important; | |
| border: none !important; | |
| border-radius: 50px !important; | |
| padding: 15px 30px !important; | |
| font-size: 1.2em !important; | |
| font-weight: bold !important; | |
| color: white !important; | |
| margin-top: 20px !important; | |
| width: 100%; | |
| } | |
| .generate-btn:hover { | |
| transform: scale(1.05); | |
| box-shadow: 0 5px 15px rgba(255, 107, 107, 0.4); | |
| } | |
| .dropdown, .checkbox { | |
| background: white !important; | |
| border-radius: 10px !important; | |
| border: 2px solid #96CEB4 !important; | |
| margin: 10px 0; | |
| } | |
| .audio-player { | |
| border-radius: 15px !important; | |
| margin-top: 20px; | |
| } | |
| .subtitle { | |
| text-align: center; | |
| font-size: 1.5em !important; | |
| font-weight: 600; | |
| color: white; | |
| margin-bottom: 20px; | |
| text-shadow: 1px 1px 2px rgba(0,0,0,0.1); | |
| } | |
| .footer { | |
| text-align: center; | |
| margin-top: 20px; | |
| color: #666; | |
| font-style: italic; | |
| font-size: 1.1em !important; | |
| } | |
| """ | |
| with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as iface: | |
| gr.HTML(""" | |
| <div class="main-header"> | |
| π StoryTime AI πͺ | |
| </div> | |
| """) | |
| gr.HTML(""" | |
| <div class="subtitle"> | |
| π― Create amazing stories that spark imagination and teach valuable lessons! | |
| </div> | |
| """) | |
| # API Key warning | |
| if not GROQ_API_KEY: | |
| gr.Warning("β οΈ Please set GROQ_API_KEY in Hugging Face Space secrets to use this app") | |
| with gr.Row(): | |
| with gr.Column(scale=1, min_width=300): | |
| with gr.Group(elem_classes="control-panel"): | |
| gr.Markdown("### π¨ Story Settings") | |
| age_input = gr.Dropdown( | |
| age_options, | |
| label="πΆ Child's Age", | |
| value="5", | |
| info="Select age 3-12 years" | |
| ) | |
| theme_input = gr.Dropdown( | |
| theme_options, | |
| label="π Story Theme", | |
| value="Adventure", | |
| info="Choose your favorite theme" | |
| ) | |
| language_input = gr.Dropdown( | |
| language_options, | |
| label="π Language", | |
| value="English", | |
| info="English or Urdu" | |
| ) | |
| tts_input = gr.Checkbox( | |
| label="π Include Audio Story", | |
| value=True, | |
| info="Listen to the story (may not work in all environments)" | |
| ) | |
| generate_btn = gr.Button( | |
| "β¨ Create Magical Story! β¨", | |
| elem_classes="generate-btn" | |
| ) | |
| with gr.Column(scale=2): | |
| with gr.Group(elem_classes="story-container"): | |
| gr.Markdown("### π Your Magical Story") | |
| story_output = gr.Markdown( | |
| "Your story will appear here! Choose settings and click the magic button! π", | |
| show_label=False | |
| ) | |
| with gr.Group(): | |
| gr.Markdown("### π§ Listen to Your Story") | |
| audio_output = gr.Audio( | |
| label="Audio Story", | |
| show_label=False | |
| ) | |
| gr.HTML(""" | |
| <div class="footer"> | |
| Made with β€οΈ for young readers everywhere! | Watch your stories come to life! β¨ | |
| </div> | |
| """) | |
| generate_btn.click( | |
| create_story_interface, | |
| [age_input, theme_input, language_input, tts_input], | |
| [story_output, audio_output] | |
| ) | |
| if __name__ == "__main__": | |
| iface.launch() |