File size: 4,973 Bytes
7b7951a
 
 
 
 
 
 
 
 
 
 
 
a8d427d
 
7b7951a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50c4eb9
 
7b7951a
 
 
50c4eb9
7b7951a
50c4eb9
 
7b7951a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cef88ad
7b7951a
 
 
 
50c4eb9
a25c8cf
7b7951a
 
 
 
 
 
 
50c4eb9
7b7951a
 
50c4eb9
 
 
 
 
 
 
 
 
7b7951a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import streamlit as st
import os
import io
import pdfplumber
import pandas as pd
from dotenv import load_dotenv
from groq import Groq
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from docx import Document

# Page config
st.set_page_config(page_title="πŸ“„ AI ResumeSync Analyzer", layout="centered")

# Load env vars
load_dotenv()
GROQ_API_KEY = os.getenv("GROQ_API_KEY")

if not GROQ_API_KEY:
    st.error("❌ GROQ API Key is missing. Please add it in the .env file or Hugging Face Secrets.")
    st.stop()

# Load Google Sheet
df = pd.DataFrame()
sheet_loaded = False
scope = ["https://spreadsheets.google.com/feeds", "https://www.googleapis.com/auth/drive"]

if os.path.exists("credentials.json"):
    try:
        creds = ServiceAccountCredentials.from_json_keyfile_name("credentials.json", scope)
        client = gspread.authorize(creds)
        sheet = client.open("Job_Listings").sheet1
        data = sheet.get_all_records()
        df = pd.DataFrame(data)
        sheet_loaded = True
    except Exception as e:
        st.warning(f"⚠️ Could not load job listings from Google Sheet: {e}")

# Fallback job listing
if not sheet_loaded:
    df = pd.DataFrame([{
        "Title": "Software Engineer",
        "Skills": "Python, Django, SQL",
        "Experience": "2+ years",
        "Education": "BS in Computer Science"
    }])

# Groq client
groq_client = Groq(api_key=GROQ_API_KEY)

# UI: Title
st.title("πŸ“„ AI ResumeSync Analyzer")
st.markdown("Upload your resume below to receive tailored job match analysis, skill suggestions, and a personalized cover letter.")

# File uploader
uploaded_file = st.file_uploader("πŸ“€ Upload your resume (PDF, DOCX, or TXT)", type=["pdf", "docx", "txt"])

# Resume text extractor
def extract_resume_text(uploaded_file):
    try:
        filename = uploaded_file.name.lower()
        buffer = io.BytesIO(uploaded_file.getvalue())  # Use getvalue() instead of read()
        buffer.seek(0)

        if filename.endswith(".pdf"):
            text = ""
            with pdfplumber.open(buffer) as pdf:
                for page in pdf.pages:
                    page_text = page.extract_text()
                    if page_text:
                        text += page_text + "\n"
            return text.strip()

        elif filename.endswith(".docx"):
            doc = Document(buffer)
            return "\n".join(para.text for para in doc.paragraphs if para.text.strip())

        elif filename.endswith(".txt"):
            return buffer.getvalue().decode("utf-8", errors="ignore")

        else:
            return None
    except Exception as e:
        st.error(f"❌ Error reading resume file: {e}")
        return None

# Main logic
if uploaded_file:
    with st.spinner("πŸ” Analyzing your resume..."):
        resume_text = extract_resume_text(uploaded_file)
        if not resume_text or resume_text.strip() == "":
            st.error("❌ No readable content in the uploaded resume.")
            st.stop()

        # AI Prompt
        prompt = f"""
You are an expert AI Resume Analyzer. Based on the resume and job listings provided, return a detailed, formatted response covering:
1. βœ… Match Score (as percentage)
2. 🎯 Recommended Jobs (top 3 that match well)
3. πŸ“Š Qualification Ranking (1 to 10)
4. 🧩 Skill Gaps & Suggestions
5. πŸ› οΈ Keyword Optimization Suggestions
6. πŸŽ“ Education & Experience Alignment
7. πŸ’° Estimated Salary Range
8. πŸ“ˆ Job Market Trends (optional)
9. ✍️ Personalized Cover Letter
Return the output with clear headings and markdown formatting.

Resume:
{resume_text}

Available Jobs:
{df.to_string(index=False)}
"""

        try:
            response = groq_client.chat.completions.create(
                model="llama3-8b-8192",
                messages=[{"role": "user", "content": prompt}]
            )

            message = response.choices[0].message.content.strip()

            if not message:
                st.error("❌ Groq returned an empty response.")
            else:
                st.success("βœ… Analysis Complete!")

                # Output full analysis
                st.markdown(message, unsafe_allow_html=True)

                # Job recommendations
                st.markdown("---")
                st.subheader("πŸ“Œ Job Listing Overview")
                st.dataframe(df)

                # Call-to-action
                st.markdown("### πŸ”“ Unlock More Features or Take Action")
                col1, col2 = st.columns(2)
                with col1:
                    if st.button("βœ… Apply Now"):
                        st.info("πŸ”— Redirecting to application portal... (hook this into your system)")
                with col2:
                    if st.button("πŸš€ Upgrade to Pro Templates"):
                        st.warning("Premium templates coming soon! Contact support to activate.")

        except Exception as e:
            st.error(f"❌ Failed to generate analysis: {e}")