|
import gradio as gr |
|
import pandas as pd |
|
import numpy as np |
|
import matplotlib.pyplot as plt |
|
import plotly.graph_objects as go |
|
import plotly.express as px |
|
from datetime import datetime, timedelta |
|
import random |
|
import json |
|
import os |
|
import time |
|
import requests |
|
from typing import List, Dict, Any, Optional |
|
import logging |
|
from dotenv import load_dotenv |
|
import pytz |
|
import uuid |
|
import google.generativeai as genai |
|
from google.generativeai.types import HarmCategory, HarmBlockThreshold |
|
from google.generativeai.types import Tool, FunctionDeclaration, GenerateContentConfig |
|
|
|
|
|
load_dotenv() |
|
|
|
|
|
logging.basicConfig(level=logging.INFO, |
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s') |
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "your-gemini-api-key") |
|
SERPER_API_KEY = os.getenv("SERPER_API_KEY", "your-serper-api-key") |
|
|
|
|
|
genai.configure(api_key=GEMINI_API_KEY) |
|
|
|
|
|
EMOTIONS = ["Unmotivated", "Anxious", "Confused", "Excited", "Overwhelmed", "Discouraged"] |
|
GOAL_TYPES = ["Get a job at a big company", "Find an internship", "Change careers", "Improve skills", "Network better"] |
|
USER_DB_PATH = "user_database.json" |
|
|
|
|
|
model = genai.GenerativeModel( |
|
model_name="gemini-2.0-flash", |
|
generation_config={ |
|
"temperature": 0.7, |
|
"top_p": 0.95, |
|
"top_k": 40, |
|
"max_output_tokens": 2048, |
|
}, |
|
safety_settings={ |
|
HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_ONLY_HIGH, |
|
HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_ONLY_HIGH, |
|
HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_ONLY_HIGH, |
|
HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_ONLY_HIGH, |
|
} |
|
) |
|
|
|
|
|
search_jobs = FunctionDeclaration( |
|
name="search_jobs", |
|
description="Search for job opportunities based on location and career goals", |
|
parameters={ |
|
"type": "OBJECT", |
|
"properties": { |
|
"location": { |
|
"type": "STRING", |
|
"description": "The city or country where the user is located", |
|
}, |
|
"career_goal": { |
|
"type": "STRING", |
|
"description": "The user's career goal or job interest", |
|
}, |
|
"max_results": { |
|
"type": "NUMBER", |
|
"description": "Maximum number of job opportunities to return", |
|
}, |
|
}, |
|
"required": ["location", "career_goal"], |
|
}, |
|
) |
|
|
|
generate_document = FunctionDeclaration( |
|
name="generate_document_template", |
|
description="Generate a document template for job applications", |
|
parameters={ |
|
"type": "OBJECT", |
|
"properties": { |
|
"document_type": { |
|
"type": "STRING", |
|
"description": "Type of document to generate (Resume, Cover Letter, Self-introduction)", |
|
}, |
|
"career_field": { |
|
"type": "STRING", |
|
"description": "The career field or industry the document is for", |
|
}, |
|
"experience_level": { |
|
"type": "STRING", |
|
"description": "User's experience level (Entry, Mid, Senior)", |
|
}, |
|
}, |
|
"required": ["document_type"], |
|
}, |
|
) |
|
|
|
create_routine = FunctionDeclaration( |
|
name="create_personalized_routine", |
|
description="Create a personalized career development routine", |
|
parameters={ |
|
"type": "OBJECT", |
|
"properties": { |
|
"emotion": { |
|
"type": "STRING", |
|
"description": "User's current emotional state", |
|
}, |
|
"goal": { |
|
"type": "STRING", |
|
"description": "User's career goal", |
|
}, |
|
"available_time_minutes": { |
|
"type": "NUMBER", |
|
"description": "Available time in minutes per day", |
|
}, |
|
"routine_length_days": { |
|
"type": "NUMBER", |
|
"description": "Length of routine in days", |
|
}, |
|
}, |
|
"required": ["emotion", "goal"], |
|
}, |
|
) |
|
|
|
tools = [ |
|
Tool(function_declarations=[search_jobs]), |
|
Tool(function_declarations=[generate_document]), |
|
Tool(function_declarations=[create_routine]) |
|
] |
|
|
|
|
|
def load_user_database(): |
|
"""Load user database from JSON file or create if it doesn't exist""" |
|
try: |
|
with open(USER_DB_PATH, 'r') as file: |
|
return json.load(file) |
|
except (FileNotFoundError, json.JSONDecodeError): |
|
|
|
db = {'users': {}} |
|
save_user_database(db) |
|
return db |
|
|
|
def save_user_database(db): |
|
"""Save user database to JSON file""" |
|
with open(USER_DB_PATH, 'w') as file: |
|
json.dump(db, file, indent=4) |
|
|
|
def get_user_profile(user_id): |
|
"""Get user profile from database or create new one""" |
|
db = load_user_database() |
|
if user_id not in db['users']: |
|
db['users'][user_id] = { |
|
"user_id": user_id, |
|
"name": "", |
|
"location": "", |
|
"current_emotion": "", |
|
"career_goal": "", |
|
"progress_points": 0, |
|
"completed_tasks": [], |
|
"upcoming_events": [], |
|
"routine_history": [], |
|
"daily_emotions": [], |
|
"joined_date": datetime.now().strftime("%Y-%m-%d") |
|
} |
|
save_user_database(db) |
|
return db['users'][user_id] |
|
|
|
def update_user_profile(user_id, updates): |
|
"""Update user profile with new information""" |
|
db = load_user_database() |
|
if user_id in db['users']: |
|
for key, value in updates.items(): |
|
db['users'][user_id][key] = value |
|
save_user_database(db) |
|
return db['users'][user_id] |
|
|
|
def add_task_to_user(user_id, task): |
|
"""Add a new task to user's completed tasks""" |
|
db = load_user_database() |
|
if user_id in db['users']: |
|
if 'completed_tasks' not in db['users'][user_id]: |
|
db['users'][user_id]['completed_tasks'] = [] |
|
|
|
task_with_date = { |
|
"task": task, |
|
"date": datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
} |
|
db['users'][user_id]['completed_tasks'].append(task_with_date) |
|
db['users'][user_id]['progress_points'] += random.randint(10, 25) |
|
save_user_database(db) |
|
return db['users'][user_id] |
|
|
|
def add_emotion_record(user_id, emotion): |
|
"""Add a new emotion record to user's daily emotions""" |
|
db = load_user_database() |
|
if user_id in db['users']: |
|
if 'daily_emotions' not in db['users'][user_id]: |
|
db['users'][user_id]['daily_emotions'] = [] |
|
|
|
emotion_record = { |
|
"emotion": emotion, |
|
"date": datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
} |
|
db['users'][user_id]['daily_emotions'].append(emotion_record) |
|
db['users'][user_id]['current_emotion'] = emotion |
|
save_user_database(db) |
|
return db['users'][user_id] |
|
|
|
def add_routine_to_user(user_id, routine): |
|
"""Add a new routine to user's routine history""" |
|
db = load_user_database() |
|
if user_id in db['users']: |
|
if 'routine_history' not in db['users'][user_id]: |
|
db['users'][user_id]['routine_history'] = [] |
|
|
|
routine_with_date = { |
|
"routine": routine, |
|
"start_date": datetime.now().strftime("%Y-%m-%d"), |
|
"end_date": (datetime.now() + timedelta(days=routine.get('days', 7))).strftime("%Y-%m-%d"), |
|
"completion": 0 |
|
} |
|
db['users'][user_id]['routine_history'].append(routine_with_date) |
|
save_user_database(db) |
|
return db['users'][user_id] |
|
|
|
|
|
def search_jobs_with_serper(query, location, max_results=5): |
|
"""Search for job opportunities using Serper API""" |
|
try: |
|
headers = { |
|
'X-API-KEY': SERPER_API_KEY, |
|
'Content-Type': 'application/json' |
|
} |
|
|
|
params = { |
|
'q': f"{query} jobs in {location}", |
|
'num': max_results |
|
} |
|
|
|
response = requests.get( |
|
'https://serper.dev/search', |
|
headers=headers, |
|
params=params |
|
) |
|
|
|
if response.status_code == 200: |
|
data = response.json() |
|
|
|
job_results = [] |
|
|
|
|
|
if 'organic' in data: |
|
for item in data['organic']: |
|
if 'title' in item and 'link' in item and 'snippet' in item: |
|
|
|
if any(keyword in item['title'].lower() for keyword in ['job', 'career', 'position', 'hiring', 'work']): |
|
job_results.append({ |
|
'title': item['title'], |
|
'company': extract_company_from_title(item['title']), |
|
'description': item['snippet'], |
|
'link': item['link'], |
|
'location': location, |
|
'date_posted': 'Recent' |
|
}) |
|
|
|
return job_results |
|
else: |
|
logger.error(f"Error from Serper API: {response.status_code} - {response.text}") |
|
return [] |
|
except Exception as e: |
|
logger.error(f"Exception in search_jobs_with_serper: {str(e)}") |
|
return [] |
|
|
|
def extract_company_from_title(title): |
|
"""Extract company name from job title if possible""" |
|
|
|
if ' at ' in title: |
|
return title.split(' at ')[1].strip() |
|
if ' - ' in title: |
|
return title.split(' - ')[1].strip() |
|
return "Unknown Company" |
|
|
|
def get_ai_response(user_id, user_input, context=None): |
|
"""Get AI response using Google Gemini API""" |
|
try: |
|
user_profile = get_user_profile(user_id) |
|
|
|
system_instruction = """ |
|
You are Aishura, an emotionally intelligent AI career assistant. Your goal is to empathize with the user's emotions |
|
and provide realistic information and actionable suggestions. Follow this structure: |
|
1. Recognize and acknowledge the user's emotion |
|
2. Respond with high-empathy message |
|
3. Suggest specific action based on their input |
|
4. Offer document support or routine |
|
|
|
Remember to be proactive and preemptive - suggest actions before the user asks. |
|
""" |
|
|
|
|
|
messages = [] |
|
if context: |
|
messages.extend(context) |
|
|
|
|
|
profile_context = f""" |
|
User Profile Information: |
|
- Current emotion: {user_profile.get('current_emotion', '')} |
|
- Career goal: {user_profile.get('career_goal', '')} |
|
- Location: {user_profile.get('location', '')} |
|
""" |
|
|
|
messages.append({"role": "user", "parts": [profile_context]}) |
|
messages.append({"role": "user", "parts": [user_input]}) |
|
|
|
response = model.generate_content( |
|
messages, |
|
generation_config={"temperature": 0.7}, |
|
system_instruction=system_instruction, |
|
tools=tools |
|
) |
|
|
|
return response.text |
|
except Exception as e: |
|
logger.error(f"Error in get_ai_response: {str(e)}") |
|
return "I apologize, but I'm having trouble processing your request right now. Please try again later." |
|
|
|
def create_personalized_routine_with_ai(user_id, emotion, goal, available_time=60, days=7): |
|
"""Create a personalized routine using AI""" |
|
try: |
|
prompt = f""" |
|
Create a personalized {days}-day career development routine for a user who is feeling {emotion} and has a goal to {goal}. |
|
They have about {available_time} minutes per day to dedicate to this routine. |
|
|
|
For each day, suggest 1-3 specific tasks that will help them make progress toward their goal while considering their emotional state. |
|
|
|
For each task provide: |
|
1. Task name |
|
2. Duration in minutes |
|
3. Points value (between 10-50) |
|
4. A brief description of why this task is valuable |
|
|
|
Format the routine as a JSON object. |
|
""" |
|
|
|
response = model.generate_content(prompt) |
|
routine_text = response.text |
|
|
|
|
|
try: |
|
|
|
if "```json" in routine_text and "```" in routine_text.split("```json")[1]: |
|
json_str = routine_text.split("```json")[1].split("```")[0].strip() |
|
else: |
|
|
|
import re |
|
json_match = re.search(r'(\{.*\})', routine_text, re.DOTALL) |
|
if json_match: |
|
json_str = json_match.group(1) |
|
else: |
|
json_str = routine_text |
|
|
|
routine = json.loads(json_str) |
|
|
|
|
|
user_profile = add_routine_to_user(user_id, routine) |
|
return routine |
|
except json.JSONDecodeError: |
|
logger.error(f"Failed to parse JSON from AI response: {routine_text}") |
|
|
|
return generate_basic_routine(emotion, goal, available_time, days) |
|
except Exception as e: |
|
logger.error(f"Error in create_personalized_routine_with_ai: {str(e)}") |
|
|
|
return generate_basic_routine(emotion, goal, available_time, days) |
|
|
|
def generate_basic_routine(emotion, goal, available_time=60, days=7): |
|
"""Generate a basic routine as fallback""" |
|
routine_types = { |
|
"job_search": [ |
|
{"name": "Research target companies", "points": 10, "duration": 20, "description": "Identify potential employers that align with your career goals"}, |
|
{"name": "Update LinkedIn profile", "points": 15, "duration": 30, "description": "Keep your professional presence current and compelling"}, |
|
{"name": "Practice interview questions", "points": 20, "duration": 45, "description": "Build confidence and prepare for upcoming opportunities"}, |
|
{"name": "Reach out to a contact", "points": 25, "duration": 15, "description": "Grow your network and gather industry insights"} |
|
], |
|
"skill_building": [ |
|
{"name": "Complete one tutorial", "points": 20, "duration": 60, "description": "Develop practical skills in your field"}, |
|
{"name": "Read industry article", "points": 10, "duration": 15, "description": "Stay current with trends and developments"}, |
|
{"name": "Work on portfolio project", "points": 30, "duration": 90, "description": "Create tangible evidence of your abilities"}, |
|
{"name": "Watch expert talk", "points": 15, "duration": 30, "description": "Learn from leaders in your field"} |
|
], |
|
"motivation": [ |
|
{"name": "Write in gratitude journal", "points": 10, "duration": 10, "description": "Cultivate a positive mindset to enhance motivation"}, |
|
{"name": "Set 3 goals for the day", "points": 15, "duration": 15, "description": "Focus your energy on achievable tasks"}, |
|
{"name": "Exercise break", "points": 20, "duration": 20, "description": "Boost energy and mood with physical activity"}, |
|
{"name": "Reflect on progress", "points": 15, "duration": 15, "description": "Acknowledge achievements and identify next steps"} |
|
] |
|
} |
|
|
|
|
|
if "job" in goal.lower() or "company" in goal.lower(): |
|
routine_type = "job_search" |
|
elif "skill" in goal.lower() or "learn" in goal.lower(): |
|
routine_type = "skill_building" |
|
else: |
|
|
|
if emotion.lower() in ["unmotivated", "anxious", "confused", "overwhelmed", "discouraged"]: |
|
routine_type = "motivation" |
|
else: |
|
routine_type = random.choice(list(routine_types.keys())) |
|
|
|
|
|
daily_tasks = [] |
|
for day in range(1, days + 1): |
|
|
|
available_tasks = routine_types[routine_type].copy() |
|
random.shuffle(available_tasks) |
|
day_tasks = [] |
|
remaining_time = available_time |
|
|
|
for task in available_tasks: |
|
if task["duration"] <= remaining_time and len(day_tasks) < 3: |
|
day_tasks.append(task) |
|
remaining_time -= task["duration"] |
|
|
|
if remaining_time < 10 or len(day_tasks) >= 3: |
|
break |
|
|
|
daily_tasks.append({ |
|
"day": day, |
|
"tasks": day_tasks |
|
}) |
|
|
|
routine = { |
|
"name": f"{days}-Day {routine_type.replace('_', ' ').title()} Plan", |
|
"description": f"A personalized routine to help you {goal} while managing feelings of {emotion}.", |
|
"days": days, |
|
"daily_tasks": daily_tasks |
|
} |
|
|
|
return routine |
|
|
|
def generate_document_template_with_ai(document_type, career_field="", experience_level=""): |
|
"""Generate document templates using AI""" |
|
try: |
|
prompt = f""" |
|
Create a detailed template for a {document_type} for someone in the {career_field} field |
|
with {experience_level} experience level. |
|
|
|
The template should include all necessary sections and sample content that can be replaced. |
|
Format it in markdown. |
|
""" |
|
|
|
response = model.generate_content(prompt) |
|
return response.text |
|
except Exception as e: |
|
logger.error(f"Error in generate_document_template_with_ai: {str(e)}") |
|
return f"Error generating {document_type} template. Please try again later." |
|
|
|
|
|
def create_emotion_chart(user_id): |
|
"""Create a chart of user's emotions over time""" |
|
user_profile = get_user_profile(user_id) |
|
emotion_records = user_profile.get('daily_emotions', []) |
|
|
|
if not emotion_records: |
|
|
|
fig = px.line(title="Emotion Tracking: No data available yet") |
|
return fig |
|
|
|
|
|
emotion_values = { |
|
"Unmotivated": 1, |
|
"Anxious": 2, |
|
"Confused": 3, |
|
"Discouraged": 4, |
|
"Overwhelmed": 5, |
|
"Excited": 6 |
|
} |
|
|
|
dates = [] |
|
emotion_scores = [] |
|
emotion_names = [] |
|
|
|
for record in emotion_records: |
|
dates.append(datetime.strptime(record['date'], "%Y-%m-%d %H:%M:%S")) |
|
emotion = record['emotion'] |
|
emotion_names.append(emotion) |
|
emotion_scores.append(emotion_values.get(emotion, 3)) |
|
|
|
df = pd.DataFrame({ |
|
'Date': dates, |
|
'Emotion Score': emotion_scores, |
|
'Emotion': emotion_names |
|
}) |
|
|
|
|
|
fig = px.line(df, x='Date', y='Emotion Score', markers=True, |
|
labels={"Emotion Score": "Emotional State"}, |
|
title="Your Emotional Journey") |
|
|
|
|
|
fig.update_traces(hovertemplate='%{x}<br>Feeling: %{text}', text=df['Emotion']) |
|
|
|
|
|
fig.update_yaxes( |
|
tickvals=list(emotion_values.values()), |
|
ticktext=list(emotion_values.keys()) |
|
) |
|
|
|
return fig |
|
|
|
def create_progress_chart(user_id): |
|
"""Create a chart showing user's progress over time""" |
|
user_profile = get_user_profile(user_id) |
|
tasks = user_profile.get('completed_tasks', []) |
|
|
|
if not tasks: |
|
|
|
fig = px.line(title="Progress Tracking: No data available yet") |
|
return fig |
|
|
|
|
|
dates = [] |
|
points = [] |
|
cumulative_points = 0 |
|
task_labels = [] |
|
|
|
for task in tasks: |
|
dates.append(datetime.strptime(task['date'], "%Y-%m-%d %H:%M:%S")) |
|
|
|
cumulative_points += 20 |
|
points.append(cumulative_points) |
|
task_labels.append(task['task']) |
|
|
|
df = pd.DataFrame({ |
|
'Date': dates, |
|
'Points': points, |
|
'Task': task_labels |
|
}) |
|
|
|
|
|
fig = px.line(df, x='Date', y='Points', markers=True, |
|
title="Your Career Journey Progress") |
|
|
|
|
|
fig.update_traces(hovertemplate='%{x}<br>Points: %{y}<br>Task: %{text}', text=df['Task']) |
|
|
|
return fig |
|
|
|
def create_routine_completion_gauge(user_id): |
|
"""Create a gauge chart showing routine completion percentage""" |
|
user_profile = get_user_profile(user_id) |
|
routines = user_profile.get('routine_history', []) |
|
|
|
if not routines: |
|
|
|
fig = go.Figure() |
|
fig.add_annotation(text="No active routines yet", showarrow=False) |
|
return fig |
|
|
|
|
|
latest_routine = routines[-1] |
|
completion = latest_routine.get('completion', 0) |
|
|
|
|
|
fig = go.Figure(go.Indicator( |
|
mode = "gauge+number", |
|
value = completion, |
|
domain = {'x': [0, 1], 'y': [0, 1]}, |
|
title = {'text': "Current Routine Completion"}, |
|
gauge = { |
|
'axis': {'range': [None, 100]}, |
|
'bar': {'color': "darkblue"}, |
|
'steps': [ |
|
{'range': [0, 30], 'color': "lightgray"}, |
|
{'range': [30, 70], 'color': "gray"}, |
|
{'range': [70, 100], 'color': "darkgray"} |
|
], |
|
'threshold': { |
|
'line': {'color': "red", 'width': 4}, |
|
'thickness': 0.75, |
|
'value': 90 |
|
} |
|
} |
|
)) |
|
|
|
return fig |
|
|
|
|
|
def create_interface(): |
|
"""Create the Gradio interface for Aishura MVP""" |
|
|
|
|
|
session_user_id = str(uuid.uuid4()) |
|
|
|
|
|
def welcome(name, location, emotion, goal): |
|
if not name or not location or not emotion or not goal: |
|
return ("Please fill out all fields to continue.", |
|
gr.update(visible=True), |
|
gr.update(visible=False)) |
|
|
|
|
|
update_user_profile(session_user_id, { |
|
"name": name, |
|
"location": location, |
|
"career_goal": goal |
|
}) |
|
|
|
|
|
add_emotion_record(session_user_id, emotion) |
|
|
|
|
|
response = get_ai_response( |
|
session_user_id, |
|
f"I'm {name} from {location}. I'm feeling {emotion} and my career goal is to {goal}." |
|
) |
|
|
|
return (response, |
|
gr.update(visible=False), |
|
gr.update(visible=True)) |
|
|
|
|
|
def chat(message, history): |
|
|
|
if not history: |
|
history = [] |
|
|
|
|
|
history.append({"role": "user", "parts": [message]}) |
|
|
|
|
|
response = get_ai_response(session_user_id, message, history) |
|
|
|
|
|
history.append({"role": "assistant", "parts": [response]}) |
|
|
|
return history, "" |
|
|
|
|
|
def search_jobs_interface(query, location, max_results=5): |
|
jobs = search_jobs_with_serper(query, location, int(max_results)) |
|
|
|
if not jobs: |
|
return "No job opportunities found. Try adjusting your search terms." |
|
|
|
result = "## Job Opportunities Found\n\n" |
|
for i, job in enumerate(jobs, 1): |
|
result += f"### {i}. {job['title']}\n" |
|
result += f"**Company:** {job['company']}\n" |
|
result += f"**Location:** {job['location']}\n" |
|
result += f"**Description:** {job['description']}\n" |
|
result += f"**Link:** [Apply Here]({job['link']})\n\n" |
|
|
|
return result |
|
|
|
|
|
def generate_template(document_type, career_field, experience_level): |
|
template = generate_document_template_with_ai(document_type, career_field, experience_level) |
|
return template |
|
|
|
|
|
def create_personal_routine(emotion, goal, available_time, days): |
|
routine = create_personalized_routine_with_ai( |
|
session_user_id, emotion, goal, int(available_time), int(days) |
|
) |
|
|
|
|
|
result = f"# Your {routine['name']}\n\n" |
|
result += f"{routine['description']}\n\n" |
|
|
|
for day_plan in routine['daily_tasks']: |
|
result += f"## Day {day_plan['day']}\n\n" |
|
for task in day_plan['tasks']: |
|
result += f"- **{task['name']}** ({task['duration']} mins, {task['points']} points)\n" |
|
result += f" *{task['description']}*\n\n" |
|
|
|
|
|
add_routine_to_user(session_user_id, routine) |
|
|
|
return result |
|
|
|
|
|
def complete_task(task_name): |
|
if not task_name: |
|
return "Please enter a task name." |
|
|
|
user_profile = add_task_to_user(session_user_id, task_name) |
|
|
|
|
|
if user_profile.get('routine_history'): |
|
latest_routine = user_profile['routine_history'][-1] |
|
|
|
new_completion = min(100, latest_routine.get('completion', 0) + random.randint(5, 15)) |
|
latest_routine['completion'] = new_completion |
|
update_user_profile(session_user_id, {"routine_history": user_profile['routine_history']}) |
|
|
|
|
|
emotion_fig = create_emotion_chart(session_user_id) |
|
progress_fig = create_progress_chart(session_user_id) |
|
gauge_fig = create_routine_completion_gauge(session_user_id) |
|
|
|
return ( |
|
f"Task '{task_name}' completed! You earned {random.randint(10, 25)} points.", |
|
"", |
|
emotion_fig, |
|
progress_fig, |
|
gauge_fig |
|
) |
|
|
|
|
|
def update_emotion(emotion): |
|
add_emotion_record(session_user_id, emotion) |
|
|
|
|
|
emotion_fig = create_emotion_chart(session_user_id) |
|
|
|
return ( |
|
f"Your emotional state has been updated to: {emotion}", |
|
emotion_fig |
|
) |
|
|
|
|
|
with gr.Blocks(theme=gr.themes.Soft()) as app: |
|
gr.Markdown("# Aishura - Your AI Career Assistant") |
|
|
|
|
|
with gr.Group(visible=True) as welcome_group: |
|
gr.Markdown("## Welcome to Aishura") |
|
gr.Markdown("Let's start by getting to know you a little better.") |
|
|
|
name_input = gr.Textbox(label="Your Name") |
|
location_input = gr.Textbox(label="Your Location (City/Country)") |
|
emotion_dropdown = gr.Dropdown(choices=EMOTIONS, label="How are you feeling today?") |
|
goal_dropdown = gr.Dropdown(choices=GOAL_TYPES, label="What's your career goal?") |
|
|
|
welcome_button = gr.Button("Get Started") |
|
welcome_output = gr.Markdown() |
|
|
|
|
|
with gr.Group(visible=False) as main_interface: |
|
with gr.Tabs() as tabs: |
|
|
|
with gr.TabItem("Chat with Aishura"): |
|
chatbot = gr.Chatbot(height=400, avatar_images=["π€", "π€"]) |
|
msg = gr.Textbox(show_label=False, placeholder="Type your message here...", container=False) |
|
|
|
msg.submit(chat, [msg, chatbot], [chatbot, msg]) |
|
|
|
|
|
with gr.TabItem("Find Opportunities"): |
|
gr.Markdown("## Search for Job Opportunities") |
|
job_query = gr.Textbox(label="What kind of job are you looking for?") |
|
job_location = gr.Textbox(label="Location") |
|
job_results = gr.Slider(minimum=5, maximum=20, value=10, step=5, label="Number of Results") |
|
|
|
search_button = gr.Button("Search") |
|
job_output = gr.Markdown() |
|
|
|
search_button.click(search_jobs_interface, [job_query, job_location, job_results], job_output) |
|
|
|
|
|
with gr.TabItem("Document Templates"): |
|
gr.Markdown("## Generate Document Templates") |
|
doc_type = gr.Dropdown( |
|
choices=["Resume", "Cover Letter", "Self-Introduction", "LinkedIn Profile", "Portfolio"], |
|
label="Document Type" |
|
) |
|
career_field = gr.Textbox(label="Career Field/Industry") |
|
experience = gr.Dropdown( |
|
choices=["Entry Level", "Mid-Career", "Senior"], |
|
label="Experience Level" |
|
) |
|
|
|
template_button = gr.Button("Generate Template") |
|
template_output = gr.Markdown() |
|
|
|
template_button.click(generate_template, [doc_type, career_field, experience], template_output) |
|
|
|
|
|
with gr.TabItem("Personal Routine"): |
|
gr.Markdown("## Create Your Personal Development Routine") |
|
routine_emotion = gr.Dropdown(choices=EMOTIONS, label="Current Emotional State") |
|
routine_goal = gr.Textbox(label="What specific goal are you working toward?") |
|
time_available = gr.Slider(minimum=15, maximum=120, value=60, step=15, label="Minutes Available Per Day") |
|
routine_days = gr.Slider(minimum=3, maximum=30, value=7, step=1, label="Length of Routine (Days)") |
|
|
|
routine_button = gr.Button("Create Routine") |
|
routine_output = gr.Markdown() |
|
|
|
routine_button.click(create_personal_routine, |
|
[routine_emotion, routine_goal, time_available, routine_days], |
|
routine_output) |
|
|
|
|
|
with gr.TabItem("Track Progress"): |
|
with gr.Row(): |
|
with gr.Column(): |
|
gr.Markdown("## Mark Tasks as Complete") |
|
task_input = gr.Textbox(label="Enter Task Name") |
|
complete_button = gr.Button("Mark as Complete") |
|
task_output = gr.Markdown() |
|
|
|
with gr.Column(): |
|
gr.Markdown("## Update Your Emotional State") |
|
new_emotion = gr.Dropdown(choices=EMOTIONS, label="How are you feeling now?") |
|
emotion_button = gr.Button("Update") |
|
emotion_output = gr.Markdown() |
|
|
|
with gr.Row(): |
|
with gr.Column(): |
|
emotion_chart = gr.Plot(label="Emotional Journey") |
|
|
|
with gr.Column(): |
|
progress_chart = gr.Plot(label="Progress Journey") |
|
|
|
with gr.Row(): |
|
gauge_chart = gr.Plot(label="Routine Completion") |
|
|
|
complete_button.click( |
|
complete_task, |
|
[task_input], |
|
[task_output, task_input, emotion_chart, progress_chart, gauge_chart] |
|
) |
|
|
|
emotion_button.click( |
|
update_emotion, |
|
[new_emotion], |
|
[emotion_output, emotion_chart] |
|
) |
|
|
|
|
|
welcome_button.click( |
|
welcome, |
|
[name_input, location_input, emotion_dropdown, goal_dropdown], |
|
[welcome_output, welcome_group, main_interface] |
|
) |
|
|
|
return app |
|
|
|
|
|
def main(): |
|
app = create_interface() |
|
app.launch(share=True) |
|
|
|
if __name__ == "__main__": |
|
main() |