Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
| 1 |
# app.py
|
| 2 |
-
|
| 3 |
import os
|
| 4 |
import gradio as gr
|
| 5 |
from PyPDF2 import PdfReader
|
|
@@ -13,7 +12,7 @@ from google.genai.types import GenerateContentConfig, ThinkingConfig
|
|
| 13 |
from datetime import datetime
|
| 14 |
|
| 15 |
# Initialize components
|
| 16 |
-
kw_extractor = yake.KeywordExtractor(n=
|
| 17 |
embedder = SentenceTransformer("all-MiniLM-L6-v2")
|
| 18 |
genai_client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
|
| 19 |
|
|
@@ -32,8 +31,18 @@ def extract_text(file):
|
|
| 32 |
return ""
|
| 33 |
|
| 34 |
# 2️⃣ Extract keywords using YAKE
|
| 35 |
-
def
|
| 36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
# 3️⃣ Fetch jobs from free public APIs
|
| 39 |
def fetch_arbeitnow(keywords):
|
|
@@ -89,9 +98,9 @@ def format_posted(job):
|
|
| 89 |
def find_jobs(file, added_kw, use_ai):
|
| 90 |
resume = extract_text(file) or ""
|
| 91 |
print("Resume", resume)
|
| 92 |
-
|
| 93 |
-
print("
|
| 94 |
-
keywords = [kw.strip() for kw in
|
| 95 |
print("Keywords", keywords)
|
| 96 |
jobs = fetch_arbeitnow(keywords) + fetch_remotive(keywords) + fetch_remoteok(keywords)
|
| 97 |
print("Jobs", jobs)
|
|
@@ -120,25 +129,29 @@ def find_jobs(file, added_kw, use_ai):
|
|
| 120 |
return table, explanation
|
| 121 |
|
| 122 |
# 7️⃣ Jobs in Markdown
|
| 123 |
-
def jobs_to_markdown(table):
|
|
|
|
| 124 |
md = "| Role | Company | Location | Posted | Score | Apply |\n"
|
| 125 |
md += "| --- | ------- | -------- | ------ | ----- | ----- |\n"
|
| 126 |
for row in table:
|
| 127 |
link = f"[Apply]({row['Apply']})" if row['Apply'] else ""
|
| 128 |
md += (
|
| 129 |
-
f"| {row['Role']} | {row['Company']} "
|
| 130 |
-
f"| {row['
|
| 131 |
-
f"| {row['Score']} | {link} |\n"
|
| 132 |
)
|
|
|
|
|
|
|
|
|
|
| 133 |
return md
|
| 134 |
|
| 135 |
-
|
| 136 |
# 7️⃣ Gradio UI
|
| 137 |
-
with gr.Blocks() as demo:
|
| 138 |
gr.Markdown("## 🌍 Global Job Finder (Arbeitnow · Remotive · RemoteOK)")
|
| 139 |
with gr.Row():
|
| 140 |
resume = gr.File(label="Upload Resume (PDF/DOCX)")
|
| 141 |
added = gr.Textbox(label="Add keywords (comma-separated)", placeholder="e.g. Python, ML")
|
|
|
|
|
|
|
| 142 |
use_ai = gr.Checkbox(label="Use AI to refine explanation", value=False)
|
| 143 |
btn = gr.Button("Find Jobs")
|
| 144 |
jobs_md = gr.Markdown()
|
|
|
|
| 1 |
# app.py
|
|
|
|
| 2 |
import os
|
| 3 |
import gradio as gr
|
| 4 |
from PyPDF2 import PdfReader
|
|
|
|
| 12 |
from datetime import datetime
|
| 13 |
|
| 14 |
# Initialize components
|
| 15 |
+
kw_extractor = yake.KeywordExtractor(n=2, top=20)
|
| 16 |
embedder = SentenceTransformer("all-MiniLM-L6-v2")
|
| 17 |
genai_client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
|
| 18 |
|
|
|
|
| 31 |
return ""
|
| 32 |
|
| 33 |
# 2️⃣ Extract keywords using YAKE
|
| 34 |
+
def extract_keywords(text):
|
| 35 |
+
"""
|
| 36 |
+
Returns the top 20 1–2‑gram keywords from the text.
|
| 37 |
+
"""
|
| 38 |
+
kws = kw_extractor.extract_keywords(text)
|
| 39 |
+
# kws is list of (keyword, score). We only want the keyword string.
|
| 40 |
+
return [kw for kw,score in kws]
|
| 41 |
+
|
| 42 |
+
def on_resume_upload(file):
|
| 43 |
+
text = extract_text(file)
|
| 44 |
+
kws = extract_keywords(text)
|
| 45 |
+
return ", ".join(kws)
|
| 46 |
|
| 47 |
# 3️⃣ Fetch jobs from free public APIs
|
| 48 |
def fetch_arbeitnow(keywords):
|
|
|
|
| 98 |
def find_jobs(file, added_kw, use_ai):
|
| 99 |
resume = extract_text(file) or ""
|
| 100 |
print("Resume", resume)
|
| 101 |
+
base_kws = added_kw.split(",") if added_kw.strip() else extract_keywords(resume)[:5]
|
| 102 |
+
print("Base_kws", base_kws)
|
| 103 |
+
keywords = [kw.strip() for kw in base_kws if kw.strip()]
|
| 104 |
print("Keywords", keywords)
|
| 105 |
jobs = fetch_arbeitnow(keywords) + fetch_remotive(keywords) + fetch_remoteok(keywords)
|
| 106 |
print("Jobs", jobs)
|
|
|
|
| 129 |
return table, explanation
|
| 130 |
|
| 131 |
# 7️⃣ Jobs in Markdown
|
| 132 |
+
def jobs_to_markdown(table, explanation):
|
| 133 |
+
# Build the markdown table
|
| 134 |
md = "| Role | Company | Location | Posted | Score | Apply |\n"
|
| 135 |
md += "| --- | ------- | -------- | ------ | ----- | ----- |\n"
|
| 136 |
for row in table:
|
| 137 |
link = f"[Apply]({row['Apply']})" if row['Apply'] else ""
|
| 138 |
md += (
|
| 139 |
+
f"| {row['Role']} | {row['Company']} | {row['Location']} "
|
| 140 |
+
f"| {row['Posted']} | {row['Score']} | {link} |\n"
|
|
|
|
| 141 |
)
|
| 142 |
+
# Append the AI explanation, if any
|
| 143 |
+
if explanation:
|
| 144 |
+
md += "\n---\n**AI Explanation:**\n\n" + explanation
|
| 145 |
return md
|
| 146 |
|
|
|
|
| 147 |
# 7️⃣ Gradio UI
|
| 148 |
+
with gr.Blocks(theme=gr.themes.Base()) as demo:
|
| 149 |
gr.Markdown("## 🌍 Global Job Finder (Arbeitnow · Remotive · RemoteOK)")
|
| 150 |
with gr.Row():
|
| 151 |
resume = gr.File(label="Upload Resume (PDF/DOCX)")
|
| 152 |
added = gr.Textbox(label="Add keywords (comma-separated)", placeholder="e.g. Python, ML")
|
| 153 |
+
|
| 154 |
+
resume.upload(on_resume_upload, inputs=[resume], outputs=[added])
|
| 155 |
use_ai = gr.Checkbox(label="Use AI to refine explanation", value=False)
|
| 156 |
btn = gr.Button("Find Jobs")
|
| 157 |
jobs_md = gr.Markdown()
|