def enhancer_agent(profile_data, evaluation_feedback, target_role): import streamlit as st from groq import Groq import json from config import Config try: client = Groq(api_key=Config.GROQ_API_KEY) except Exception as e: st.error(f"❌ Groq API Configuration Error: {str(e)}") st.info("Please check your Groq API key configuration.") return if 'conversation_history' not in st.session_state: st.session_state['conversation_history'] = [] if 'selected_tab' not in st.session_state: st.session_state['selected_tab'] = "Profile Overview" profile_sections = [ "Headline", "Summary/About", "Experience", # Changed from "Current Position/Experience" to "Experience" "Education", "Skills", "Certifications", "Recommendations", ] def get_section_recommendation_and_explanation(section_name, current_content): if not current_content or current_content == '-': prompt = f""" You are an AI assistant helping a user improve their LinkedIn profile for the role of {target_role}. The user currently has no content in the {section_name} section. Provide guidance on how they can effectively add this section to enhance their profile. Guidelines: - Offer general advice on what to include in the {section_name} section. - Do not fabricate any data or metrics. - Encourage the user to reflect on their own experiences and qualifications. - Keep the recommendation professional and focused. Format: Recommendation: [Provide the recommendation here] Explanation: [Provide a brief explanation here] """ else: prompt = f""" You are an AI assistant helping a user improve their LinkedIn profile for the role of {target_role}. Focus on enhancing the user's existing content in the {section_name} section to make it more professional and eye-catching. Current content: {current_content} Guidelines: - Rewrite the existing content to improve clarity, professionalism, and impact. - Do not alter or add any factual information. - Focus on changing the tone and wording, not the facts. - Do not suggest adding new roles or experiences that the user hasn't had. - Tailor the improved content to align subtly with the target role, but prioritize enhancing the current content. - Do not mention internal strategies. - Do not fabricate any data or metrics. - Keep the recommendation professional and focused. Format: Recommendation: [Provide the improved content here] Explanation: [Provide a brief explanation here] """ try: chat_completion = client.chat.completions.create( messages=[ {'role': 'user', 'content': prompt} ], model="openai/gpt-oss-120b", stream=False, temperature=0.3 ) agent_response = chat_completion.choices[0].message.content.strip() # Clean markdown formatting from GPT-OSS response agent_response = agent_response.replace('**', '').replace('*', '') except Exception as e: st.error(f"❌ Groq API Error: {str(e)}") if "organization_restricted" in str(e): st.warning("🔑 Your Groq API key has been restricted. Please:") st.info("1. Check your Groq account at https://console.groq.com/\n2. Generate a new API key\n3. Update your .env file") return "Error generating recommendation", "Unable to generate recommendation due to API error" if "Recommendation:" in agent_response and "Explanation:" in agent_response: recommendation_part = agent_response.split("Recommendation:")[1] recommendation = recommendation_part.split("Explanation:")[0].strip() explanation = recommendation_part.split("Explanation:")[1].strip() else: recommendation = agent_response explanation = "No explanation provided." return recommendation, explanation def parse_profile_data(profile_data): person = profile_data.get('person', {}) positions_data = person.get('positions', {}) certifications_data = person.get('certifications', {}) skills_data = person.get('skills', []) educations_data = person.get('schools', {}) recommendations_data = person.get('recommendations', {}) if isinstance(skills_data, list): skills_list = skills_data if skills_data else ['-'] else: skills_list = ['-'] if isinstance(positions_data, dict): positions_list = positions_data.get('positionHistory', []) else: positions_list = [] # Get ALL positions, not just current one all_positions = positions_list if positions_list else ['-'] if isinstance(certifications_data, dict): certifications_list = certifications_data.get('certificationHistory', []) certifications_list = [ cert.get('name', '-') for cert in certifications_list if isinstance(cert, dict) ] else: certifications_list = ['-'] if isinstance(educations_data, dict): educations_list = educations_data.get('educationHistory', []) # Get ALL education entries, not just the first one all_education = educations_list if educations_list else ['-'] else: all_education = ['-'] if isinstance(recommendations_data, dict): recommendations_count = recommendations_data.get('recommendationsCount', 0) else: recommendations_count = 0 summary = person.get('summary', '-') or '-' parsed_data = { 'Headline': person.get('headline', '-') or '-', 'Summary/About': summary, 'Experience': all_positions, # Changed from current_position to all_positions 'Education': all_education, # Changed from single education to all_education 'Skills': skills_list, 'Certifications': certifications_list, 'Recommendations': recommendations_count, } return parsed_data def identify_missing_elements(parsed_data): missing_elements = [] for key in profile_sections: value = parsed_data.get(key) if not value or value == '-' or (isinstance(value, list) and all(v == '-' for v in value)): missing_elements.append(key) return missing_elements parsed_profile = parse_profile_data(profile_data) missing_elements = identify_missing_elements(parsed_profile) st.title("LinkedIn Profile Enhancement Agent") st.markdown("Enhance your LinkedIn profile to stand out for the role of **{}**.".format(target_role)) tab_names = ["Profile Overview", "Profile Evaluation", "Recommendations", "Chat with Agent"] selected_tab = st.radio("Navigate to", tab_names, index=tab_names.index(st.session_state['selected_tab']), key='tabs') st.session_state['selected_tab'] = selected_tab if selected_tab == "Profile Overview": st.header("Profile Overview") st.markdown("Review your current LinkedIn profile sections.") for key in profile_sections: value = parsed_profile.get(key, '-') st.markdown(f"### {key}") # Underlined heading if not value or value == '-' or (isinstance(value, list) and not any(value)): st.markdown("_This section is currently missing or incomplete._") else: if key == "Experience" and isinstance(value, list) and value != ['-']: # Display all experience entries for i, position in enumerate(value): st.markdown(f"### Experience {i+1}") start_end_date = position.get('startEndDate', {}) start_date = start_end_date.get('start') end_date = start_end_date.get('end') if isinstance(start_date, dict): start_month = start_date.get('month', '-') start_year = start_date.get('year', '-') else: start_month = '-' start_year = '-' if isinstance(end_date, dict): end_month = end_date.get('month', '-') end_year = end_date.get('year', '-') else: end_month = 'Present' end_year = '' duration = f"{start_month}/{start_year} - {end_month}/{end_year}".strip() if duration == "-/- - Present/": duration = "Present" position_details = f"**Title:** {position.get('title', '-')}\n\n" \ f"**Company Name:** {position.get('companyName', '-')}\n\n" \ f"**Duration:** {duration}\n\n" \ f"**Description:**\n{position.get('description', '-')}" st.markdown(position_details) st.markdown("---") # Separator between experiences elif key == "Education" and isinstance(value, list) and value != ['-']: # Display all education entries for i, education in enumerate(value): st.markdown(f"### Education {i+1}") start_end_date = education.get('startEndDate', {}) start_date = start_end_date.get('start') end_date = start_end_date.get('end') if isinstance(start_date, dict): start_year = start_date.get('year', '-') else: start_year = '-' if isinstance(end_date, dict): end_year = end_date.get('year', '-') else: end_year = '-' duration = f"{start_year} - {end_year}".strip() education_details = f"**School Name:** {education.get('schoolName', '-')}\n\n" \ f"**Degree Name:** {education.get('degreeName', '-')}\n\n" \ f"**Field of Study:** {education.get('fieldOfStudy', '-')}\n\n" \ f"**Duration:** {duration}" st.markdown(education_details) st.markdown("---") # Separator between education entries elif key == "Skills" and isinstance(value, list): st.markdown("\n".join([f"- {skill}" for skill in value])) elif isinstance(value, list): st.markdown(", ".join(value)) elif isinstance(value, int): st.markdown(f"**{value} Recommendations**") else: st.markdown(value) elif selected_tab == "Profile Evaluation": st.header("Profile Evaluation") st.markdown("Here are some suggestions to improve your LinkedIn profile.") def enhance_evaluation_feedback(evaluation_feedback): prompt = f""" You are an AI assistant helping a user by improving the following evaluation feedback to make it more user-friendly and actionable. Original Evaluation Feedback: {evaluation_feedback} Guidelines: - Rephrase the feedback to be clear and helpful. - Provide actionable suggestions for improvement. - Use a friendly and encouraging tone. - Do not mention internal processes. - Do not include any disallowed content. Enhanced Evaluation Feedback: """ try: chat_completion = client.chat.completions.create( messages=[ {'role': 'user', 'content': prompt} ], model="openai/gpt-oss-120b", stream=False, temperature=0.3 ) enhanced_feedback = chat_completion.choices[0].message.content.strip() # Clean markdown formatting from GPT-OSS response enhanced_feedback = enhanced_feedback.replace('**', '').replace('*', '') return enhanced_feedback except Exception as e: st.error(f"❌ Groq API Error: {str(e)}") if "organization_restricted" in str(e): st.warning("🔑 Your Groq API key has been restricted. Please:") st.info("1. Check your Groq account at https://console.groq.com/\n2. Generate a new API key\n3. Update your .env file") return evaluation_feedback # Return original feedback if enhancement fails enhanced_evaluation = enhance_evaluation_feedback(evaluation_feedback) st.markdown(enhanced_evaluation) st.subheader("Missing Profile Sections") if missing_elements: st.markdown("Adding the following sections can greatly enhance your profile:") for element in missing_elements: st.markdown(f"- **{element}**") else: st.markdown("Great job! Your profile has all the key sections filled out.") elif selected_tab == "Recommendations": st.header("Personalized Recommendations") st.markdown(f"Enhance your profile sections to align with the role of **{target_role}**.") for key in profile_sections: current_content = parsed_profile.get(key, '-') if key == "Experience" and isinstance(current_content, list) and current_content != ['-']: # Handle multiple experience entries experience_strs = [] for position in current_content: experience_strs.append(f"Title: {position.get('title', '-')}\nCompany Name: {position.get('companyName', '-')}\nDescription: {position.get('description', '-')}") current_content_str = "\n\n".join(experience_strs) recommendation, explanation = get_section_recommendation_and_explanation(key, current_content_str) elif isinstance(current_content, list) and current_content != ['-']: current_content_str = ", ".join(current_content) recommendation, explanation = get_section_recommendation_and_explanation(key, current_content_str) elif current_content != '-' and current_content: recommendation, explanation = get_section_recommendation_and_explanation(key, current_content) else: recommendation, explanation = get_section_recommendation_and_explanation(key, '') with st.expander(f"{key} Recommendation", expanded=False): st.subheader("Recommendation") st.code(recommendation, language=None) st.subheader("Explanation") st.write(explanation) elif selected_tab == "Chat with Agent": st.header("Chat with Enhancement Agent") st.markdown("Interact with the agent to personalize your profile further or provide additional details.") def display_conversation(): for message in st.session_state['conversation_history']: if message['role'] == 'user': st.markdown(f"""