devmalik-official commited on
Commit
d57e12f
·
verified ·
1 Parent(s): 03de778

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -180
app.py CHANGED
@@ -1,215 +1,100 @@
1
  import gradio as gr
2
- import json
3
- from pathlib import Path
4
- from utils.ai_analyzer import analyze_resume_with_openai
5
- from config.settings import ALLOWED_EXTENSIONS
6
 
7
- # Global state
8
- resume_text_state = ""
9
- analysis_result_state = None
10
 
 
 
 
11
 
12
- def process_resume_file(file_obj):
13
- if file_obj is None:
14
- return "❌ Please upload a resume file", ""
15
 
16
  try:
17
- # file_obj is a filepath string from Gradio's File component
18
- file_path = Path(file_obj)
19
- file_ext = file_path.suffix.lower()
 
 
 
 
 
20
 
21
- if file_ext not in ALLOWED_EXTENSIONS:
22
- return f"❌ Unsupported file format. Supported: {', '.join(ALLOWED_EXTENSIONS)}", ""
 
 
23
 
24
- # Read the file directly from the path
25
- with open(file_path, 'rb') as f:
26
- from utils.resume_parser import parse_resume
27
- resume_text = parse_resume(f.read(), file_ext)
28
 
29
- global resume_text_state
30
- resume_text_state = resume_text
31
-
32
- return f"✅ Resume loaded successfully: {file_path.name}", resume_text
33
-
34
- except Exception as e:
35
- return f"❌ Error reading file: {str(e)}", ""
36
-
37
-
38
- def analyze_with_ai(resume_text_input):
39
- if not resume_text_input or resume_text_input.strip() == "":
40
- return "❌ Please upload and load a resume first", "", "", "", "", ""
41
-
42
- try:
43
- global analysis_result_state
44
- analysis = analyze_resume_with_openai(resume_text_input)
45
- analysis_result_state = analysis
46
-
47
- return (
48
- format_overall_section(analysis),
49
- format_skills_section(analysis),
50
- format_experience_section(analysis),
51
- format_education_section(analysis),
52
- format_gaps_section(analysis),
53
- format_recommendations_section(analysis),
54
- )
55
 
56
  except Exception as e:
57
- return f"Error during analysis: {str(e)}", "", "", "", "", ""
58
-
59
-
60
- def format_overall_section(analysis):
61
- score = analysis.get("overall_score", {}).get("rating", 0)
62
- explanation = analysis.get("overall_score", {}).get("explanation", "")
63
- summary = analysis.get("summary", "")
64
-
65
- return f"""## 📊 Overall Assessment
66
-
67
- **Score: {score}/100**
68
-
69
- **Explanation:** {explanation}
70
-
71
- ### 📝 Executive Summary
72
- {summary}
73
- """
74
-
75
-
76
- def format_skills_section(analysis):
77
- skills = analysis.get("skills", {})
78
- output = "## 🔧 Skills Analysis\n\n### Technical Skills\n"
79
-
80
- technical = skills.get("technical", [])
81
- output += "\n".join([f"- {s}" for s in technical]) if technical else "- No technical skills identified\n"
82
-
83
- output += "\n\n### Soft Skills\n"
84
- soft = skills.get("soft", [])
85
- output += "\n".join([f"- {s}" for s in soft]) if soft else "- No soft skills identified\n"
86
-
87
- output += "\n\n### Skills to Develop\n"
88
- missing = skills.get("missing", [])
89
- output += "\n".join([f"- ❌ {s}" for s in missing]) if missing else "- No significant gaps identified\n"
90
 
91
- return output
92
 
 
93
 
94
- def format_experience_section(analysis):
95
- experience = analysis.get("experience", {})
96
- output = "## 💼 Experience Review\n\n### Highlights\n"
97
 
98
- for h in experience.get("highlights", []):
99
- output += f"- ✅ {h}\n"
 
 
 
100
 
101
- output += "\n### Concerns\n"
102
- for c in experience.get("concerns", []):
103
- output += f"- ⚠️ {c}\n"
104
 
105
- return output
 
 
106
 
 
107
 
108
- def format_education_section(analysis):
109
- education = analysis.get("education", {})
110
- return f"""## 🎓 Education Background
111
 
112
- **Details:** {education.get('details', 'No education information provided')}
 
113
 
114
- **Relevance:** {education.get('relevant', 'N/A')}
 
 
 
 
115
  """
116
 
 
117
 
118
- def format_gaps_section(analysis):
119
- output = "## 🔍 Career Gaps & Concerns\n\n"
120
-
121
- gaps = analysis.get("career_gaps", [])
122
- output += "\n".join([f"- {g}" for g in gaps]) if gaps else "✅ No significant career gaps identified\n"
123
-
124
- job_compat = analysis.get("job_compatibility", {})
125
- output += "\n\n## 🎯 Job Market Compatibility\n\n### Strengths\n"
126
-
127
- for s in job_compat.get("strengths", []):
128
- output += f"- ✅ {s}\n"
129
-
130
- output += "\n### Areas to Improve\n"
131
- for w in job_compat.get("weaknesses", []):
132
- output += f"- ⚠️ {w}\n"
133
-
134
- return output
135
-
136
-
137
- def format_recommendations_section(analysis):
138
- recs = analysis.get("recommendations", [])
139
- output = "## 💡 Improvement Recommendations\n\n"
140
-
141
- for i, r in enumerate(recs, 1):
142
- output += f"{i}. {r}\n"
143
-
144
- return output if recs else output + "No specific recommendations available\n"
145
-
146
-
147
- def export_json(_):
148
- if analysis_result_state is None:
149
- return "No analysis available to export"
150
-
151
- return json.dumps(analysis_result_state, indent=2)
152
-
153
-
154
- def export_text(_):
155
- if analysis_result_state is None:
156
- return "No analysis available to export"
157
-
158
- analysis = analysis_result_state
159
- report = "RESUME ANALYSIS REPORT\n" + "=" * 60 + "\n\n"
160
- report += f"OVERALL SCORE: {analysis.get('overall_score', {}).get('rating', 0)}/100\n"
161
- report += f"Rating: {analysis.get('overall_score', {}).get('explanation', '')}\n\n"
162
- report += analysis.get("summary", "")
163
-
164
- return report
165
-
166
-
167
- def create_interface():
168
- with gr.Blocks(title="Resume Analyzer", theme=gr.themes.Soft()) as demo:
169
 
