File size: 3,755 Bytes
94516ce
646e4f3
9480219
94516ce
 
 
 
9480219
94516ce
863e40a
94516ce
 
 
 
 
 
 
8d505f4
 
 
 
c045a8c
9480219
 
8d505f4
 
 
 
 
 
94516ce
 
8d505f4
 
 
 
 
 
94516ce
8d505f4
 
 
4d83474
9480219
4d83474
 
 
 
8d505f4
9480219
863e40a
 
 
 
8d505f4
863e40a
94516ce
 
 
 
a69a9de
863e40a
a69a9de
 
 
863e40a
 
 
 
 
a69a9de
 
 
 
 
 
863e40a
a69a9de
 
 
 
 
 
863e40a
a69a9de
 
 
 
 
 
863e40a
94516ce
a69a9de
 
 
 
 
 
94516ce
 
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
# app.py

import os
import gradio as gr
from text_extractor import extract_text_from_file
from embedder import get_embeddings
from vector_store import create_faiss_index, search_similar_cvs
from groq_api import summarize_match

# Global state
cv_texts = []
cv_names = []
cv_vectors = []
faiss_index = None

def upload_cvs(files):
    global cv_texts, cv_names, cv_vectors, faiss_index
    try:
        cv_texts = [extract_text_from_file(f.name) for f in files]
        cv_names = [f.name for f in files]
        cv_vectors = get_embeddings(cv_texts)

        import numpy as np
        if cv_vectors is None or np.array(cv_vectors).size == 0:
            return "❌ No valid CVs extracted or embedded."

        faiss_index = create_faiss_index(cv_vectors)
        return f"βœ… Uploaded and indexed {len(files)} CVs."
    except Exception as e:
        return f"❌ Error during upload: {e}"

def match_jd(jd_text):
    global faiss_index
    try:
        if not faiss_index:
            return "❌ Please upload CVs first."
        if not jd_text.strip():
            return "❌ Job description is empty."

        jd_vector = get_embeddings([jd_text])[0]
        top_k_indices = search_similar_cvs(jd_vector, faiss_index, k=3)

        import os
        matched_names = [os.path.basename(cv_names[i]) for i in top_k_indices]
        matched_texts = [
            cv_texts[i][:500] if cv_texts[i].strip() else "[No CV content]"
            for i in top_k_indices
        ]

        summary = summarize_match(jd_text, matched_names, matched_texts)
        return f"""
βœ… <span style='color:#16a34a; font-weight:bold;'>Top Matches:</span><br>{matched_names}<br><br>
πŸ“ <span style='color:#3b82f6; font-weight:bold;'>Summary:</span><br>{summary}
"""
    except Exception as e:
        return f"<span style='color:red;'>❌ Error during matching: {e}</span>"

def clear_data():
    global cv_texts, cv_names, cv_vectors, faiss_index
    cv_texts, cv_names, cv_vectors, faiss_index = [], [], [], None
    return "🧹 All data cleared. You can now start fresh."

# ======================
# TABBED PROFESSIONAL UI
# ======================
with gr.Blocks(css="""
    .gr-button { background-color: #2563eb; color: white; font-weight: bold; }
    .gr-button:hover { background-color: #1d4ed8; }
    textarea, input[type='file'] { border: 2px solid #3b82f6 !important; }
    .gr-textbox label { color: #111827; font-weight: 600; }
""") as upload_tab:
    gr.Markdown("## πŸ“€ Upload CVs")
    gr.Markdown("Upload candidate CVs in PDF or DOCX format.")
    cv_upload = gr.File(label="Upload CVs", file_types=[".pdf", ".docx"], file_count="multiple")
    upload_button = gr.Button("πŸ“ Upload & Index CVs")
    upload_status = gr.Textbox(label="Status", interactive=False)
    upload_button.click(upload_cvs, inputs=[cv_upload], outputs=[upload_status])

with gr.Blocks() as match_tab:
    gr.Markdown("## πŸ“‹ Match Job Description to CVs")
    jd_input = gr.Textbox(label="Paste Job Description", lines=8, placeholder="e.g. Looking for a Python Data Analyst...")
    match_button = gr.Button("πŸ” Match CVs")
    match_result = gr.HTML()
    match_button.click(match_jd, inputs=[jd_input], outputs=[match_result])

with gr.Blocks() as reset_tab:
    gr.Markdown("## 🧹 Clear All Data")
    gr.Markdown("Click below to reset the app and upload new CVs.")
    clear_button = gr.Button("Reset App")
    clear_output = gr.Textbox(label="Reset Status", interactive=False)
    clear_button.click(clear_data, inputs=[], outputs=[clear_output])

# Menu Bar Style Tabs
app = gr.TabbedInterface(
    interface_list=[upload_tab, match_tab, reset_tab],
    tab_names=["πŸ“€ Upload CVs", "πŸ“‹ Match JD", "🧹 Reset"]
)

if __name__ == "__main__":
    app.launch()