File size: 4,589 Bytes
f619900
 
 
 
 
 
 
 
 
 
 
 
 
 
6f25c56
 
f619900
 
6f25c56
f619900
 
 
 
 
 
 
 
 
cedea36
f619900
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cedea36
 
 
 
 
f619900
 
 
 
cedea36
 
 
f619900
cedea36
f619900
cedea36
f619900
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cedea36
f619900
 
 
cedea36
 
 
 
f619900
 
 
 
 
 
 
 
cedea36
 
 
 
f619900
 
 
 
 
 
 
 
 
 
 
 
cedea36
 
f619900
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# 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()