BasitAliii commited on
Commit
d2d61af
·
verified ·
1 Parent(s): 0d0e01d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -66
app.py CHANGED
@@ -5,9 +5,15 @@ import faiss
5
  from sentence_transformers import SentenceTransformer
6
  from groq import Groq
7
 
8
- # Initialize LLM and embeddings
9
- client = Groq()
 
 
 
 
 
10
  embedder = SentenceTransformer("all-MiniLM-L6-v2")
 
11
  EMBED_DIM = 384
12
  faiss_index = faiss.IndexFlatIP(EMBED_DIM)
13
  candidates = []
@@ -26,94 +32,158 @@ def llm_generate(prompt: str):
26
  )
27
  return completion.choices[0].message.content
28
 
29
- # ---------------- FUNCTIONALITY ----------------
30
-
31
  def add_candidate(name, skills, experience):
32
- profile_text = f"Name: {name}\nSkills: {skills}\nExperience: {experience}"
33
- vec = embed_text(profile_text)
 
 
 
34
  faiss_index.add(vec)
35
- candidates.append(profile_text)
36
- return f"Candidate '{name}' added successfully!"
 
37
 
38
  def generate_bio(raw_data):
39
- prompt = f"""You are a professional HR recruiter.
40
- Write a concise, formal candidate bio using the data below.
 
 
41
  Rules:
42
  - Professional tone
43
- - No exaggeration
44
  - No emojis
 
45
  - Max 120 words
46
 
47
  Candidate Data:
48
- {raw_data}"""
 
49
  return llm_generate(prompt)
50
 
51
  def rewrite_job(job_desc):
52
- prompt = f"""Rewrite the job description below to comply with professional recruitment standards.
53
- Ensure it is inclusive, clear, and well-structured.
 
54
 
55
  Job Description:
56
- {job_desc}"""
 
57
  return llm_generate(prompt)
58
 
59
  def recommend_candidates(job_query):
60
- if len(candidates) == 0:
61
- return "No candidates available.", "", ""
62
-
63
  job_vec = embed_text(job_query)
64
  scores, ids = faiss_index.search(job_vec, k=min(3, len(candidates)))
65
-
66
- top_candidates = []
67
- explanations = []
68
-
69
- for rank, idx in enumerate(ids[0]):
70
  candidate = candidates[idx]
71
- explain_prompt = f"""Explain why the candidate below is a good match for the job.
72
- Base reasoning only on skills and experience.
73
- Keep it concise and professional.
74
 
75
  Candidate:
76
  {candidate}
77
 
78
- Job:
79
- {job_query}"""
80
- explanation = llm_generate(explain_prompt)
81
- top_candidates.append(f"Rank {rank+1}: {candidate}")
82
- explanations.append(explanation)
83
-
84
- return "\n\n".join(top_candidates), "\n\n".join(explanations), "Done"
85
-
86
- # ---------------- GRADIO INTERFACE ----------------
87
-
88
- with gr.Blocks() as demo:
89
- gr.Markdown("# AI-Powered Recruitment MVP")
90
-
91
- with gr.Tab("Add Candidate"):
92
- name_input = gr.Textbox(label="Candidate Name")
93
- skills_input = gr.Textbox(label="Skills")
94
- exp_input = gr.Textbox(label="Experience")
95
- add_btn = gr.Button("Add Candidate")
96
- add_output = gr.Textbox(label="Status")
97
- add_btn.click(add_candidate, inputs=[name_input, skills_input, exp_input], outputs=add_output)
98
-
99
- with gr.Tab("Candidate Bio Generator"):
100
- raw_input = gr.Textbox(label="Candidate Raw Data", lines=5)
101
- bio_btn = gr.Button("Generate Bio")
102
- bio_output = gr.Textbox(label="Candidate Bio", lines=5)
103
- bio_btn.click(generate_bio, inputs=raw_input, outputs=bio_output)
104
-
105
- with gr.Tab("Job Description Filter"):
106
- job_input = gr.Textbox(label="Job Description", lines=5)
107
- rewrite_btn = gr.Button("Rewrite Job")
108
- rewrite_output = gr.Textbox(label="Rewritten Job Description", lines=5)
109
- rewrite_btn.click(rewrite_job, inputs=job_input, outputs=rewrite_output)
110
-
111
- with gr.Tab("Candidate Recommendation"):
112
- query_input = gr.Textbox(label="Job Requirements", lines=5)
113
- rec_btn = gr.Button("Recommend Candidates")
114
- rec_candidates = gr.Textbox(label="Top Candidates", lines=5)
115
- rec_explanation = gr.Textbox(label="Recommendation Explanation", lines=10)
116
- rec_status = gr.Textbox(label="Status")
117
- rec_btn.click(recommend_candidates, inputs=query_input, outputs=[rec_candidates, rec_explanation, rec_status])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
  demo.launch()
 
5
  from sentence_transformers import SentenceTransformer
6
  from groq import Groq
7
 
8
+ # ---------------- CONFIG ----------------
9
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY")
10
+ if not GROQ_API_KEY:
11
+ raise ValueError("GROQ_API_KEY not found. Please set it in Hugging Face Secrets.")
12
+
13
+ # ---------------- INIT ----------------
14
+ client = Groq(api_key=GROQ_API_KEY)
15
  embedder = SentenceTransformer("all-MiniLM-L6-v2")
16
+
17
  EMBED_DIM = 384
18
  faiss_index = faiss.IndexFlatIP(EMBED_DIM)
19
  candidates = []
 
32
  )
33
  return completion.choices[0].message.content
34
 
35
+ # ---------------- CORE FEATURES ----------------
 
36
  def add_candidate(name, skills, experience):
