Johnny commited on
Commit
19ea0c5
·
1 Parent(s): 56325dc

mvp app tested, configured postgreSQL Supabase

Browse files
.gitignore CHANGED
@@ -16,4 +16,7 @@ venv/
16
  build/
17
 
18
  # Do not ignore a specific file inside an ignored directory
19
- !build/keep-me.txt
 
 
 
 
16
  build/
17
 
18
  # Do not ignore a specific file inside an ignored directory
19
+ !build/keep-me.txt
20
+
21
+ # ignore cache files
22
+ __pycache__/
__pycache__/config.cpython-311.pyc CHANGED
Binary files a/__pycache__/config.cpython-311.pyc and b/__pycache__/config.cpython-311.pyc differ
 
__pycache__/utils.cpython-311.pyc CHANGED
Binary files a/__pycache__/utils.cpython-311.pyc and b/__pycache__/utils.cpython-311.pyc differ
 
config.py CHANGED
@@ -13,6 +13,17 @@ if not SUPABASE_KEY:
13
  supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
14
 
15
  # Hugging Face API Config
16
- HF_API_URL = "https://api-inference.huggingface.co/models/google/gemma-7b"
17
  HF_API_TOKEN = os.getenv("HF_API_TOKEN")
18
- HF_HEADERS = {"Authorization": f"Bearer {HF_API_TOKEN}"}
 
 
 
 
 
 
 
 
 
 
 
 
13
  supabase = create_client(SUPABASE_URL, SUPABASE_KEY)
14
 
15
  # Hugging Face API Config
16
+ HF_API_URL = "https://router.huggingface.co/hf-inference/models/google/gemma-7b"
17
  HF_API_TOKEN = os.getenv("HF_API_TOKEN")
18
+ HF_HEADERS = {"Authorization": f"Bearer HF_API_TOKEN"}
19
+
20
+ def query(payload):
21
+ """Sends request to Hugging Face inference API."""
22
+ import requests
23
+ response = requests.post(HF_API_URL, headers=HF_HEADERS, json=payload)
24
+
25
+ if response.status_code != 200:
26
+ print(f"Error: {response.status_code}, {response.text}") # Debugging
27
+ return None
28
+
29
+ return response.json()
main.py CHANGED
@@ -1,5 +1,12 @@
1
  import streamlit as st
2
- from utils import process_resumes, generate_pdf_report
 
 
 
 
 
 
 
3
 
4
  def main():
5
  st.title("AI Candidate Screening App")
 
1
  import streamlit as st
2
+ from utils import process_resumes, generate_pdf_report, store_in_supabase, score_candidate, extract_email, parse_resume
3
+ from config import supabase
4
+ from config import HF_API_TOKEN, HF_API_URL, HF_HEADERS
5
+ import fitz # PyMuPDF
6
+ from io import BytesIO
7
+ from dotenv import load_dotenv
8
+ import os
9
+ import requests
10
 
11
  def main():
12
  st.title("AI Candidate Screening App")
utils.py CHANGED
@@ -4,7 +4,10 @@ import json
4
  import re
5
  from io import BytesIO
6
  import supabase
7
- from config import SUPABASE_URL, SUPABASE_KEY, HF_API_TOKEN, HF_API_URL, HF_HEADERS
 
 
 
8
 
9
  def parse_resume(pdf_file):
10
  """Extracts text from a resume PDF."""
@@ -20,8 +23,8 @@ def extract_email(resume_text):
20
  def score_candidate(resume_text, job_description):
21
  """Sends resume and job description to Hugging Face for scoring."""
22
  payload = {"inputs": f"Resume: {resume_text}\nJob Description: {job_description}"}
23
- response = requests.post(HF_API_URL, headers=HF_HEADERS, data=json.dumps(payload))
24
- return response.json().get("score", 0)
25
  # Debugging: Print response
26
  if response.status_code != 200:
27
  print(f"Error: {response.status_code}, {response.text}") # Log any errors
@@ -33,16 +36,18 @@ def score_candidate(resume_text, job_description):
33
  print("Failed to decode JSON response:", response.text) # Debugging output
34
  return 0 # Return default score if JSON decoding fails
35
 
36
- def store_in_supabase(resume_text, score, candidate_name):
37
- """Stores resume data in Supabase."""
38
- email = extract_email(resume_text)
39
  data = {
40
- "name": candidate_name,
41
- "resume": resume_text,
42
- "score": score,
43
- "email": email
 
44
  }
