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"""
You: {message['content']}
""", unsafe_allow_html=True) elif message['role'] == 'assistant': st.markdown(f"""
Agent: {message['content']}
""", unsafe_allow_html=True) display_conversation() with st.form(key='chat_form', clear_on_submit=True): user_input = st.text_input("Type your message here...") submit_button = st.form_submit_button(label='Send') if submit_button: if user_input: st.session_state['conversation_history'].append({'role': 'user', 'content': user_input}) messages = st.session_state['conversation_history'].copy() profile_context = "" for key, value in parsed_profile.items(): if value != '-' and value: if key == "Experience" and isinstance(value, list) and value != ['-']: experience_details = [] for position in value: position_detail = f"Title: {position.get('title', '-')}\n" \ f"Company Name: {position.get('companyName', '-')}\n" \ f"Description: {position.get('description', '-')}" experience_details.append(position_detail) profile_context += f"\n{key}:\n" + "\n\n".join(experience_details) elif isinstance(value, list): profile_context += f"\n{key}:\n{', '.join(value)}" elif isinstance(value, int): profile_context += f"\n{key}:\n{value}" else: profile_context += f"\n{key}:\n{value}" system_prompt = f""" You are an AI assistant helping a user improve their LinkedIn profile for the role of {target_role}. Provide concise and actionable advice based on the user's messages. Avoid providing lists or unnecessary details. Offer explanations only if needed, and keep them brief. Do not mention internal strategies or methodologies. User's current profile data: {profile_context} """ messages.insert(0, {'role': 'system', 'content': system_prompt}) chat_completion = client.chat.completions.create( messages=messages, 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('*', '') st.session_state['conversation_history'].append({'role': 'assistant', 'content': agent_response}) display_conversation()