37
+ if not name or not skills:
38
+ return "⚠️ Please fill in required fields."
39
+
40
+ profile = f"Name: {name}\nSkills: {skills}\nExperience: {experience}"
41
+ vec = embed_text(profile)
42
  faiss_index.add(vec)
43
+ candidates.append(profile)
44
+
45
+ return f"✅ Candidate **{name}** added successfully."
46
 
47
  def generate_bio(raw_data):
48
+ prompt = f"""
49
+ You are a professional HR recruiter.
50
+ Write a concise, formal candidate bio.
51
+
52
  Rules:
53
  - Professional tone
 
54
  - No emojis
55
+ - No exaggeration
56
  - Max 120 words
57
 
58
  Candidate Data:
59
+ {raw_data}
60
+ """
61
  return llm_generate(prompt)
62
 
63
  def rewrite_job(job_desc):
64
+ prompt = f"""
65
+ Rewrite the job description below to meet modern recruitment standards.
66
+ Make it inclusive, clear, and well-structured.
67
 
68
  Job Description:
69
+ {job_desc}
70
+ """
71
  return llm_generate(prompt)
72
 
73
  def recommend_candidates(job_query):
74
+ if not candidates:
75
+ return "No candidates available.", "", "⚠️ Add candidates first."
76
+
77
  job_vec = embed_text(job_query)
78
  scores, ids = faiss_index.search(job_vec, k=min(3, len(candidates)))
79
+
80
+ ranked = []
81
+ reasons = []
82
+
83
+ for i, idx in enumerate(ids[0]):
84
  candidate = candidates[idx]
85
+ explain_prompt = f"""
86
+ Explain why this candidate matches the job.
87
+ Focus only on skills and experience.
88
 
89
  Candidate:
90
  {candidate}
91
 
92
+ Job Requirements:
93
+ {job_query}
94
+ """
95
+ ranked.append(f"### Rank {i+1}\n{candidate}")
96
+ reasons.append(llm_generate(explain_prompt))
97
+
98
+ return "\n\n".join(ranked), "\n\n".join(reasons), "✅ Recommendations generated"
99
+
100
+ # ---------------- UI ----------------
101
+ theme = gr.themes.Soft(
102
+ primary_hue="blue",
103
+ secondary_hue="slate",
104
+ neutral_hue="gray",
105
+ )
106
+
107
+ with gr.Blocks(theme=theme) as demo:
108
+
109
+ gr.Markdown("""
110
+ # 🤖 AI Recruitment Assistant
111
+ **Smart hiring tools for modern recruiters**
112
+ """)
113
+
114
+ gr.Markdown("---")
115
+
116
+ with gr.Tabs():
117
+
118
+ with gr.Tab("➕ Add Candidate"):
119
+ gr.Markdown("### Candidate Profile Entry")
120
+
121
+ with gr.Row():
122
+ with gr.Column():
123
+ name = gr.Textbox(label="Candidate Name *", placeholder="e.g. Ali Khan")
124
+ skills = gr.Textbox(label="Key Skills *", placeholder="Python, React, SQL, ML")
125
+ experience = gr.Textbox(label="Experience Summary", lines=4)
126
+
127
+ add_btn = gr.Button("Add Candidate", variant="primary")
128
+ status = gr.Markdown()
129
+
130
+ with gr.Column():
131
+ gr.Markdown("""
132
+ #### 💡 Tips
133
+ - Be specific with skills
134
+ - Mention years & domain
135
+ - Clean data = better matching
136
+ """)
137
+
138
+ add_btn.click(add_candidate, [name, skills, experience], status)
139
+
140
+ with gr.Tab("🧾 Candidate Bio Generator"):
141
+ raw_data = gr.Textbox(lines=6, placeholder="Paste candidate CV data...")
142
+ bio_btn = gr.Button("Generate Bio", variant="primary")
143
+ bio_output = gr.Textbox(lines=6, label="Generated Bio")
144
+
145
+ bio_btn.click(generate_bio, raw_data, bio_output)
146
+
147
+ with gr.Tab("📄 Job Description Optimizer"):
148
+ job_desc = gr.Textbox(lines=6, placeholder="Paste job description...")
149
+ rewrite_btn = gr.Button("Rewrite Professionally", variant="primary")
150
+ rewrite_output = gr.Textbox(lines=6)
151
+
152
+ rewrite_btn.click(rewrite_job, job_desc, rewrite_output)
153
+
154
+ with gr.Tab("🎯 Candidate Recommendation"):
155
+ job_query = gr.Textbox(lines=5, placeholder="Enter job requirements...")
156
+ rec_btn = gr.Button("Find Best Matches", variant="primary")
157
+
158
+ with gr.Row():
159
+ rec_candidates = gr.Markdown()
160
+ rec_explanation = gr.Textbox(lines=10)
161
+
162
+ rec_status = gr.Markdown()
163
+
164
+ rec_btn.click(
165
+ recommend_candidates,
166
+ job_query,
167
+ [rec_candidates, rec_explanation, rec_status]
168
+ )
169
+
170
+ with gr.Tab("📘 About This App"):
171
+ gr.Markdown("""
172
+ ## What is this application?
173
+ An AI-powered recruitment assistant that automates:
174
+ - Candidate shortlisting
175
+ - Bio generation
176
+ - Job optimization
177
+ - Intelligent matching
178
+
179
+ ## Example
180
+ Job: *Python developer with ML experience*
181
+ Output: Ranked candidates with explanations
182
+
183
+ ## Tech Stack
184
+ Groq • FAISS • Sentence Transformers • Gradio
185
+ """)
186
+
187
+ gr.Markdown("--- Built for Hugging Face Spaces 🚀")
188
 
189
  demo.launch()