import os import streamlit as st from dotenv import load_dotenv from openai import OpenAI import ast import subprocess import tempfile load_dotenv() class StoryToCodeConverter: def __init__(self): api_key = os.getenv("NOVITA_API_KEY") if not api_key: raise ValueError("NOVITA_API_KEY not found in environment") self.client = OpenAI( api_key=api_key, base_url="https://api.novita.ai/v3/openai" ) def generate_code(self, story: str) -> str: prompt = f""" Convert this children's story into Python animation code using turtle graphics. Include comments that explain loops, movement, colors—easy for kids. Story: \"\"\"{story}\"\"\" Wrap the code in triple backticks like ```python ... ``` """ response = self.client.chat.completions.create( model="meta-llama/llama-3.1-8b-instruct", messages=[ {"role": "system", "content": "You are a friendly teacher and coder for kids."}, {"role": "user", "content": prompt} ], max_tokens=512, ) return self._extract_code(response.choices[0].message.content) def _extract_code(self, content: str) -> str: if "```python" in content: return content.split("```python")[1].split("```")[0] return content class CodeExecutor: def execute_safely(self, code: str) -> bool: try: ast.parse(code) with tempfile.NamedTemporaryFile(delete=False, suffix=".py") as tmp: tmp.write(code.encode("utf-8")) path = tmp.name subprocess.Popen(["python", path]) return True except Exception as e: st.error(f"Robot Chef burned the cake: {e}") return False st.set_page_config(page_title="CodeTales", page_icon="✨") with st.sidebar: st.header("🍰 How It Works") st.markdown(""" 1. 📝 Kids write a story 2. 🔮 Novita AI turns it into Python‑turtle code 3. 🎮 Animation plays 4. 🤖 Robot Teacher explains concepts """) st.title("✨ CodeTales: Storytime + Coding Magic") story = st.text_area("Write your story here:", height=200, placeholder="A turtle draws a rainbow circle...") if st.button("✨ Bake My Story Cake!"): if not story.strip(): st.warning("Please enter a story!") else: with st.spinner("Baking your story code... 🍰"): try: converter = StoryToCodeConverter() code = converter.generate_code(story) except Exception as e: st.error(f"AI oven broke down! {e}") st.stop() st.subheader("📜 Your Code Recipe") st.code(code, language="python") executor = CodeExecutor() if executor.execute_safely(code): st.balloons() with st.expander("🤖 Robot Teacher Says:"): st.markdown(""" - `turtle.forward(100)` – Moves forward - `turtle.color("red")` – Changes color - `for` loops – Repeat patterns """) st.success("🎉 Animation ready!") else: st.error("Oops, something went wrong.") st.caption("Made with ❤️ for young coders | Powered by Novita AI + Python Turtle")