# gemini_handler.py import google.generativeai as genai import json import time import numpy as np import streamlit as st # --- Gemini API Setup --- try: GEMINI_API_KEY = st.secrets["GEMINI_API_KEY"] except: GEMINI_API_KEY = "AIzaSyCwEhM7qjRMEEIIpH79A_DlazXa5RozCSM" # Replace with your key genai.configure(api_key=GEMINI_API_KEY) GEMINI_MODEL = 'gemini-1.5-flash' # --- SAFEGUARDS (Improved) --- FALLBACK_PERSONAL_SWOT = { "Strengths": ["Unique perspective and background."], "Weaknesses": ["Consider areas for skill development."], "Opportunities": ["Leverage personal interests in emerging fields."], "Threats": ["Stay aware of the competitive landscape."] } FALLBACK_CAREER_SWOT = { "Strengths": ["AI analysis could not be completed at this time due to high server load. Please try again later."], "Weaknesses": ["Please check your internet connection and API key status."], "Opportunities": ["-"], "Threats": ["-"] } # --- MATHEMATICAL CORRELATION --- def recommend_careers_correlation(user_riasec, career_profiles): recommendations = [] riasec_order = ["Realistic", "Investigative", "Artistic", "Social", "Enterprising", "Conventional"] user_scores = np.array([user_riasec.get(key, 0) for key in riasec_order]) if np.std(user_scores) < 1e-6: sorted_clusters = sorted(list(career_profiles.keys())) return [(cluster, 0.0) for cluster in sorted_clusters] for career, profile in career_profiles.items(): career_scores = np.array([profile.get(key, 0) for key in riasec_order]) correlation_matrix = np.corrcoef(user_scores, career_scores) correlation = correlation_matrix[0, 1] if not np.isnan(correlation): recommendations.append((career, correlation)) recommendations.sort(key=lambda x: x[1], reverse=True) return recommendations # --- GEMINI API CALLS --- def get_personal_swot_analysis(user_data): system_instruction = "You are an insightful personal development coach. Analyze the user's profile. Your task is to create a personal SWOT analysis (Strengths, Weaknesses, Opportunities, Threats). Your response MUST be a valid JSON object. Each key must have a value that is a list of 2-3 concise, insightful bullet points (strings)." prompt = f"User Profile:\n{json.dumps(user_data, indent=2)}" try: model = genai.GenerativeModel(GEMINI_MODEL, system_instruction=system_instruction) response = model.generate_content(prompt) time.sleep(1) # Minimal delay is fine for single calls cleaned_response = response.text.strip().replace("```json", "").replace("```", "").strip() return json.loads(cleaned_response) except Exception as e: print(f"Error generating personal SWOT: {e}") return FALLBACK_PERSONAL_SWOT def get_ai_match_scores(user_data, cluster_list): system_instruction = "You are an expert career counselor AI. Given a user's detailed profile and a list of 10 career clusters, your task is to provide a final, holistic 'percentage match score' (an integer from 50 to 100) for each. This score MUST consider EVERYTHING in the user's profile. Your response MUST be ONLY a valid JSON object where keys are the career cluster names and values are the integer scores. DO NOT add any other text or formatting." prompt = f"User Profile:\n{json.dumps(user_data, indent=2)}\n\nCareer Cluster List to Score:\n{json.dumps(cluster_list)}" try: model = genai.GenerativeModel(GEMINI_MODEL, system_instruction=system_instruction) response = model.generate_content(prompt) time.sleep(1) cleaned_response = response.text.strip() scores = json.loads(cleaned_response) return {k: int(v) for k, v in scores.items()} except Exception as e: print(f"Error generating AI scores, returning random scores: {e}") return {cluster: np.random.randint(65, 95) for cluster in cluster_list} def get_career_swot_analysis_batch(user_data, cluster_list): """ NEW EFFICIENT FUNCTION: Gets SWOT for a list of careers in a single API call. """ system_instruction = f""" You are a career strategist AI. For the provided user profile, you must generate a SWOT-style analysis for EACH of the following career clusters: {', '.join(cluster_list)}. Your response MUST be a single, valid JSON object. The keys of this object will be the exact career cluster names. The value for each key will be another JSON object with four keys: "Strengths", "Weaknesses", "Opportunities", and "Threats". The value for each of these SWOT keys must be a list of concise bullet points (strings). NEVER fail to produce a valid JSON response. If information is lacking, provide generalized but helpful advice for that point. Example structure for your response: {{ "IT & Computer Science": {{ "Strengths": ["Point 1", "Point 2"], "Weaknesses": ["Point 1"], "Opportunities": ["Point 1", "Point 2"], "Threats": ["Point 1"] }}, "Medical Sciences": {{ "Strengths": ["Point 1"], "Weaknesses": ["Point 1", "Point 2"], "Opportunities": ["Point 1"], "Threats": ["Point 1", "Point 2"] }} }} """ prompt = f"User Profile:\n{json.dumps(user_data, indent=2)}" try: model = genai.GenerativeModel(GEMINI_MODEL, system_instruction=system_instruction) response = model.generate_content(prompt) time.sleep(1) cleaned_response = response.text.strip().replace("```json", "").replace("```", "").strip() return json.loads(cleaned_response) except Exception as e: print(f"Error generating batch career SWOT: {e}") # Return a fallback for each requested cluster return {cluster: FALLBACK_CAREER_SWOT for cluster in cluster_list}