Inhance / enhancer_agent.py
yashgori20's picture
done
492af8a
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"""
<div style='text-align: left; margin: 10px 0;'>
<div style='display: inline-block; padding: 10px; border-radius: 10px; background-color: #000000;'>
<strong>You:</strong> {message['content']}
</div>
</div>
""", unsafe_allow_html=True)
elif message['role'] == 'assistant':
st.markdown(f"""
<div style='text-align: left; margin: 10px 0;'>
<div style='display: inline-block; padding: 10px; border-radius: 10px; background-color: #000000;'>
<strong>Agent:</strong> {message['content']}
</div>
</div>
""", 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()