Spaces:
Runtime error
Runtime error
| """ | |
| Prompt utilities for personalization and content generation. | |
| Usage: | |
| ------ | |
| Import the model_config module: | |
| from src.model_config import get_llm_client, get_primary_model, get_backup_model | |
| The prompt utilities are used in: | |
| - src/tools/audio_utils.py (translations and named entity identification) | |
| - src/Slide_Creation_Node_refactor.py (slide narration) | |
| """ | |
| from typing import List, Optional | |
| #code_generation_node.py | |
| def get_code_segmentation_prompt(full_code: str, language: str = "python") -> str: | |
| """ | |
| Generates a clear prompt to send to the LLM to segment code. | |
| The input code is delimited so the model knows its boundaries, but the model's | |
| output must be raw JSON (no markdown wrappers). | |
| """ | |
| # Optional: strip extraneous leading/trailing whitespace to avoid weird indentation issues | |
| trimmed_code = full_code.strip() | |
| return ( | |
| f"Break down the following {language} code into logical, self-contained, and explainable segments. " | |
| "For each segment, provide the exact code snippet (preserving original line breaks and indentation) " | |
| "and a concise explanation (2–4 sentences describing its purpose and functionality).\n\n" | |
| "Return the output as a JSON array of objects. Each object must have exactly two keys: " | |
| "'code_snippet' (string) and 'explanation' (string). Ensure the segments collectively cover the entire " | |
| "provided code in the correct order. Do NOT include any extra text or conversational filler outside the " | |
| "main JSON array. Do NOT wrap the returned JSON in markdown (no ``` around it).\n\n" | |
| f"{language} Code (delimited by triple backticks):\n```{trimmed_code}```\n" | |
| ) | |
| # Slide_Creation_Node.py | |
| def get_oration_prompt( | |
| content: str, | |
| user_name: Optional[str] = None, | |
| user_age: Optional[int] = None, | |
| user_tech_knowledge: Optional[str] = None, | |
| user_preferred_activity: Optional[List[str]] = None | |
| ) -> List[dict]: | |
| """ | |
| Returns a system+user message list for generating a formal explanation (oration), | |
| optionally personalized based on available user metadata. | |
| """ | |
| prompt = ( | |
| "Craft a succinct, formally structured explanation (industrial training level) using the provided content. " | |
| "Avoid informalities (greetings, thanks). Use logical organization and pertinent real-world examples or scenarios " | |
| "if applicable to enhance comprehension. Do not include code blocks in the oration." | |
| ) | |
| if user_name: | |
| age_desc = f"{user_age}-year-old" if user_age is not None else "of unspecified age" | |
| tech = user_tech_knowledge or "beginner" | |
| activities = ', '.join(user_preferred_activity) if user_preferred_activity else "general topics" | |
| prompt += ( | |
| f" The student is {user_name}, a {age_desc} with {tech} level knowledge. " | |
| f"Use examples related to their interests: {activities}." | |
| ) | |
| return [ | |
| {"role": "system", "content": prompt}, | |
| {"role": "user", "content": content} | |
| ] | |
| #three_b_node.py | |
| def get_personalization_prompt( | |
| topic: str, | |
| programming_language: str, | |
| presentation_txt: str, | |
| user_name: Optional[str] = None, | |
| user_age: Optional[int] = None, | |
| user_gender: Optional[str] = None, | |
| user_tech_knowledge: Optional[str] = None, | |
| user_preferred_activity: Optional[List[str]] = None, | |
| user_food: Optional[str] = None, | |
| user_physical_activities: Optional[str] = None | |
| ) -> str: | |
| """ | |
| Returns the raw prompt body for personalizing a presentation. Caller is responsible | |
| for wrapping this into messages for the LLM. | |
| """ | |
| personalization_context = "" | |
| if user_name: | |
| age_desc = f"{user_age}-year-old" if user_age is not None else "of unspecified age" | |
| gender_part = f" {user_gender}" if user_gender else "" | |
| personalization_context += f"You are teaching {user_name}, a {age_desc}{gender_part} student. " | |
| if user_tech_knowledge: | |
| personalization_context += f"Their technical knowledge level is {user_tech_knowledge}. " | |
| if user_preferred_activity: | |
| activities = ', '.join(user_preferred_activity) | |
| personalization_context += f"They enjoy {activities}. " | |
| if user_food: | |
| personalization_context += f"Their favorite food is {user_food}. " | |
| if user_physical_activities: | |
| personalization_context += f"They like {user_physical_activities}. " | |
| personalization_context += "Use examples and analogies that relate to their interests and knowledge level. " | |
| prompt = ( | |
| f"{personalization_context}\n" | |
| f"Here is an existing presentation for the topic '{topic}' in '{programming_language}':\n\n" | |
| f"{presentation_txt}\n\n" | |
| "Please personalize and enhance this presentation for the student described above. " | |
| "Keep the structure and number of slides, but adjust examples, analogies, and explanations to better fit the student's interests and background. " | |
| "Do not generate from scratch; instead, modify and enrich the provided content. " | |
| "Keep each slide concise (max 100 words or 10 lines). " | |
| "Format EACH slide strictly as:\n" | |
| "Slide <number>:\nTitle: <Concise, descriptive title>\n\n" | |
| "Content:\n" | |
| "<Your bulleted content, with each point starting with '-' and optional code snippets marked with ```>.\n" | |
| "IMPORTANT: When declaring code blocks, do not mention the code extension, programming language, or file type. " | |
| "Simply use ``` to start and end the code block." | |
| ) | |
| return prompt | |
| def build_concept_code_prompt(topic: str, programming_language: str) -> str: | |
| return ( | |
| f"Create a comprehensive {programming_language} program that demonstrates the concept of " | |
| f"'{topic}' with practical examples and clear comments." | |
| ) | |
| def get_code_generation_prompt(programming_language: str, code_prompt: str) -> list[dict]: | |
| system_msg = { | |
| "role": "system", | |
| "content": ( | |
| f"Generate executable {programming_language} code based on the provided topic and analogy. " | |
| "The code should be complete, runnable, and demonstrate the concept clearly without requiring user input." | |
| ) | |
| } | |
| user_msg = {"role": "user", "content": code_prompt} | |
| return [system_msg, user_msg] | |
| #three_a_node.py | |
| def get_subtitle_prompt(topic: str) -> str: | |
| """ | |
| Returns a prompt to generate a 3–5 word subtitle based on topic. | |
| """ | |
| return f"Generate 3-5 word subtitle based on {topic}" | |
| def get_presentation_generation_prompt(topic: str, programming_language: str) -> str: | |
| """ | |
| Returns a prompt for generating a presentation for a given topic and programming language. | |
| """ | |
| return ( | |
| f"Generate content to explain '{topic}' for students, focusing on '{programming_language}'. " | |
| "Present the most important basics using concise bullet points. Include small, relevant real-world examples " | |
| "with brief code snippets (only if truly necessary and illustrative). Maintain a professional tone. " | |
| "DIVIDE THE OUTPUT INTO EXACTLY 4-6 SLIDES to ensure thorough coverage. " | |
| "Each slide should cover a distinct aspect of the topic. " | |
| "Keep each bullet point to 1-2 lines and limit each slide's content to a maximum of 80 words. " | |
| "Code snippets should be 3-5 lines maximum. " | |
| "Format EACH slide strictly as:\n" | |
| "Slide <number>:\nTitle: <Concise, descriptive title>\n\nContent:\n" | |
| "<Your bulleted content, with each point starting with '-' and optional code snippets marked with '>'.\n" | |
| "Include one slide with a real-world analogy to help students understand the concept.\n" | |
| "IMPORTANT: When declaring code blocks, do not mention the code extension, programming language, or file type. " | |
| "Simply use ``` to start and end the code block." | |
| ) | |
| def get_topic_code_prompt(topic: str, programming_language: str) -> tuple[str, str]: | |
| """ | |
| Returns system and user messages for generating executable code for a topic. | |
| """ | |
| system_message = ( | |
| f"Generate executable {programming_language} code based on the provided topic and analogy. " | |
| "The code should be complete, runnable, and demonstrate the concept clearly without requiring user input." | |
| ) | |
| user_message = ( | |
| f"Based on this topic '{topic}' create executable {programming_language} code that demonstrates the concept clearly." | |
| ) | |
| return system_message, user_message | |
| #audio_utils.py | |
| def get_named_entity_identification_prompt() -> str: | |
| """ | |
| Returns the prompt for identifying named entities and coding jargon | |
| in a text for translation context. | |
| """ | |
| return ( | |
| "Below is a technical explanation that will be translated into another language. " | |
| "Your task is to identify parts of the text that are specific named entities—these include:\n" | |
| "Coding Jargon: Specific functions, classes, variables, or code snippets (e.g., main(), print()). " | |
| "Make sure to include as much coding jargon as possible\n" | |
| "Technical Terms: Programming languages (e.g., Python, JavaScript), libraries (e.g., TensorFlow, NumPy)\n" | |
| "Proper Nouns: Names of organizations, products, or companies (e.g., Across the Globe, Microsoft).\n" | |
| "terms like loops are named entities that should not be translated.\n\n" | |
| "Wrap these identified words or phrases in the tag <named_entities></named_entities>. " | |
| "Ensure the final text is formatted exactly as requested and returned within triple single quotes ('''). " | |
| "Do not modify the text except to add the tags. Here's the text:" | |
| ) | |
| def get_regional_translation_prompt(target_language: str, cleaned_text: str) -> str: | |
| """ | |
| Returns the prompt for translating English text to a specified regional language. | |
| """ | |
| return f""" | |
| Translate the following English text to "{target_language}" and return JSON only: | |
| "{cleaned_text}" | |
| Guidelines: | |
| - Use simple, everyday {target_language}. | |
| - Avoid complex words. | |
| - Don't translate 'For', 'If', or 'Across The Globe'. | |
| - Use pure {target_language} script. | |
| - Respond ONLY as JSON like this: | |
| {{ | |
| "translation": "<translated_text_here>" | |
| }} | |
| """ | |
| def get_pun_translation_prompt(target_language: str, cleaned_text: str) -> str: | |
| """ | |
| Builds the prompt for translating English text to a regional language (Punjabi variant). | |
| """ | |
| return f""" | |
| Translate the following English text to "{target_language}" and return JSON only: | |
| "{cleaned_text}" | |
| Guidelines: | |
| - Use simple, everyday {target_language}. | |
| - Avoid complex words. | |
| - Don't translate 'For', 'If', or 'Across The Globe'. | |
| - Use pure {target_language} script. | |
| - Respond ONLY as JSON like this: | |
| {{ | |
| "translation": "<translated_text_here>" | |
| }} | |
| """ | |
| def get_pun_named_entity_prompt() -> str: | |
| """ | |
| Returns the prompt for identifying named entities and coding jargon in a text | |
| for Punjabi translation context. | |
| """ | |
| return ( | |
| "Below is a technical explanation that will be translated into another language. " | |
| "Your task is to identify parts of the text that are specific named entities—these include:\n\n" | |
| "Coding Jargon: Specific functions, classes, variables, or code snippets (e.g., main(), print()). " | |
| "Make sure to include as much coding jargon as possible\n" | |
| "Technical Terms: Programming languages (e.g., Python, JavaScript), libraries (e.g., TensorFlow, NumPy)\n" | |
| "Proper Nouns: Names of organizations, products, or companies (e.g., Across the Globe, Microsoft).\n" | |
| "terms like loops are named entities that should not be translated.\n\n" | |
| "Wrap these identified words or phrases in the tag <named_entities></named_entities>. " | |
| "Ensure the final text is formatted exactly as requested and returned within triple single quotes ('''). " | |
| "Do not modify the text except to add the tags. Here's the text:" | |
| ) | |
| # Slide_Creation_Node_refactor.py | |
| def get_tts_narration_prompt( | |
| slide_content: str, | |
| slide_title: str, | |
| topic: str, | |
| target_audience: str = "beginners", | |
| user_name: Optional[str] = None, | |
| previous_slide_title: Optional[str] = None, | |
| previous_slide_summary: Optional[str] = None | |
| ) -> str: | |
| """ | |
| Returns a prompt optimized for generating natural, conversational narration text | |
| specifically designed for TTS (Text-to-Speech) with Gemini API. | |
| This prompt focuses on: | |
| - Natural speech patterns with proper punctuation for pauses | |
| - Conversational tone that sounds realistic when spoken | |
| - Strategic use of commas, periods, and ellipses for pacing | |
| - Avoiding robotic bullet-point reading | |
| - Context awareness from previous slides for smooth transitions | |
| """ | |
| personalization = f" The student's name is {user_name}." if user_name else "" | |
| # Build context from previous slide if available | |
| context_section = "" | |
| if previous_slide_title and previous_slide_summary: | |
| context_section = f""" | |
| PREVIOUS SLIDE CONTEXT: | |
| Previous Topic: {previous_slide_title} | |
| Key Points Covered: {previous_slide_summary} | |
| IMPORTANT: Create a smooth transition from the previous slide. Use phrases like: | |
| - "Now that we've covered [previous topic], let's move to..." | |
| - "Building on what we just learned about [previous topic]..." | |
| - "Next, we'll explore..." | |
| - "This connects directly to what we discussed about [previous topic]..." | |
| """ | |
| return f"""You are creating a narration script for a text-to-speech system. The script will be read aloud by an AI voice, so it must sound natural, engaging, and conversational when spoken. | |
| SLIDE INFORMATION: | |
| Title: {slide_title} | |
| Topic: {topic} | |
| Audience: {target_audience}{personalization} | |
| {context_section} | |
| CONTENT TO NARRATE: | |
| {slide_content} | |
| TTS NARRATION GUIDELINES: | |
| 1. NATURAL SPEECH PATTERNS: | |
| - Write as if you're continuing an ongoing conversation with the student | |
| - Use conversational phrases like "Let's explore...", "You see...", "Now here's the interesting part..." | |
| - Vary sentence length for natural rhythm | |
| - DO NOT use greetings like "Welcome", "Hello", or "Hi" - we're in the middle of the lesson | |
| 2. PUNCTUATION FOR PACING (Critical for TTS): | |
| - Use commas (,) for brief pauses and breath breaks | |
| - Use periods (.) for natural sentence endings | |
| - Use ellipses (...) for thoughtful pauses or building anticipation | |
| - Use em dashes (—) for emphasis or adding related thoughts | |
| - Example: "First, let's understand the basics... Python is powerful, flexible, and—most importantly—easy to learn." | |
| 3. EMOTIONAL INTELLIGENCE: | |
| - Show enthusiasm for interesting concepts: "Here's what makes this amazing!" | |
| - Acknowledge difficulty: "This might seem tricky at first, but stick with me..." | |
| - Build confidence: "You've got this!", "Let's break this down together." | |
| - Use encouraging transitions: "Great! Now that we understand X, let's move to Y." | |
| 4. STRICT RULES - AVOID: | |
| - Welcome greetings ("Welcome", "Hello", "Hi") - this is NOT the introduction | |
| - Robotic bullet-point reading ("Point one. Point two.") | |
| - Long, complex sentences without breaks | |
| - Academic jargon without explanation | |
| - Monotonous structure | |
| - Starting fresh as if it's a new lesson - maintain continuity | |
| 5. PACING TECHNIQUES: | |
| - Start with a transition or hook: "Now let's look at..." or "Here's where it gets interesting..." | |
| - Use rhetorical questions to engage: "Why does this matter?" | |
| - Break complex ideas into digestible chunks with pauses | |
| - End with a memorable takeaway or bridge to the next concept | |
| 6. CODE MENTIONS: | |
| - When mentioning code, speak it naturally: "the print function" not "print parenthesis close parenthesis" | |
| - Add brief context: "the main function, which is where our program starts" | |
| OUTPUT REQUIREMENTS: | |
| - Generate 3-5 sentences of natural, conversational narration | |
| - Length: 60-120 words (optimal for TTS clarity) | |
| - Include strategic punctuation for natural pauses | |
| - Sound like a friendly, knowledgeable teacher continuing a lesson | |
| - Make it engaging and personalized for {target_audience} | |
| - NO welcome/greeting phrases - maintain lesson continuity | |
| Generate the TTS-optimized narration script now:""" | |
| def get_length_limited_narration_prompt(original_text: str, max_seconds: int = 15, wpm: int = 150, user_name: Optional[str] = None) -> str: | |
| """ | |
| Returns a prompt instructing the LLM to shorten a narration to a target time limit | |
| while preserving natural tone and punctuation suitable for TTS. | |
| """ | |
| max_words = max(10, int(max_seconds * wpm / 60)) | |
| personalization = f"Address the learner by their name, {user_name}, at the beginning. " if user_name else "" | |
| return ( | |
| f"{personalization}Rewrite the following narration so that it is at most {max_words} words long (approx {max_seconds} seconds at {wpm} WPM).\n" | |
| "Maintain a friendly, conversational tone suitable for TTS, and preserve punctuation for pauses (commas, ellipses, dashes).\n" | |
| "Do not truncate mid-sentence; prefer to rephrase to keep the meaning and natural flow.\n\n" | |
| f"Original narration:\n{original_text}\n\n" | |
| "Return only the revised, shortened narration text (no extra commentary)." | |
| ) | |
| def shorten_narration_text(client, original_text: str, max_seconds: int = 15, wpm: int = 150, user_name: Optional[str] = None, model: str = "gpt-4o-mini") -> str: | |
| """ | |
| Uses the provided client (OpenAI) to shorten a narration to fit within the given time limit. | |
| Falls back to a simple word truncation if the client is not available. | |
| """ | |
| if not original_text or not original_text.strip(): | |
| return original_text | |
| max_words = max(10, int(max_seconds * wpm / 60)) | |
| if len(original_text.split()) <= max_words: | |
| return original_text | |
| prompt = get_length_limited_narration_prompt(original_text, max_seconds, wpm, user_name) | |
| if not client: | |
| # Fallback: simple truncation by words preserving punctuation as much as possible. | |
| words = original_text.split() | |
| shortened = " ".join(words[:max_words]) | |
| # Try to end at the last sentence terminator if present | |
| for sep in ['. ', '... ', '? ', '! ']: | |
| if sep in shortened: | |
| shortened = shortened.rsplit(sep, 1)[0] + sep.strip() | |
| break | |
| return shortened | |
| try: | |
| completion = client.chat.completions.create( | |
| model=model, | |
| messages=[ | |
| {"role": "system", "content": "You are concise copywriter for TTS narration. Keep it friendly, natural, and short."}, | |
| {"role": "user", "content": prompt}, | |
| ], | |
| temperature=0.6, | |
| max_tokens=300, | |
| ) | |
| shortened = completion.choices[0].message.content or original_text | |
| return shortened.strip() | |
| except Exception: | |
| # Safe fallback | |
| words = original_text.split() | |
| return " ".join(words[:max_words]) | |
| def get_welcome_narration_prompt( | |
| topic: str, | |
| subtitle: str, | |
| user_name: Optional[str] = None, | |
| target_audience: str = "beginners" | |
| ) -> str: | |
| """ | |
| Returns a prompt specifically for generating an engaging welcome/introduction narration. | |
| This is ONLY for the first slide of the video. | |
| This prompt focuses on: | |
| - Warm, welcoming tone with greetings | |
| - Building excitement about the topic | |
| - Setting expectations for what they'll learn | |
| - Personal connection with the student | |
| """ | |
| personalization = f" The student's name is {user_name}." if user_name else "" | |
| greeting = f"Hello {user_name}! " if user_name else "Welcome! " | |
| return f"""You are creating the opening narration for an educational video. This is the FIRST thing the student will hear, so make it warm, welcoming, and exciting! | |
| VIDEO INFORMATION: | |
| Topic: {topic} | |
| Subtitle: {subtitle} | |
| Audience: {target_audience}{personalization} | |
| WELCOME NARRATION GUIDELINES: | |
| 1. WARM GREETING (REQUIRED): | |
| - Start with "{greeting}" | |
| - If user name provided: "Hello [name]! Welcome to..." | |
| - If no name: "Welcome! Today we're going to..." | |
| - Make it personal and friendly | |
| 2. BUILD EXCITEMENT: | |
| - Show enthusiasm: "I'm so excited to teach you about..." | |
| - Highlight what makes this topic interesting: "This is one of the most powerful concepts in programming..." | |
| - Use phrases like: "You're about to learn...", "Get ready to discover..." | |
| 3. SET EXPECTATIONS: | |
| - Briefly mention what they'll learn: "In this video, we'll cover..." | |
| - Keep it high-level and motivating | |
| - Make it feel achievable: "By the end, you'll be able to..." | |
| 4. TTS OPTIMIZATION: | |
| - Use commas (,) for brief pauses | |
| - Use ellipses (...) for anticipation | |
| - Use periods (.) for natural sentence endings | |
| - Keep it conversational and natural | |
| 5. TONE: | |
| - Friendly and encouraging | |
| - Enthusiastic but not overwhelming | |
| - Professional yet approachable | |
| - Like a knowledgeable friend starting a conversation | |
| 6. LENGTH: | |
| - Keep it concise: 40-80 words | |
| - This will be shortened to ~15 seconds | |
| - Focus on greeting + excitement + brief overview | |
| OUTPUT REQUIREMENTS: | |
| - MUST start with a greeting ("Welcome" or "Hello [name]") | |
| - Generate 3-5 sentences | |
| - Include strategic punctuation for natural TTS delivery | |
| - Sound warm, welcoming, and excited to teach | |
| - Make the student feel this will be a great learning experience | |
| Generate the welcome narration script now:""" | |