import gradio as gr import os import json from openai import OpenAI from dotenv import load_dotenv # Load environment variables load_dotenv() api_key = os.getenv("OPENAI_API_KEY") # Initialize OpenAI client client = OpenAI(api_key=api_key) # Define the base careers directory base_careers_dir = "careers" # Ensure the base careers directory exists os.makedirs(base_careers_dir, exist_ok=True) prompt_template = """ Generate a detailed JSON object representing a career card for a {career}. The JSON structure should match the provided IPS Officer example, covering the following sections: 1. "CareerCard": - "Title": The career name (e.g., Doctor, Software Developer, Teacher). - "Enabled": Set to 1 (indicating the card is available). - "ImageMale": A relevant image path for a male character (e.g., "images/careers/doctor/doctor_male.jpg"). - "ImageFemale": A relevant image path for a female character (e.g., "images/careers/doctor/doctor_female.jpg"). - "Overview": A detailed, gender-inclusive description (3-4 sentences) explaining the career's primary role, responsibilities, and importance. - "Benefits and Challenges": - "Benefits": A list of at least **4 positive aspects** of this career (e.g., job security, personal growth). - "Job Challenges": A list of at least **4 difficulties** or challenges (e.g., stress, work-life balance). - "Dual Impact Highlights": - "Personal Growth": Describe how this career enhances **personal development** (skills, knowledge, personal fulfillment). - "Community Impact": Explain how this career **benefits society** or the broader community. - "Choices": Provide **two decision options** that reflect different approaches to the career. Each option should: - "Option": A choice description. One should focus on **maximizing personal growth**, and the other on **balancing personal and community impact**. - "PersonalImpact": A score between 1-5 for how much this option enhances personal growth. - "CommunityImpact": A score between 1-5 for how much this option helps the community. - "Result": A description of the **outcome** of choosing this path. 2. "Scenarios": Provide **two real-world scenarios** for this career. Each scenario must: - "Title": A short, engaging title (e.g., "Emergency Surgery Crisis"). - "Audio": A path to a scenario-related sound (e.g., "audio/doctor/emergency_room.mp3"). - "BackgroundImage": A path to a scenario-related image (e.g., "images/careers/doctor/emergency_room.jpg"). - "Description": A detailed, gender-neutral narrative (3-5 sentences) presenting a realistic challenge faced by professionals in this career. - "DecisionCards": Two decision options for handling the scenario, each with: - "Option": The action the player can choose (e.g., "Perform emergency surgery"). - "Outcomes": - "PersonalImpact": A score (1-7) representing the effect on personal development. - "CommunityImpact": A score (1-7) representing the effect on the community. 3. "Result": Define the final outcomes based on the player’s total score. Include: - "Achieved": Message for a **high score** (e.g., "You've become a respected leader in your field!"). - "AchievedImage": "images/careers/{career}/achieved_{career}.jpg", - "Moderate": Message for a **moderate score** (e.g., "You've made a solid impact but can achieve more."). - "ModerateImage": "images/careers/{career}/moderate_{career}.jpg", - "Retry": Message for a **low score** (e.g., "Your journey ends here… but you can try again!"). - "RetryImage": "images/careers/{career}/retry_{career}.jpg", - "Quit": "Game Over!", - "QuitImage": "images/careers/{career}/game_over.jpg", Ensure the JSON is properly formatted and adheres to the structure exactly. Generate unique and creative responses for each section while maintaining consistency across different careers and all three gender representations. """ def generate_career_profile(career, job_category, gender): # Map gender to image key and label gender_map = { "Male": ("Male", "male"), "Female": ("Female", "female"), "Neutral": ("Neutral", "neutral") } gender_label, gender_key = gender_map[gender] # Define the prompt prompt = prompt_template.format( career=career, career_lower=career.replace(" ", "_").lower(), gender=gender_key, gender_label=gender_label ) # Generate the JSON response response = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "You are an AI that generates structured career profiles in JSON format."}, {"role": "user", "content": prompt}, ], ) # Debugging: Print the response print("Response from OpenAI:", response) # Extract and clean response content if response.choices: content = response.choices[0].message.content.strip() # Remove possible markdown formatting if content.startswith("```json"): content = content[7:-3].strip() try: career_profile = json.loads(content) # Convert string to JSON # Define the category-specific directory path category_dir = os.path.join(base_careers_dir, job_category) os.makedirs(category_dir, exist_ok=True) # Ensure the category directory exists # Define the file path file_path = os.path.join(category_dir, f"{career.replace(' ', '_').lower()}_{gender_key}.json") # Save the JSON to a file with open(file_path, "w", encoding="utf-8") as f: json.dump(career_profile, f, indent=4) # Return the file path so that Gradio displays a downloadable file. return file_path except json.JSONDecodeError: return "Error: Failed to parse OpenAI response into JSON." return "Error: OpenAI API response did not contain the expected content." # Define the Gradio interface with a file output for download iface = gr.Interface( fn=generate_career_profile, inputs=[ gr.Textbox(label="Job Profile Name"), gr.Dropdown( label="Job Category", choices=["Education", "Technology", "Healthcare", "Hospitality", "Finance", "Marketing", "Engineering", "Arts and Design", "Legal", "Science and Research", "Civil Services"], type="value", ), gr.Dropdown( label="Gender", choices=["Male", "Female", "Neutral"], type="value", ), ], outputs=gr.File(label="Career Profile JSON"), live=False ) # Launch the interface iface.launch()