45
- supabase.table("candidates").insert(data).execute()
 
 
46
 
47
  def generate_pdf_report(shortlisted_candidates):
48
  """Generates a PDF summary of shortlisted candidates."""
@@ -50,7 +55,11 @@ def generate_pdf_report(shortlisted_candidates):
50
  doc = fitz.open()
51
  for candidate in shortlisted_candidates:
52
  page = doc.new_page()
53
- page.insert_text((50, 50), f"Candidate: {candidate['name']}\nEmail: {candidate['email']}\nScore: {candidate['score']}\nSummary: {candidate['summary']}")
 
 
 
 
54
  doc.save(pdf)
55
  pdf.seek(0)
56
  return pdf
@@ -62,11 +71,19 @@ def process_resumes(uploaded_files, job_description):
62
  resume_text = parse_resume(pdf_file)
63
  score = score_candidate(resume_text, job_description)
64
  email = extract_email(resume_text)
 
 
 
 
65
  candidates.append({
66
- "name": pdf_file.name,
67
- "resume": resume_text,
68
- "score": score,
69
- "email": email
 
70
  })
71
- store_in_supabase(resume_text, score, pdf_file.name, email)
72
- return sorted(candidates, key=lambda x: x["score"], reverse=True)[:5]
 
 
 
 
4
  import re
5
  from io import BytesIO
6
  import supabase
7
+ from config import SUPABASE_URL, SUPABASE_KEY, HF_API_TOKEN, HF_API_URL, HF_HEADERS, supabase
8
+ #from config import supabase
9
+
10
+ # These functions will be called in the main.py file
11
 
12
  def parse_resume(pdf_file):
13
  """Extracts text from a resume PDF."""
 
23
  def score_candidate(resume_text, job_description):
24
  """Sends resume and job description to Hugging Face for scoring."""
25
  payload = {"inputs": f"Resume: {resume_text}\nJob Description: {job_description}"}
26
+ response = requests.post(HF_API_URL, headers=HF_HEADERS, json=payload)
27
+
28
  # Debugging: Print response
29
  if response.status_code != 200:
30
  print(f"Error: {response.status_code}, {response.text}") # Log any errors
 
36
  print("Failed to decode JSON response:", response.text) # Debugging output
37
  return 0 # Return default score if JSON decoding fails
38
 
39
+ def store_in_supabase(resume_text, score, candidate_name, email, summary):
40
+ """Stores candidate data in Supabase"""
 
41
  data = {
42
+ "name": candidate_name,
43
+ "resume": resume_text,
44
+ "score": score,
45
+ "email": email,
46
+ "summary": summary # Store summary in Supabase
47
  }
48
+
49
+ response = supabase.table("candidates").insert(data).execute()
50
+ print("Inserted into Supabase:", response) # Debugging output
51
 
52
  def generate_pdf_report(shortlisted_candidates):
53
  """Generates a PDF summary of shortlisted candidates."""
 
55
  doc = fitz.open()
56
  for candidate in shortlisted_candidates:
57
  page = doc.new_page()
58
+ summary = candidate.get("summary", "No summary available") # Avoid KeyError
59
+ page.insert_text(
60
+ (50, 50),
61
+ f"Candidate: {candidate['name']}\nEmail: {candidate['email']}\nScore: {candidate['score']}\nSummary: {summary}"
62
+ )
63
  doc.save(pdf)
64
  pdf.seek(0)
65
  return pdf
 
71
  resume_text = parse_resume(pdf_file)
72
  score = score_candidate(resume_text, job_description)
73
  email = extract_email(resume_text)
74
+
75
+ # Generate summary (replace with actual summarization logic later)
76
+ summary = f"{pdf_file.name} has a score of {score} for this job."
77
+
78
  candidates.append({
79
+ "name": pdf_file.name,
80
+ "resume": resume_text,
81
+ "score": score,
82
+ "email": email,
83
+ "summary": summary
84
  })
85
+
86
+ # Store all details including summary in Supabase
87
+ store_in_supabase(resume_text, score, pdf_file.name, email, summary)
88
+
89
+ return sorted(candidates, key=lambda x: x["score"], reverse=True)[:5] # Return top 5 candidates