Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,24 +1,88 @@
|
|
| 1 |
import streamlit as st
|
| 2 |
import requests
|
| 3 |
import os
|
|
|
|
| 4 |
|
| 5 |
-
|
| 6 |
-
BACKEND_URL = "http://127.0.0.1:8000/process-resume"
|
| 7 |
|
| 8 |
-
|
|
|
|
|
|
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
if uploaded_file:
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import streamlit as st
|
| 2 |
import requests
|
| 3 |
import os
|
| 4 |
+
from dotenv import load_dotenv
|
| 5 |
|
| 6 |
+
load_dotenv()
|
|
|
|
| 7 |
|
| 8 |
+
# Configuration
|
| 9 |
+
# Defaults to localhost for dev, but can be overridden in production (e.g., Docker)
|
| 10 |
+
BACKEND_URL = os.getenv("BACKEND_URL", "http://127.0.0.1:8000/process-resume")
|
| 11 |
|
| 12 |
+
st.set_page_config(page_title="AI Resume Analyzer", page_icon="π", layout="centered")
|
| 13 |
+
|
| 14 |
+
st.title("π Intelligent Resume Parser")
|
| 15 |
+
st.markdown("---")
|
| 16 |
+
st.write("Upload a professional resume in PDF format to extract key insights using AI.")
|
| 17 |
+
|
| 18 |
+
# Sidebar for status
|
| 19 |
+
with st.sidebar:
|
| 20 |
+
st.info(f"Connected to Backend: `{BACKEND_URL}`")
|
| 21 |
+
|
| 22 |
+
uploaded_file = st.file_uploader("Upload PDF Resume", type="pdf")
|
| 23 |
|
| 24 |
if uploaded_file:
|
| 25 |
+
# Basic Frontend Validation
|
| 26 |
+
if uploaded_file.size > 5 * 1024 * 1024:
|
| 27 |
+
st.error("File is too large! Please upload a file smaller than 5MB.")
|
| 28 |
+
else:
|
| 29 |
+
if st.button("Analyze Resume", type="primary"):
|
| 30 |
+
with st.spinner("Processing with AI..."):
|
| 31 |
+
try:
|
| 32 |
+
files = {
|
| 33 |
+
"file": (uploaded_file.name, uploaded_file.getvalue(), "application/pdf")
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
# Set a timeout to prevent hanging
|
| 37 |
+
response = requests.post(BACKEND_URL, files=files, timeout=30)
|
| 38 |
+
|
| 39 |
+
if response.status_code == 200:
|
| 40 |
+
data = response.json()
|
| 41 |
+
|
| 42 |
+
# Handle case where AI returns an error key
|
| 43 |
+
if "error" in data:
|
| 44 |
+
st.error(data["error"])
|
| 45 |
+
else:
|
| 46 |
+
st.success("Extraction Complete!")
|
| 47 |
+
|
| 48 |
+
# Summary Section
|
| 49 |
+
st.markdown("### π Professional Summary")
|
| 50 |
+
st.info(data.get('summary', 'No summary available.'))
|
| 51 |
+
|
| 52 |
+
# Contact Info
|
| 53 |
+
st.markdown("### π Contact Details")
|
| 54 |
+
c1, c2, c3 = st.columns(3)
|
| 55 |
+
c1.metric("Name", data.get('name', 'N/A'))
|
| 56 |
+
c2.metric("Email", data.get('email', 'N/A'))
|
| 57 |
+
c3.metric("Phone", data.get('phone', 'N/A'))
|
| 58 |
+
|
| 59 |
+
# Skills Section
|
| 60 |
+
st.markdown("### π Technical Skills")
|
| 61 |
+
skills = data.get('skills', [])
|
| 62 |
+
if skills and isinstance(skills, list):
|
| 63 |
+
# CSS styling for tags
|
| 64 |
+
st.markdown(
|
| 65 |
+
f"""
|
| 66 |
+
<div style="display: flex; flex-wrap: wrap; gap: 10px;">
|
| 67 |
+
{''.join([f'<span style="background-color: #e0f2f1; color: #00695c; padding: 5px 10px; border-radius: 15px; font-size: 14px;">{skill}</span>' for skill in skills])}
|
| 68 |
+
</div>
|
| 69 |
+
""",
|
| 70 |
+
unsafe_allow_html=True
|
| 71 |
+
)
|
| 72 |
+
else:
|
| 73 |
+
st.write("No specific skills detected.")
|
| 74 |
+
|
| 75 |
+
with st.expander("View Raw JSON Data"):
|
| 76 |
+
st.json(data)
|
| 77 |
+
|
| 78 |
+
elif response.status_code == 413:
|
| 79 |
+
st.error("The file is too large for the server to process.")
|
| 80 |
+
else:
|
| 81 |
+
st.error(f"Server Error: {response.status_code} - {response.text}")
|
| 82 |
+
|
| 83 |
+
except requests.exceptions.ConnectionError:
|
| 84 |
+
st.error("π¨ Connection Failed: Could not reach the backend server.")
|
| 85 |
+
except requests.exceptions.Timeout:
|
| 86 |
+
st.error("π¨ Request Timed Out: The AI took too long to respond.")
|
| 87 |
+
except Exception as e:
|
| 88 |
+
st.error(f"An unexpected error occurred: {e}")
|