Job_tracker / app.py
Projecthack's picture
Update app.py
6f25c56 verified
Raw
History Blame Contribute Delete
4.59 kB
# Job Tracker Agent - First Version with Gradio + JSON Memory + CSV Export (No OpenAI Key)
# - Uses Hugging Face Inference API (Mistral-7B)
# - Extracts job info from text
# - Saves to JSON + allows CSV export
import gradio as gr
import os
import json
import csv
import requests
from datetime import datetime
JOB_LOG_FILE = "job_memory.json"
CSV_EXPORT_FILE = "job_memory.csv"
HF_API_URL = "https://api-inference.huggingface.co/models/HuggingFaceH4/zephyr-7b-beta"
# Optional: use your Hugging Face token for more reliability
HF_API_TOKEN = os.getenv("HUG_API_TOKEN") # or leave None for free/public use
headers = {"Authorization": f"Bearer {HF_API_TOKEN}"} if HF_API_TOKEN else {}
# Initialize memory file
if not os.path.exists(JOB_LOG_FILE):
with open(JOB_LOG_FILE, "w") as f:
json.dump([], f)
# Extract job info using Hugging Face Inference API
def extract_job_details(text):
prompt = f"""
Extract structured JSON with the following fields from the input text:
- company
- role
- location
- source
- status
- link (if present)
- follow_up_date (in YYYY-MM-DD if mentioned, else null)
Input:
{text}
Output:
"""
payload = {
"inputs": prompt,
"parameters": {"max_new_tokens": 500},
"options": {"wait_for_model": True}
}
try:
response = requests.post(HF_API_URL, headers=headers, json=payload)
response.raise_for_status()
result = response.json()
if isinstance(result, dict) and "error" in result:
return json.dumps(result)
if isinstance(result, list) and "generated_text" in result[0]:
return result[0]["generated_text"].split("Output:")[-1].strip()
return json.dumps({"error": "Unexpected response format"})
except Exception as e:
return json.dumps({"error": str(e)})
# Store to JSON file
def store_job_data(parsed_json):
try:
job_data = json.loads(parsed_json)
job_data["logged_at"] = datetime.now().isoformat()
with open(JOB_LOG_FILE, "r+") as f:
existing = json.load(f)
existing.append(job_data)
f.seek(0)
json.dump(existing, f, indent=2)
return "βœ… Job logged successfully."
except Exception as e:
return f"❌ Error logging job: {e}"
# Read memory safely with missing key handling
def get_job_history():
with open(JOB_LOG_FILE, "r") as f:
entries = json.load(f)
formatted = "\n\n".join([
f"{e.get('role', '[Missing Role]')} at {e.get('company', '[Missing Company]')} ({e.get('status', 'Unknown')}) - {e.get('follow_up_date', 'N/A')}"
for e in entries
])
return formatted or "No jobs tracked yet."
# Export to CSV
def export_to_csv():
try:
with open(JOB_LOG_FILE, "r") as f:
entries = json.load(f)
if entries:
keys = set()
for entry in entries:
keys.update(entry.keys())
keys = sorted(keys)
with open(CSV_EXPORT_FILE, "w", newline='') as f:
writer = csv.DictWriter(f, fieldnames=keys)
writer.writeheader()
writer.writerows(entries)
return f"βœ… Exported to {CSV_EXPORT_FILE}"
return "❌ No job data to export."
except Exception as e:
return f"❌ Export failed: {e}"
# Gradio logic
def job_tracker_interface(user_input):
parsed_json = extract_job_details(user_input)
if "error" in parsed_json:
return parsed_json, "❌ Failed to log job.", get_job_history()
store_status = store_job_data(parsed_json)
memory_state = get_job_history()
return parsed_json, store_status, memory_state
def export_interface():
return export_to_csv()
# Gradio app
demo = gr.Interface(
fn=job_tracker_interface,
inputs=gr.Textbox(lines=10, label="Paste a job description or job-related email"),
outputs=[
gr.Textbox(label="🧠 Extracted Job Info (JSON)"),
gr.Textbox(label="πŸ“₯ Save Status"),
gr.Textbox(label="πŸ“‚ Job Tracker Memory (Current Session)")
],
title="Job Tracker AI (v1) - No OpenAI Key",
description="Paste job descriptions or emails. This AI agent uses Mistral-7B to extract job data, save it in memory, and export to CSV."
)
export_demo = gr.Interface(
fn=export_interface,
inputs=[],
outputs=gr.Textbox(label="πŸ“€ Export Result"),
title="Export to CSV",
description="Click the button below to export your job data to a CSV file."
)
demo.launch()
# Optionally launch CSV export in a separate tab
# export_demo.launch()