170
- gr.Markdown("""
171
- # 📄 Resume Analyzer
172
- ### AI-Powered Resume Analysis & Recommendations
173
- """)
174
 
175
- with gr.Tab("📤 Upload & Analyze"):
176
- file_upload = gr.File(label="Upload Resume", file_types=[".pdf", ".docx", ".doc", ".txt"], type="filepath")
177
- load_button = gr.Button("📖 Load Resume")
178
- status_output = gr.Textbox(label="Status", interactive=False)
179
- resume_preview = gr.Textbox(label="Resume Preview", lines=10, interactive=False)
180
- analyze_button = gr.Button("🤖 Analyze with AI", variant="primary")
181
 
182
- overall_output = gr.Markdown()
183
- skills_output = gr.Markdown()
184
- experience_output = gr.Markdown()
185
- education_output = gr.Markdown()
186
- gaps_output = gr.Markdown()
187
- recommendations_output = gr.Markdown()
188
 
189
- load_button.click(process_resume_file, file_upload, [status_output, resume_preview])
190
- analyze_button.click(
191
- analyze_with_ai,
192
- resume_preview,
193
- [overall_output, skills_output, experience_output, education_output, gaps_output, recommendations_output]
194
- )
195
 
196
- with gr.Tab("📥 Export Results"):
197
- json_btn = gr.Button("📋 Export as JSON")
198
- json_output = gr.Textbox(lines=15, interactive=False)
199
 
200
- text_btn = gr.Button("📄 Export as Text")
201
- text_output = gr.Textbox(lines=15, interactive=False)
 
 
202
 
203
- json_btn.click(export_json, inputs=[], outputs=json_output)
204
- text_btn.click(export_text, inputs=[], outputs=text_output)
 
 
 
205
 
206
- return demo
207
 
 
208
 
209
  if __name__ == "__main__":
210
- demo = create_interface()
211
- demo.launch(
212
- server_name="0.0.0.0",
213
- server_port=7861,
214
- share=True
215
- )
 
1
  import gradio as gr
2
+ import pdfplumber
3
+ import docx
 
 
4
 
5
+ # -------- Resume Text Extraction -------- #
 
 
6
 
7
+ def extract_text(file):
8
+ if file is None:
9
+ return "Please upload a resume."
10
 
11
+ file_name = file.name
 
 
12
 
13
  try:
14
+ # PDF
15
+ if file_name.endswith(".pdf"):
16
+ text = ""
17
+ with pdfplumber.open(file) as pdf:
18
+ for page in pdf.pages:
19
+ page_text = page.extract_text()
20
+ if page_text:
21
+ text += page_text
22
 
23
+ # DOCX
24
+ elif file_name.endswith(".docx"):
25
+ doc = docx.Document(file)
26
+ text = "\n".join([p.text for p in doc.paragraphs])
27
 
28
+ else:
29
+ return "Unsupported file format. Upload PDF or DOCX."
 
 
30
 
31
+ return analyze_resume(text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
  except Exception as e:
34
+ return f"Error reading file: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
 
36
 
37
+ # -------- Resume Analyzer -------- #
38
 
39
+ def analyze_resume(text):
 
 
40
 
41
+ skills = [
42
+ "python","machine learning","deep learning","data science",
43
+ "sql","pandas","numpy","tensorflow","pytorch",
44
+ "nlp","git","docker","flask","fastapi"
45
+ ]
46
 
47
+ found_skills = []
 
 
48
 
49
+ for skill in skills:
50
+ if skill.lower() in text.lower():
51
+ found_skills.append(skill)
52
 
53
+ score = min(len(found_skills) * 10, 100)
54
 
55
+ result = f"""
56
+ Resume Score: {score}/100
 
57
 
58
+ Detected Skills:
59
+ {', '.join(found_skills) if found_skills else 'No major skills detected'}
60
 
61
+ Suggestions:
62
+ • Add more technical skills
63
+ • Include projects
64
+ • Mention measurable achievements
65
+ • Use clear headings
66
  """
67
 
68
+ return result
69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
+ # -------- Gradio UI -------- #
 
 
 
72
 
73
+ with gr.Blocks(title="Resume Analyzer") as demo:
 
 
 
 
 
74
 
75
+ gr.Markdown("# 📄 AI Resume Analyzer")
76
+ gr.Markdown("Upload your resume and get instant feedback.")
 
 
 
 
77
 
78
+ resume_input = gr.File(
79
+ label="Upload Resume",
80
+ file_types=[".pdf", ".docx"]
81
+ )
 
 
82
 
83
+ analyze_btn = gr.Button("Analyze Resume")
 
 
84
 
85
+ output_box = gr.Textbox(
86
+ label="Analysis Result",
87
+ lines=15
88
+ )
89
 
90
+ analyze_btn.click(
91
+ fn=extract_text,
92
+ inputs=resume_input,
93
+ outputs=output_box
94
+ )
95
 
 
96
 
97
+ # -------- Launch App -------- #
98
 
99
  if __name__ == "__main__":
100
+ demo.launch()