Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -51,8 +51,9 @@ def extract_basic_resume_info(text):
|
|
51 |
Parse the extracted text to summarize basic info:
|
52 |
- Name
|
53 |
- Age
|
54 |
-
- Work Experience
|
55 |
- Expected Industry/Direction
|
|
|
56 |
"""
|
57 |
info = {
|
58 |
"Name": None,
|
@@ -61,71 +62,93 @@ def extract_basic_resume_info(text):
|
|
61 |
"Expected Industry/Direction": None,
|
62 |
}
|
63 |
|
64 |
-
#
|
65 |
name_match = re.search(r"[Nn]ame[:\-]\s*([A-Za-z\s]+)", text)
|
66 |
if name_match:
|
67 |
info["Name"] = name_match.group(1).strip()
|
68 |
else:
|
69 |
-
#
|
70 |
potential_names = re.findall(r"\b[A-Z][a-z]+(?:\s+[A-Z][a-z]+){1,2}\b", text)
|
71 |
if potential_names:
|
72 |
info["Name"] = potential_names[0]
|
73 |
|
74 |
-
# Extract Age (
|
75 |
age_match = re.search(r"[Aa]ge[:\-]\s*(\d{1,2})", text)
|
76 |
if age_match:
|
77 |
info["Age"] = age_match.group(1)
|
78 |
|
79 |
-
# Extract Work Experience (e.g., "5 years of experience"
|
80 |
exp_match = re.search(r"(\d+)\s+(years|yrs)\s+(?:of\s+)?experience", text, re.IGNORECASE)
|
81 |
if exp_match:
|
82 |
info["Work Experience"] = f"{exp_match.group(1)} {exp_match.group(2)}"
|
83 |
else:
|
84 |
-
#
|
85 |
exp_line = re.search(r"(Experience|Background)[:\-]\s*(.*)", text, re.IGNORECASE)
|
86 |
if exp_line:
|
87 |
info["Work Experience"] = exp_line.group(2).strip()
|
88 |
|
89 |
-
# Extract Expected Industry/Direction
|
90 |
-
# (e.g., "Interest: Software Development" or "Expected Industry: Healthcare")
|
91 |
industry_match = re.search(r"(Industry|Interest|Direction)[:\-]\s*(.+)", text, re.IGNORECASE)
|
92 |
if industry_match:
|
93 |
info["Expected Industry/Direction"] = industry_match.group(2).strip()
|
94 |
|
95 |
return info
|
96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
97 |
#####################################
|
98 |
# Main Resume Processing Logic
|
99 |
#####################################
|
100 |
def process_resume(file_obj):
|
101 |
if file_obj is None:
|
102 |
return None, None
|
|
|
103 |
# Extract text content from the file.
|
104 |
resume_text = extract_text_from_file(file_obj)
|
105 |
-
# Extract
|
106 |
basic_info = extract_basic_resume_info(resume_text)
|
107 |
-
|
|
|
|
|
108 |
|
109 |
#####################################
|
110 |
# Streamlit Interface
|
111 |
#####################################
|
112 |
-
st.title("Resume Summary
|
113 |
st.markdown("""
|
114 |
-
Upload your resume file
|
115 |
-
|
116 |
""")
|
117 |
|
118 |
uploaded_file = st.file_uploader("Upload Resume", type=["doc", "docx"])
|
119 |
|
120 |
-
if st.button("
|
121 |
if uploaded_file is None:
|
122 |
st.error("Please upload a file first.")
|
123 |
else:
|
124 |
-
with st.spinner("
|
125 |
-
resume_text,
|
126 |
-
|
127 |
-
st.subheader("Extracted Resume Text")
|
128 |
-
st.text_area("", resume_text, height=300)
|
129 |
|
130 |
-
st.subheader("Basic
|
131 |
-
st.
|
|
|
51 |
Parse the extracted text to summarize basic info:
|
52 |
- Name
|
53 |
- Age
|
54 |
+
- Work Experience
|
55 |
- Expected Industry/Direction
|
56 |
+
Returns a dictionary of extracted data.
|
57 |
"""
|
58 |
info = {
|
59 |
"Name": None,
|
|
|
62 |
"Expected Industry/Direction": None,
|
63 |
}
|
64 |
|
65 |
+
# Extract Name (e.g., "Name: John Doe")
|
66 |
name_match = re.search(r"[Nn]ame[:\-]\s*([A-Za-z\s]+)", text)
|
67 |
if name_match:
|
68 |
info["Name"] = name_match.group(1).strip()
|
69 |
else:
|
70 |
+
# Heuristic: search for a line with two or three capitalized words.
|
71 |
potential_names = re.findall(r"\b[A-Z][a-z]+(?:\s+[A-Z][a-z]+){1,2}\b", text)
|
72 |
if potential_names:
|
73 |
info["Name"] = potential_names[0]
|
74 |
|
75 |
+
# Extract Age (e.g., "Age: 28")
|
76 |
age_match = re.search(r"[Aa]ge[:\-]\s*(\d{1,2})", text)
|
77 |
if age_match:
|
78 |
info["Age"] = age_match.group(1)
|
79 |
|
80 |
+
# Extract Work Experience (e.g., "5 years of experience")
|
81 |
exp_match = re.search(r"(\d+)\s+(years|yrs)\s+(?:of\s+)?experience", text, re.IGNORECASE)
|
82 |
if exp_match:
|
83 |
info["Work Experience"] = f"{exp_match.group(1)} {exp_match.group(2)}"
|
84 |
else:
|
85 |
+
# Fallback: look for overall experience information.
|
86 |
exp_line = re.search(r"(Experience|Background)[:\-]\s*(.*)", text, re.IGNORECASE)
|
87 |
if exp_line:
|
88 |
info["Work Experience"] = exp_line.group(2).strip()
|
89 |
|
90 |
+
# Extract Expected Industry/Direction
|
|
|
91 |
industry_match = re.search(r"(Industry|Interest|Direction)[:\-]\s*(.+)", text, re.IGNORECASE)
|
92 |
if industry_match:
|
93 |
info["Expected Industry/Direction"] = industry_match.group(2).strip()
|
94 |
|
95 |
return info
|
96 |
|
97 |
+
#####################################
|
98 |
+
# Function: Summarize Basic Info into a Paragraph
|
99 |
+
#####################################
|
100 |
+
def summarize_basic_info(info):
|
101 |
+
"""
|
102 |
+
Create a paragraph summary from the basic resume information.
|
103 |
+
"""
|
104 |
+
parts = []
|
105 |
+
if info.get("Name"):
|
106 |
+
parts.append(f"{info['Name']}")
|
107 |
+
if info.get("Age"):
|
108 |
+
parts.append(f"aged {info['Age']}")
|
109 |
+
if info.get("Work Experience"):
|
110 |
+
parts.append(f"with {info['Work Experience']} of work experience")
|
111 |
+
if info.get("Expected Industry/Direction"):
|
112 |
+
parts.append(f"seeking opportunities in {info['Expected Industry/Direction']}")
|
113 |
+
|
114 |
+
if parts:
|
115 |
+
summary_paragraph = "The candidate is " + ", ".join(parts) + "."
|
116 |
+
else:
|
117 |
+
summary_paragraph = "Basic information could not be extracted from the resume."
|
118 |
+
return summary_paragraph
|
119 |
+
|
120 |
#####################################
|
121 |
# Main Resume Processing Logic
|
122 |
#####################################
|
123 |
def process_resume(file_obj):
|
124 |
if file_obj is None:
|
125 |
return None, None
|
126 |
+
|
127 |
# Extract text content from the file.
|
128 |
resume_text = extract_text_from_file(file_obj)
|
129 |
+
# Extract and summarize basic info.
|
130 |
basic_info = extract_basic_resume_info(resume_text)
|
131 |
+
summary_paragraph = summarize_basic_info(basic_info)
|
132 |
+
|
133 |
+
return resume_text, summary_paragraph
|
134 |
|
135 |
#####################################
|
136 |
# Streamlit Interface
|
137 |
#####################################
|
138 |
+
st.title("Resume Basic Info Summary")
|
139 |
st.markdown("""
|
140 |
+
Upload your resume file in **.doc** or **.docx** format. The app will extract the content and generate a summary paragraph
|
141 |
+
that highlights the candidate's basic information (name, age, work experience, and expected industry/direction).
|
142 |
""")
|
143 |
|
144 |
uploaded_file = st.file_uploader("Upload Resume", type=["doc", "docx"])
|
145 |
|
146 |
+
if st.button("Process Resume"):
|
147 |
if uploaded_file is None:
|
148 |
st.error("Please upload a file first.")
|
149 |
else:
|
150 |
+
with st.spinner("Processing resume..."):
|
151 |
+
resume_text, summary_paragraph = process_resume(uploaded_file)
|
|
|
|
|
|
|
152 |
|
153 |
+
st.subheader("Summary of Basic Information")
|
154 |
+
st.markdown(summary_paragraph)
|