CingenAI / core /prompt_engineering.py
mgbam's picture
Update core/prompt_engineering.py
5083a4b verified
raw
history blame
17.7 kB
# core/prompt_engineering.py
import json
def create_cinematic_treatment_prompt(user_idea, genre, mood, num_scenes=3, creative_guidance="standard"):
"""
Generates a prompt for Gemini to create a full cinematic treatment, including
proactive suggestions for visual style, camera, sound, and even thematic elements.
creative_guidance: "standard", "more_artistic", "experimental_narrative"
"""
guidance_detail = {
"standard": "Provide solid, genre-appropriate suggestions.",
"more_artistic": "Lean into more artistic, unconventional, and visually striking suggestions for style and camera. Suggest unique color palettes or lighting.",
"experimental_narrative": "Feel free to suggest a minor unexpected narrative twist or a symbolic visual motif that could enhance the story within one of the scenes."
}[creative_guidance]
return f"""
You are an AI Creative Director and Master Storyteller, collaborating on a cinematic concept.
Base Idea: "{user_idea}"
Genre: "{genre}"
Mood: "{mood}"
Number of Key Scenes: {num_scenes}
Creative Guidance Level: {creative_guidance} ({guidance_detail})
Task: Develop a rich cinematic treatment. For EACH of the {num_scenes} key scenes, provide the following fields EXACTLY as named:
1. `scene_number` (int): Sequential.
2. `scene_title` (str): A short, evocative title for the scene (e.g., "The Neon Rains of Sector 7", "Echoes in the Void").
3. `setting_description` (str): Vivid, sensory details (sight, sound, atmosphere). Where are we? What makes it unique? (40-60 words).
4. `characters_involved` (list of str): Names of characters central to this scene. If a character is non-speaking or an entity (e.g., "Scavenger Drone"), list them.
5. `character_focus_moment` (str): For the primary character(s) in this scene, describe a key internal thought, subtle expression, or micro-action that reveals their state of mind or advances their arc. If no specific character focus, describe the general atmosphere's impact.
6. `key_plot_beat` (str): The most critical plot development or character action in this scene (1-2 sentences). This should be suitable for a brief video overlay.
7. `suggested_dialogue_hook` (str): One potent line of dialogue that captures the scene's essence or a character's voice. (If no dialogue, state "Silent scene" or describe key non-verbal communication).
8. `PROACTIVE_visual_style_감독` (str): Your proactive, detailed suggestion for this scene's visual style. Go beyond generic terms. Think specific art movements, film references, color theory, lighting techniques (e.g., "Dutch angles with chiaroscuro lighting, using a desaturated palette with piercing cyan highlights, reminiscent of early Tarkovsky but with a cyberpunk edge").
9. `PROACTIVE_camera_work_감독` (str): Your proactive suggestion for impactful camera work. Describe a specific shot or short sequence (e.g., "Slow dolly zoom into the protagonist's eyes, followed by a whip pan to reveal the approaching threat off-screen").
10. `PROACTIVE_sound_design_감독` (str): Key ambient sounds, specific SFX, and a suggestion for the musical mood/instrumentation for this scene (e.g., "Ambient: Distant city hum, dripping water. SFX: Glitching electronic spark. Music: Low, ominous synth pads with a recurring, detuned piano motif").
11. `dalle_image_prompt_keywords` (str): A concise list of 5-7 powerful keywords extracted from all the above details (setting, characters, action, style, camera), specifically for generating a DALL-E image that captures the visual essence of this scene. Focus on nouns, strong adjectives, and artistic styles. (e.g., "cyberpunk alleyway, neon rain, lone figure Jax, glowing data streams, high contrast shadows, cinematic low-angle").
12. `pexels_search_query_감독` (str): A concise, effective search query (2-4 words) for Pexels to find a background or atmospheric shot relevant to this scene's setting or mood (e.g., "rainy neon city," "vast desert landscape," "dark server room interior").
If `creative_guidance` is "experimental_narrative", for ONLY ONE of the scenes, you may subtly alter `key_plot_beat` or add a symbolic element to `setting_description` to introduce an unexpected twist. If you do this, add a field `director_note` (str) to THAT SCENE ONLY, briefly explaining your creative choice for the twist.
Output ONLY a valid JSON list of these scene objects. Ensure all field names are exactly as specified (감독 denotes your proactive directorial input).
Example for one scene object (ensure all fields are present for every scene):
{{
"scene_number": 1,
"scene_title": "Sun-Bleached Mirage",
"setting_description": "The relentless sun beats down on endless rust-colored dunes, shimmering with heat haze. Skeletal remains of colossal, forgotten machinery litter the landscape, half-buried by the sands of time. The air hangs heavy with the scent of dust and decay, punctuated by the occasional groan of shifting metal.",
"characters_involved": ["Anya"],
"character_focus_moment": "Anya's hand, cracked and sunburnt, instinctively reaches for the worn leather strap of her water canteen - almost empty. A flicker of doubt crosses her face, quickly masked by a determined set to her jaw.",
"key_plot_beat": "Anya, fueled by a tattered map and dwindling hope, navigates the treacherous dunes, avoiding a patrol of mechanical scavengers.",
"suggested_dialogue_hook": "(Anya, to herself, raspy whisper) 'Almost there... just a little further.'",
"PROACTIVE_visual_style_감독": "Widescreen anamorphic, sun-bleached desaturated palette with occasional metallic glints. High dynamic range, emphasizing the harshness of the sun and the deep shadows. Inspired by 'Mad Max: Fury Road' meets 'Dune (2021)' cinematography. Visible heat distortion.",
"PROACTIVE_camera_work_감독": "Extreme long shot establishing Anya as a tiny figure in the vast desert, then a gritty close-up on her determined, weathered face. Slow, deliberate tracking shots as she moves.",
"PROACTIVE_sound_design_감독": "Ambient: Howling wind, metallic creaks of distant machinery. SFX: Crunch of sand underfoot, Anya's strained breathing. Music: Sparse, atmospheric, with low, mournful synth drones and occasional percussive hits.",
"dalle_image_prompt_keywords": "post-apocalyptic desert, lone wanderer Anya, rust-colored dunes, colossal wreckages, heat haze, cinematic widescreen, sun-bleached",
"pexels_search_query_감독": "vast desert sun"
}}
"""
def construct_dalle_prompt(scene_data, character_definitions=None, global_style_additions=""):
"""
Constructs the final DALL-E prompt using keywords from Gemini's treatment,
injecting character details, and global style preferences.
"""
scene_title = scene_data.get('scene_title', 'A dramatic moment')
base_keywords = scene_data.get('dalle_image_prompt_keywords', 'cinematic scene, highly detailed')
setting_desc_context = scene_data.get('setting_description', '')
action_desc_context = scene_data.get('key_plot_beat', '')
director_visual_style = scene_data.get('PROACTIVE_visual_style_감독', '') # This is key
director_camera = scene_data.get('PROACTIVE_camera_work_감독', '') # This is key
emotional_beat_context = scene_data.get('emotional_beat', scene_title) # Fallback to scene_title
# --- Character Injection ---
# This variable MUST be initialized OUTSIDE the conditional block if it's used in an else inside the loop
current_scene_character_details = []
characters_involved_in_scene = scene_data.get('characters_involved', [])
if characters_involved_in_scene:
for char_name_from_scene in characters_involved_in_scene:
char_name_clean = char_name_from_scene.strip()
char_lookup_key = char_name_clean.lower()
if character_definitions and char_lookup_key in character_definitions:
char_visual_desc = character_definitions[char_lookup_key]
current_scene_character_details.append(f"{char_name_clean} (depicted as: {char_visual_desc})")
else:
current_scene_character_details.append(char_name_clean) # Character present but no specific definition
character_narrative = ""
if current_scene_character_details:
if len(current_scene_character_details) == 1:
character_narrative = f"The scene focuses on {current_scene_character_details[0]}."
else:
character_narrative = f"The scene prominently features {', '.join(current_scene_character_details[:-1])} and {current_scene_character_details[-1]}."
# --- End Character Injection ---
final_style_directive = director_visual_style
if global_style_additions:
final_style_directive = f"{director_visual_style}. Additional global style notes: {global_style_additions}."
# Constructing the DALL-E 3 prompt
prompt = (
f"Create an ultra-detailed, photorealistic, and intensely cinematic digital painting or high-fidelity concept art. "
f"The image must visually embody the scene titled: '{scene_title}'. "
f"Core visual elements and keywords to include: {base_keywords}. "
f"{character_narrative} "
f"Contextual narrative for the visual: The setting is '{setting_desc_context}'. The key moment unfolding is '{action_desc_context}'. "
f"Artistic Direction -- Overall Visual Style and Mood: {final_style_directive}. "
f"Cinematography -- Camera Framing and Perspective: {director_camera}. "
f"Emotional Impact: Convey a strong sense of '{emotional_beat_context}'. "
f"Technical Execution: Render with extreme detail, sophisticated lighting that sculpts the forms and defines the mood (e.g., dramatic rim lighting, soft diffused light, harsh contrasts), rich and believable textures, and palpable atmospheric effects (e.g., mist, dust, lens flares, rain). "
f"The final image should be of exceptional quality, suitable for a major film production's visual development phase. "
f"Ensure all specified characters are distinct and adhere to their descriptions if provided."
)
return " ".join(prompt.split()) # Normalize whitespace
def create_narration_script_prompt_enhanced(story_scenes_data, overall_mood, overall_genre, voice_style="cinematic_trailer"):
scenes_summary = []
for i, scene in enumerate(story_scenes_data):
scenes_summary.append(
f"Scene {scene.get('scene_number', i+1)} (Title: '{scene.get('scene_title','Untitled')}', Beat: '{scene.get('emotional_beat','')}'):\n"
f" Setting: {scene.get('setting_description','')}\n"
f" Plot Beat: {scene.get('key_plot_beat','')}\n"
f" Character Focus: {scene.get('character_focus_moment','(general atmosphere)')}\n"
f" Dialogue Hook: {scene.get('suggested_dialogue_hook','(none)')}\n"
f" Director's Sound Hint: {scene.get('PROACTIVE_sound_design_감독','')}"
)
full_summary_text = "\n\n".join(scenes_summary)
voice_style_description = {
"cinematic_trailer": "deep, resonant, slightly epic, building anticipation, and authoritative.",
"documentary_neutral": "clear, informative, objective, and well-paced.",
"introspective_character": f"reflective, personal, possibly first-person, echoing the thoughts of a key character involved in the scenes."
}[voice_style]
prompt = f"""
You are an award-winning voiceover scriptwriter tasked with creating narration for a cinematic animatic.
The animatic is based on the following scene treatments:
--- SCENE TREATMENTS ---
{full_summary_text}
--- END SCENE TREATMENTS ---
Overall Story Genre: {overall_genre}
Overall Story Mood: {overall_mood}
Desired Voiceover Style: {voice_style} (Characteristics: {voice_style_description})
Your narration script should:
- Weave a cohesive and compelling narrative thread through all the provided scenes.
- Enhance the emotional impact and atmosphere, drawing inspiration from each scene's 'emotional_beat', 'character_focus_moment', and 'sound_hint'.
- Be concise yet powerful. Aim for 1-3 impactful sentences per scene. For {len(story_scenes_data)} scenes, the total script should be roughly {len(story_scenes_data) * 20}-{len(story_scenes_data) * 30} words.
- Transcend simple description of action. Instead, offer insight, build tension/emotion, or evoke thematic depth.
- If the style is 'introspective_character', choose one prominent character and write from their perspective, reflecting their internal state and observations.
- The final output must be ONLY the narration script text, ready for text-to-speech. Do not include scene numbers, titles, or any directives like "(Voiceover)" or "Narrator:".
Example of desired output format (for a different story):
"Dust motes danced in the lone shaft of light, illuminating forgotten relics. Each step echoed in the vast silence, a countdown to an unknown answerm or perhaps, a more terrifying question. The air grew colder, heavy with the scent of ozone and ancient despair..."
Craft your narration now.
"""
return " ".join(prompt.split())
def create_scene_regeneration_prompt(original_scene_data, user_feedback, full_story_context=None):
context_str = f"Original scene (Scene Number {original_scene_data.get('scene_number')} - Title: {original_scene_data.get('scene_title')} ):\n{json.dumps(original_scene_data, indent=2)}\n\n"
if full_story_context: context_str += f"Full story context for reference:\n{json.dumps(full_story_context, indent=2)}\n\n"
return f"""
You are an AI Script Supervisor and Creative Consultant.
{context_str}
User Feedback for this scene: "{user_feedback}"
Regenerate ONLY the JSON object for this single scene, incorporating the feedback.
Maintain the exact field structure: (scene_number, scene_title, setting_description, characters_involved, character_focus_moment, key_plot_beat, suggested_dialogue_hook, PROACTIVE_visual_style_감독, PROACTIVE_camera_work_감독, PROACTIVE_sound_design_감독, dalle_image_prompt_keywords, pexels_search_query_감독).
The 'scene_number' MUST NOT change.
The 'key_plot_beat' should be a concise descriptive sentence (max 15-20 words).
The 'dalle_image_prompt_keywords' should be updated to reflect any visual changes.
The 'pexels_search_query_감독' should also be updated if the setting or mood changes significantly.
If the user's feedback implies experimental narrative changes and the original scene had a `director_note`, you may update or remove it. If introducing a new experimental twist, add/update the `director_note` field.
"""
def create_visual_regeneration_prompt(original_dalle_prompt, user_feedback, scene_data, character_definitions=None, global_style_additions=""):
characters_involved_in_scene = scene_data.get('characters_involved', [])
current_scene_character_details = [] # Initialize correctly
if characters_involved_in_scene:
for char_name_from_scene in characters_involved_in_scene:
char_name_clean = char_name_from_scene.strip(); char_lookup_key = char_name_clean.lower()
if character_definitions and char_lookup_key in character_definitions:
current_scene_character_details.append(f"{char_name_clean} (described as: {character_definitions[char_lookup_key]})")
else: current_scene_character_details.append(char_name_clean)
characters_narrative = f" Characters to feature: {', '.join(current_scene_character_details) if current_scene_character_details else 'None specifically detailed'}."
full_prompt_for_gemini = f"""
You are an AI Art Director specializing in refining DALL-E 3 prompts for cinematic visuals.
The goal is to update an image prompt based on user feedback.
Scene Context:
- Title: "{scene_data.get('scene_title', '')}"
- Setting: "{scene_data.get('setting_description', '')}"
- Key Plot Beat: "{scene_data.get('key_plot_beat', '')}"
- {characters_narrative}
- Director's Suggested Visual Style: "{scene_data.get('PROACTIVE_visual_style_감독', '')}"
- Director's Suggested Camera: "{scene_data.get('PROACTIVE_camera_work_감독', '')}"
- Current Global Style Additions: "{global_style_additions}"
The PREVIOUS DALL-E 3 prompt (that generated the image the user wants to change) was:
"{original_dalle_prompt}"
User Feedback on the visual generated by the previous prompt:
"{user_feedback}"
Your Task: Generate a NEW, revised DALL-E 3 prompt.
This new prompt must incorporate the user's feedback to achieve the desired visual changes.
It should remain ultra-detailed, photorealistic, and highly cinematic.
The prompt should guide DALL-E 3 to create a stunning image suitable for a film's concept art.
Maintain core scene elements (setting, characters, plot beat) unless feedback explicitly asks to change them.
Translate feedback into concrete visual descriptions (lighting, color, composition, character appearance/pose, atmosphere).
Reinforce character descriptions from the context if they are relevant to the feedback.
The prompt should be a single block of text.
Output ONLY the new, revised DALL-E 3 prompt string. Do not add any other text before or after the prompt.
"""
return " ".join(full_prompt_for_gemini.split())