AI_Resume_Builder / src /streamlit_app.py
Alexvatti's picture
Update src/streamlit_app.py
0bf8bc3 verified
import os
import io
import streamlit as st
from langchain_google_genai import ChatGoogleGenerativeAI
from fpdf import FPDF
# === CONFIGURE YOUR GOOGLE GEMINI KEY ===
os.environ["GOOGLE_API_KEY"] = "AIzaSyCB5NLx39vOAlfRQBDmnEG3uLBgLraGvH4"
# Initialize Gemini Model
model = ChatGoogleGenerativeAI(model="gemini-2.5-flash", temperature=0.0)
st.title("AI Resume Builder - Professional Format")
# Session state
for key in ("education_list", "project_list", "experience_list", "publication_list"):
if key not in st.session_state:
st.session_state[key] = []
# Basic Info Section
st.subheader("Personal Information")
col1, col2 = st.columns(2)
with col1:
name = st.text_input("Full Name")
email = st.text_input("Email")
phone = st.text_input("Phone Number")
with col2:
location = st.text_input("Location (City, State/Country)")
website = st.text_input("Personal Website (optional)")
linkedin = st.text_input("LinkedIn URL")
github = st.text_input("GitHub URL (optional)")
# Professional Summary
st.subheader("Professional Summary")
summary_manual = st.text_area("Professional Summary (optional - will be auto-generated if left blank)",
placeholder="Brief overview of your career, skills, and goals...")
# Skills Section
st.subheader("Skills & Technologies")
languages = st.text_input("Programming Languages", placeholder="e.g., Python, Java, C++, JavaScript")
technologies = st.text_input("Technologies/Frameworks", placeholder="e.g., React, Django, AWS, Docker")
databases = st.text_input("Databases (optional)", placeholder="e.g., MySQL, MongoDB, PostgreSQL")
other_skills = st.text_input("Other Skills (optional)", placeholder="e.g., Git, Linux, Agile, Machine Learning")
# Education Section
st.subheader("Education Details")
col1, col2 = st.columns(2)
with col1:
college = st.text_input("University/College Name")
degree = st.text_input("Degree & Major", placeholder="e.g., BS in Computer Science")
with col2:
edu_start = st.text_input("Start Date", placeholder="e.g., Sept 2020")
edu_end = st.text_input("End Date", placeholder="e.g., May 2024")
gpa = st.text_input("GPA (optional)", placeholder="e.g., 3.9/4.0")
coursework = st.text_input("Relevant Coursework (optional)", placeholder="e.g., Data Structures, Machine Learning, Database Systems")
achievements = st.text_input("Academic Achievements (optional)", placeholder="e.g., Dean's List, Magna Cum Laude")
if st.button("Add Education"):
st.session_state.education_list.append({
"college": college,
"degree": degree,
"start": edu_start,
"end": edu_end,
"gpa": gpa,
"coursework": coursework,
"achievements": achievements
})
for i, edu in enumerate(st.session_state.education_list, start=1):
st.write(f"{i}. {edu['college']}, {edu['degree']} | {edu['start']}{edu['end']}")
if st.button(f"Remove Education {i}", key=f"remove_edu_{i}"):
st.session_state.education_list.pop(i-1)
st.rerun()
# Experience Section
exp_status = st.radio("Experience Level", ("Fresher", "Experienced"))
if exp_status == "Experienced":
st.subheader("Work Experience")
col1, col2 = st.columns(2)
with col1:
job_title = st.text_input("Job Title")
company = st.text_input("Company Name")
with col2:
work_location = st.text_input("Work Location", placeholder="e.g., New York, NY")
work_start = st.text_input("Start Date", placeholder="e.g., June 2022")
work_end = st.text_input("End Date", placeholder="e.g., Present or Aug 2024")
# Job responsibilities
st.write("Job Responsibilities (add multiple bullet points):")
responsibility = st.text_area("Responsibility/Achievement",
placeholder="Describe a specific achievement with metrics if possible...")
if st.button("Add Experience"):
st.session_state.experience_list.append({
"title": job_title,
"company": company,
"location": work_location,
"start": work_start,
"end": work_end,
"responsibility": responsibility
})
for i, exp in enumerate(st.session_state.experience_list, start=1):
st.write(f"{i}. {exp['title']} at {exp['company']}{exp['location']} | {exp['start']}{exp['end']}")
if st.button(f"Remove Experience {i}", key=f"remove_exp_{i}"):
st.session_state.experience_list.pop(i-1)
st.rerun()
# Projects Section
st.subheader("Projects")
col1, col2 = st.columns(2)
with col1:
proj_title = st.text_input("Project Title")
proj_tools = st.text_input("Technologies Used", placeholder="e.g., Python, Flask, MySQL")
with col2:
proj_github = st.text_input("GitHub/Demo Link (optional)")
proj_date = st.text_input("Project Date (optional)", placeholder="e.g., Jan 2024")
proj_desc = st.text_area("Project Description",
placeholder="Describe what the project does, your role, and key achievements...")
if st.button("Add Project"):
st.session_state.project_list.append({
"title": proj_title,
"tools": proj_tools,
"github": proj_github,
"date": proj_date,
"desc": proj_desc
})
for i, proj in enumerate(st.session_state.project_list, start=1):
st.write(f"{i}. {proj['title']} | Tools: {proj['tools']}")
if st.button(f"Remove Project {i}", key=f"remove_proj_{i}"):
st.session_state.project_list.pop(i-1)
st.rerun()
# Publications Section (Optional)
st.subheader("Publications (Optional)")
pub_title = st.text_input("Publication Title")
pub_authors = st.text_input("Authors", placeholder="e.g., John Doe, Jane Smith")
pub_date = st.text_input("Publication Date", placeholder="e.g., Jan 2024")
pub_doi = st.text_input("DOI/Link (optional)")
if st.button("Add Publication"):
st.session_state.publication_list.append({
"title": pub_title,
"authors": pub_authors,
"date": pub_date,
"doi": pub_doi
})
for i, pub in enumerate(st.session_state.publication_list, start=1):
st.write(f"{i}. {pub['title']} | {pub['authors']} | {pub['date']}")
if st.button(f"Remove Publication {i}", key=f"remove_pub_{i}"):
st.session_state.publication_list.pop(i-1)
st.rerun()
# Generate Resume
if st.button("Generate Professional Resume", type="primary"):
# Prepare data for prompt
contact_info = f"{name}\n{location} | {email} | {phone}"
if website:
contact_info += f" | {website}"
if linkedin:
contact_info += f"\nlinkedin.com/in/{linkedin.split('/')[-1] if '/' in linkedin else linkedin}"
if github:
contact_info += f" | github.com/{github.split('/')[-1] if '/' in github else github}"
# Skills formatting
skills_text = ""
if languages:
skills_text += f"Languages: {languages}\n"
if technologies:
skills_text += f"Technologies: {technologies}\n"
if databases:
skills_text += f"Databases: {databases}\n"
if other_skills:
skills_text += f"Other Skills: {other_skills}"
# Education formatting
education_text = ""
for edu in st.session_state.education_list:
education_text += f"• {edu['college']}, {edu['degree']}"
if edu['start'] and edu['end']:
education_text += f" | {edu['start']}{edu['end']}\n"
else:
education_text += "\n"
if edu['gpa']:
education_text += f" - GPA: {edu['gpa']}\n"
if edu['coursework']:
education_text += f" - Coursework: {edu['coursework']}\n"
if edu['achievements']:
education_text += f" - {edu['achievements']}\n"
# Experience formatting
experience_text = ""
if exp_status == "Experienced" and st.session_state.experience_list:
for exp in st.session_state.experience_list:
experience_text += f"• {exp['title']}, {exp['company']}{exp['location']} | {exp['start']}{exp['end']}\n"
if exp['responsibility']:
for resp in exp['responsibility'].split('\n'):
if resp.strip():
experience_text += f" - {resp.strip()}\n"
else:
experience_text = "Recent graduate seeking entry-level opportunities to apply academic knowledge and skills."
# Projects formatting
project_text = ""
for proj in st.session_state.project_list:
project_text += f"• {proj['title']}"
if proj['github']:
project_text += f" | {proj['github']}"
if proj['date']:
project_text += f" | {proj['date']}"
project_text += "\n"
if proj['desc']:
for desc_line in proj['desc'].split('\n'):
if desc_line.strip():
project_text += f" - {desc_line.strip()}\n"
if proj['tools']:
project_text += f" - Tools Used: {proj['tools']}\n"
# Publications formatting
publications_text = ""
for pub in st.session_state.publication_list:
publications_text += f"• {pub['title']} | {pub['date']}\n"
publications_text += f" {pub['authors']}\n"
if pub['doi']:
publications_text += f" {pub['doi']}\n"
# Create comprehensive prompt
prompt = [
("system", """You are a professional resume writer specializing in creating clean, ATS-friendly resumes.
Create resumes that follow this exact format and structure:
HEADER: Name on first line, then contact info on subsequent lines
SECTIONS: Use clear section headers in ALL CAPS
FORMATTING: Use bullet points (•) for lists, maintain consistent spacing
STYLE: Professional, concise, action-oriented language with quantifiable achievements when possible
Always include these sections in this order:
1. Contact Information (header)
2. Professional Summary (if experience) or Objective (if fresher)
3. Education
4. Experience (if applicable)
5. Projects
6. Publications (if any)
7. Technologies/Skills
Make it ATS-friendly with no fancy formatting, just clean structure."""),
("human", f"""Create a professional resume using this information:
CONTACT INFORMATION:
{contact_info}
PROFESSIONAL SUMMARY:
Status: {exp_status}
Manual Summary: {summary_manual or '(Generate based on profile)'}
EDUCATION:
{education_text or '(No education provided)'}
EXPERIENCE:
{experience_text}
PROJECTS:
{project_text or '(No projects provided)'}
PUBLICATIONS:
{publications_text or '(No publications)'}
SKILLS & TECHNOLOGIES:
{skills_text or '(No skills provided)'}
INSTRUCTIONS:
1. Format exactly like a professional resume with clear sections
2. Use bullet points for achievements and responsibilities
3. Keep it concise but comprehensive
4. Include quantifiable results where possible
5. Make it ATS-friendly
6. If manual summary is blank, generate a professional 3-4 line summary based on their profile
7. Don't include empty sections
8. Use action verbs for experience and project descriptions
9. Maintain professional tone throughout
10. Format contact info cleanly at the top
Generate the complete resume now:""")
]
try:
response = model.invoke(prompt)
resume_text = response.content
resume_text = resume_text.replace("*", "-")
st.subheader("Generated Professional Resume")
st.text_area("Resume Output", value=resume_text, height=600)
# Enhanced PDF generation
def create_pdf_unicode(text: str):
pdf = FPDF()
pdf.add_page()
pdf.set_font("Arial", size=12)
lines = text.split("\n")
for line in lines:
if line.strip() == "":
pdf.ln(3)
elif line.isupper() and len(line.strip()) < 50: # Section headers
pdf.set_font("Arial", "B", 12)
pdf.ln(5)
pdf.cell(0, 8, line.strip(), ln=True)
pdf.ln(2)
pdf.set_font("Arial", size=11)
elif line.startswith(name.split()[0]) and len(line) < 100: # Name header
pdf.set_font("Arial", "B", 16)
pdf.cell(0, 10, line.strip(), ln=True, align='C')
pdf.set_font("Arial", size=11)
else:
pdf.set_font("Arial", size=11)
# Handle long lines
if len(line) > 90:
pdf.multi_cell(0, 6, line.strip())
else:
pdf.cell(0, 6, line.strip(), ln=True)
return io.BytesIO(pdf.output(dest="S").encode("latin-1"))
pdf_buffer = create_pdf_unicode(resume_text)
st.download_button(
"📄 Download Professional Resume as PDF",
data=pdf_buffer,
file_name=f"{name.replace(' ', '_')}_Resume.pdf" if name else "Professional_Resume.pdf",
mime="application/pdf"
)
st.success("✅ Professional resume generated successfully! Click download to save as PDF.")
except Exception as e:
st.error(f"Error generating resume: {str(e)}")
st.info("Please check your Google API key and try again.")