import gradio as gr import random import tempfile import os from reportlab.lib.pagesizes import letter from reportlab.pdfgen import canvas from huggingface_hub import InferenceClient # Assuming generate_cinematic_prompt, clear_inputs, random_inputs, and download_prompt_file functions are defined in previous cells # The generate_cinematic_prompt function is already defined and includes validation and LM integration. # The download_prompt_file function is already defined. # The clear_inputs and random_inputs functions are already defined. # Replace 'YOUR_HF_API_TOKEN' with your actual token, or set the HF_API_TOKEN environment variable. # It's recommended to set the HF_API_TOKEN environment variable. hf_api_token = os.environ.get("HF_API_TOKEN", "hf_YOUR_HF_API_TOKEN") client = None # Initialize client to None if hf_api_token == "hf_YOUR_HF_API_TOKEN": print("Warning: Hugging Face API token is not set correctly. Using a placeholder. Please set the HF_API_TOKEN environment variable or replace the placeholder.") # Attempt to use a public model without authentication for demonstration purposes if no token is set try: # Using a commonly available public model client = InferenceClient(model="HuggingFaceH4/zephyr-7b-beta") # Specify a public model print("Attempting to use a public model without authentication.") except Exception as e: print(f"Failed to initialize InferenceClient without authentication: {e}") client = None # Set client to None if initialization fails else: try: client = InferenceClient(token=hf_api_token) print("Hugging Face InferenceClient initialized with provided token.") except Exception as e: print(f"Failed to initialize InferenceClient with token: {e}") client = None # Set client to None if initialization fails def generate_cinematic_prompt( genre, mood, visual_style, aesthetic, environment, lighting, location, color_tones, camera_angle, atmosphere ): """ Generate a detailed cinematic prompt using a language model based on user selections. Includes input validation for Location and uses the InferenceClient to generate text. Adjusted prompt template and parameters for improved quality. """ # Define environments that require a location environments_requiring_location = ["Futuristic City", "Enchanted Forest", "Haunted Mansion", "Cozy Cafe"] # Input validation for Location if environment in environments_requiring_location and not location: return f"Error: The selected environment '{environment}' requires a specific location. Please enter a location." if client is None: return "Error: Hugging Face InferenceClient is not initialized. Please check your API token or environment setup." # Construct a more detailed and directive prompt for the language model # Experimenting with phrasing and structure prompt_template = ( f"Generate a vivid cinematic scene description. Focus on sensory details and atmosphere.\n\n" f"Include these elements:\n" f"- Genre: {genre}\n" f"- Mood: {mood}\n" f"- Visual Style: {visual_style}\n" f"- Aesthetic: {aesthetic}\n" f"- Environment: {environment}" ) if location: prompt_template += f"\n- Location: {location}" prompt_template += ( f"\n- Lighting: {lighting}\n" f"- Color Tones: {color_tones}\n" f"- Camera Angle: {camera_angle}\n" f"- Atmosphere: {atmosphere}\n\n" f"Write a detailed paragraph (around 150-200 words) that captures the essence of this scene. Begin by setting the environment and describing the lighting. Ensure the description is cinematic and evokes the chosen mood and aesthetic." ) try: # Use the InferenceClient to generate text # Adjusting max_new_tokens for potentially longer, more detailed output generated_text = client.text_generation(prompt_template, max_new_tokens=300, temperature=0.7, repetition_penalty=1.2) # Post-process the generated text # Removing common unwanted leading/trailing characters or phrases processed_text = generated_text.strip() # Example: Remove potential conversational filler from the model if processed_text.lower().startswith("here is a cinematic scene description:"): processed_text = processed_text[len("here is a cinematic scene description:"):].strip() # Add more post-processing rules based on observed model output if not processed_text: # Fallback to the original function's prompt generation if LM returns empty print("Language model returned empty response. Falling back to original prompt generation.") prompt_parts = [] prompt_parts.append( f"A {mood.lower()} {genre.lower()} scene in the style of {aesthetic}." ) prompt_parts.append( f"The visual style is {visual_style.lower()} with {color_tones.lower()}." ) if location: prompt_parts.append( f"Set in a {environment.lower()} environment, located in {location}." ) else: prompt_parts.append( f"Set in a {environment.lower()} environment." ) prompt_parts.append( f"Lit with {lighting.lower()}, creating an atmosphere of {atmosphere.lower()}." ) prompt_parts.append( f"Captured using a {camera_angle.lower()}, creating a {mood.lower()} atmosphere for maximum cinematic effect." ) processed_text = " ".join(prompt_parts) return processed_text except Exception as e: print(f"Error during language model text generation: {e}") # Return an error message or fallback to the original function's prompt generation # Fallback to the original function's prompt generation on error print("Error using language model. Falling back to original prompt generation.") prompt_parts = [] prompt_parts.append( f"A {mood.lower()} {genre.lower()} scene in the style of {aesthetic}." ) prompt_parts.append( f"The visual style is {visual_style.lower()} with {color_tones.lower()}." ) if location: prompt_parts.append( f"Set in a {environment.lower()} environment, located in {location}." ) else: prompt_parts.append( f"Set in a {environment.lower()} environment." ) prompt_parts.append( f"Lit with {lighting.lower()}, creating an atmosphere of {atmosphere.lower()}." ) prompt_parts.append( f"Captured using a {camera_angle.lower()}, creating a {mood.lower()} atmosphere for maximum cinematic effect." ) return " ".join(prompt_parts) def clear_inputs(): """Clears all input and output fields in the interface.""" return { genre_dropdown: None, mood_dropdown: None, visual_style_dropdown: None, aesthetic_dropdown: None, environment_dropdown: None, location_dropdown: None, lighting_dropdown: None, color_tones_dropdown: None, camera_angle_dropdown: None, atmosphere_dropdown: None, output_text: "", download_format_radio: None # Set to None to clear the selection } def random_inputs(): """Generates random selections for all input fields.""" print("random_inputs function called") # Debug print genres = ["Sci-Fi", "Fantasy", "Horror", "Action", "Drama", "Comedy", "Quranic Verse", "Spiritual", "Islamic"] moods = ["Mysterious", "Epic", "Terrifying", "Susenseful", "Emotional", "Humorous"] visual_styles = ["Cyberpunk", "Steampunk", "Noir", "Gritty", "Surreal", "Minimalist"] aesthetics = ["Denis Villeneuve Style", "Tim Burton Style", "Quentin Tarantino Style", "Wes Anderson Style", "Ridley Scott Style", "Quranic Verse", "Spiritual", "Islamic"] environments = ["Futuristic City", "Enchanted Forest", "Haunted Mansion", "Desert Landscape", "Cozy Cafe", "Alien Planet"] lightings = ["Neon Lighting", "Candlelight", "Moonlight", "Harsh Sunlight", "Soft Glow", "Eerie Shadows"] color_tones_choices = ["Vibrant Colors", "Monochromatic", "Pastel Palette", "Dark and Moody", "Warm Tones", "Cool Tones"] camera_angles = ["Low Angle", "High Angle", "Dutch Angle", "Close-up", "Wide Shot", "Over the Shoulder"] atmospheres = ["Rain", "Foggy", "Sunny", "Snowy", "Windy", "Quiet"] # Define a combined list of all possible locations all_locations = ["Neon Alley", "Skyline Rooftop", "Underground Market", "Cybernetic Lab", "Whispering Woods", "Crystal Clear Stream", "Ancient Oak Glade", "Hidden Waterfall", "Grand Ballroom", "Dusty Library", "Creepy Attic", "Spooky Cellar", "Sand Dunes", "Oasis", "Canyon", "Ancient Ruins", "Window Seat", "Corner Booth", "Outdoor Patio", "Bar Counter", "Crater Lake", "Crystal Caves", "Volcanic Plains", "Floating Islands"] random_genre = random.choice(genres) random_mood = random.choice(moods) random_visual_style = random.weights(visual_styles, weights=[3, 1, 2, 2, 1, 1])[0] random_aesthetic = random.choice(aesthetics) random_environment = random.choice(environments) random_location = random.choice(all_locations) # Select a random location from the combined list random_lighting = random.choice(lightings) random_color_tones = random.choice(color_tones_choices) random_camera_angle = random.choice(camera_angles) random_atmosphere = random.choice(atmospheres) print(f"Randomly selected values: Genre={random_genre}, Mood={random_mood}, Environment={random_environment}, Location={random_location}, Visual Style={random_visual_style}, Aesthetic={random_aesthetic}, Lighting={random_lighting}, Color Tones={random_color_tones}, Camera Angle={random_camera_angle}, Atmosphere={random_atmosphere}") # Debug print return { genre_dropdown: random_genre, mood_dropdown: random_mood, visual_style_dropdown: random_visual_style, aesthetic_dropdown: random_aesthetic, environment_dropdown: random_environment, location_dropdown: random_location, lighting_dropdown: random_lighting, color_tones_dropdown: random_color_tones, camera_angle_dropdown: random_camera_angle, atmosphere_dropdown: random_atmosphere } def download_prompt_file(prompt_text, format_choice): """Generates a temporary file (text or PDF) containing the prompt text and returns the path.""" if not prompt_text or prompt_text.startswith("Error:"): print("No prompt text to download or it is an error message.") return None try: if format_choice == "Text": print("Creating temporary text file.") with tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="w", encoding="utf-8") as tmp_file: tmp_file.write(prompt_text) file_path = tmp_file.name print(f"Temporary text file created at: {file_path}") return file_path elif format_choice == "PDF": with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_file: file_path = tmp_file.name c = canvas.Canvas(file_path, pagesize=letter) textobject = c.beginText() textobject.setTextOrigin(50, 750) lines = prompt_text.split('\n') for line in lines: textobject.textLine(line) c.drawText(textobject) c.save() print(f"Temporary PDF file created at: {file_path}") return file_path else: print(f"Unknown format choice: {format_choice}") return None except Exception as e: print(f"Error during file generation: {e}") return None # Keep the get_locations_for_environment function, but it will no longer be directly linked to the environment dropdown's change event for updating choices. def get_locations_for_environment(environment): """Returns a list of locations based on the selected environment.""" print(f"Environment selected: {environment}") # Debug print location_map = { "Futuristic City": ["Neon Alley", "Skyline Rooftop", "Underground Market", "Cybernetic Lab"], "Enchanted Forest": ["Whispering Woods", "Crystal Clear Stream", "Ancient Oak Glade", "Hidden Waterfall"], "Haunted Mansion": ["Grand Ballroom", "Dusty Library", "Creepy Attic", "Spooky Cellar"], "Desert Landscape": ["Sand Dunes", "Oasis", "Canyon", "Ancient Ruins"], "Cozy Cafe": ["Window Seat", "Corner Booth", "Outdoor Patio", "Bar Counter"], "Alien Planet": ["Crater Lake", "Crystal Caves", "Volcanic Plains", "Floating Islands"] } locations = location_map.get(environment, []) # Return empty list if environment not found print(f"Returning locations: {locations}") # Debug print return locations custom_css = """ /* Add your custom CSS here */ h2 { color: #3366ff; /* Example: Change the color of h2 headings */ } """ with gr.Blocks(theme=gr.themes.Soft(), css=custom_css) as interface: # Apply a theme and custom CSS gr.Markdown("## Cinematic Prompt Generator") gr.Markdown("Generate a cinematic prompt based on your selections.") with gr.Tabs(): with gr.TabItem("Core Elements"): genre_dropdown = gr.Dropdown( label="Genre", choices=["Sci-Fi", "Fantasy", "Horror", "Action", "Drama", "Comedy", "Quranic Verse", "Spiritual", "Islamic"], info="Select the primary genre of the cinematic scene." ) mood_dropdown = gr.Dropdown( label="Mood", choices=["Mysterious", "Epic", "Terrifying", "Susenseful", "Emotional", "Humorous"], info="Choose the overall emotional tone of the scene." ) with gr.TabItem("Visuals"): visual_style_dropdown = gr.Dropdown( label="Visual Style", choices=["Cyberpunk", "Steampunk", "Noir", "Gritty", "Surreal", "Minimalist"], info="Define the artistic and visual approach." ) aesthetic_dropdown = gr.Dropdown( label="Aesthetic", choices=["Denis Villeneuve Style", "Tim Burton Style", "Quentin Tarantino Style", "Wes Anderson Style", "Ridley Scott Style", "Quranic Verse", "Spiritual", "Islamic"], info="Specify a director or style to emulate." ) color_tones_dropdown = gr.Dropdown( label="Color Tones", choices=["Vibrant Colors", "Monochromatic", "Pastel Palette", "Dark and Moody", "Warm Tones", "Cool Tones"], info="Set the dominant color scheme." ) with gr.TabItem("Setting"): environment_dropdown = gr.Dropdown( label="Environment", choices=["Futuristic City", "Enchanted Forest", "Haunted Mansion", "Desert Landscape", "Cozy Cafe", "Alien Planet"], info="Select the general setting for the scene." ) # Use a static list for location choices location_dropdown = gr.Dropdown( label="Location", choices=["Neon Alley", "Skyline Rooftop", "Underground Market", "Cybernetic Lab", "Whispering Woods", "Crystal Clear Stream", "Ancient Oak Glade", "Hidden Waterfall", "Grand Ballroom", "Dusty Library", "Creepy Attic", "Spooky Cellar", "Sand Dunes", "Oasis", "Canyon", "Ancient Ruins", "Window Seat", "Corner Booth", "Outdoor Patio", "Bar Counter", "Crater Lake", "Crystal Caves", "Volcanic Plains", "Floating Islands"], info="Select a specific location within the environment." ) lighting_dropdown = gr.Dropdown( label="Lighting", choices=["Neon Lighting", "Candlelight", "Moonlight", "Harsh Sunlight", "Soft Glow", "Eerie Shadows"], info="Describe the lighting conditions." ) with gr.TabItem("Composition & Atmosphere"): camera_angle_dropdown = gr.Dropdown( label="Camera Angle", choices=["Low Angle", "High Angle", "Dutch Angle", "Close-up", "Wide Shot", "Over the Shoulder"], info="Choose the camera's perspective." ) atmosphere_dropdown = gr.Dropdown( label="Atmosphere", choices=["Rain", "Foggy", "Sunny", "Snowy", "Windy", "Quiet"], info="Define the prevailing weather or environmental feel." ) with gr.TabItem("About/Instructions"): gr.Markdown( """ ## About the Cinematic Prompt Generator This tool helps you generate detailed cinematic prompts for creative writing, visual art, or any project requiring scene descriptions. ### How to Use: 1. **Select Options:** Choose a value from each of the dropdown menus under the "Core Elements", "Visuals", "Setting", and "Composition & Atmosphere" tabs. 2. **Select Location:** Choose a location from the dropdown. Note that this dropdown now contains all possible locations and does not change based on the Environment selection. 3. **Generate Prompt:** Click the "Generate Prompt" button to create your cinematic scene description. 4. **Clear Inputs:** Click the "Clear" button to reset all input fields and the generated prompt. 5. **Random Inputs:** Click the "Random" button to populate the input fields with random selections. 6. **Download Prompt:** Select your desired format (Text or PDF) using the "Download Format" radio buttons, and then click the "Download" button to save the generated prompt to your computer. 7. **Copy Prompt:** Use the copy button next to the generated prompt textbox to quickly copy the text to your clipboard. The generated prompts are designed to be a starting point, feel free to modify and expand upon them! """ ) with gr.Row(): generate_button = gr.Button("Generate Prompt") clear_button = gr.Button("Clear") random_button = gr.Button("Random") download_button = gr.Button("Download") download_format_radio = gr.Radio( ["Text", "PDF"], label="Download Format", value=None, # Explicitly set default value to None info="Choose the file format for download." ) output_text = gr.Textbox(label="Generated Prompt", show_copy_button=True) download_file = gr.File(label="Download Prompt") # Remove the dynamic link for environment_dropdown change # environment_dropdown.change( # fn=get_locations_for_environment, # inputs=environment_dropdown, # outputs=location_dropdown # ) generate_button.click( fn=generate_cinematic_prompt, inputs=[ genre_dropdown, mood_dropdown, visual_style_dropdown, aesthetic_dropdown, environment_dropdown, lighting_dropdown, location_dropdown, color_tones_dropdown, camera_angle_dropdown, atmosphere_dropdown ], outputs=output_text ) clear_button.click( fn=clear_inputs, inputs=[], outputs=[ genre_dropdown, mood_dropdown, visual_style_dropdown, aesthetic_dropdown, environment_dropdown, location_dropdown, lighting_dropdown, color_tones_dropdown, camera_angle_dropdown, atmosphere_dropdown, output_text, download_format_radio ] ) random_button.click( fn=random_inputs, inputs=[], outputs=[ genre_dropdown, mood_dropdown, visual_style_dropdown, aesthetic_dropdown, environment_dropdown, location_dropdown, lighting_dropdown, color_tones_dropdown, camera_angle_dropdown, atmosphere_dropdown ] ) download_button.click( fn=download_prompt_file, inputs=[output_text, download_format_radio], outputs=download_file ) if __name__ == "__main__": interface.launch(show_api=False) # Removed show_share_button=False as it's not valid for gr.Blocks