Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import numpy as np | |
| 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 storage | |
| cv_texts = [] | |
| cv_names = [] | |
| cv_vectors = [] | |
| faiss_index = None | |
| def upload_cvs(files): | |
| global cv_texts, cv_names, cv_vectors, faiss_index | |
| try: | |
| if len(files) > 10: | |
| return "β Limit exceeded: Upload a maximum of 10 CVs." | |
| # Remove duplicates based on filename | |
| unique_files = [] | |
| seen = set() | |
| for f in files: | |
| if f.name not in seen: | |
| seen.add(f.name) | |
| unique_files.append(f) | |
| files = unique_files | |
| cv_texts = [extract_text_from_file(f) for f in files] | |
| cv_names = [f.name for f in files] | |
| cv_vectors = get_embeddings(cv_texts) | |
| if cv_vectors is None or np.array(cv_vectors).size == 0: | |
| return "β No valid CVs." | |
| faiss_index = create_faiss_index(cv_vectors) | |
| return f"β Uploaded and indexed {len(files)} CV(s)." | |
| except Exception as e: | |
| return f"β Error during upload: {e}" | |
| def match_jd(jd_text, match_mode): | |
| if faiss_index is None: | |
| return "β Please upload CVs first." | |
| if not jd_text.strip(): | |
| return "β οΈ Job description is empty." | |
| try: | |
| jd_vector = get_embeddings([jd_text])[0] | |
| # Select CVs based on match mode | |
| if match_mode == "Top 3 Matches": | |
| indices = search_similar_cvs(jd_vector, faiss_index, k=3) | |
| else: # All uploaded CVs | |
| indices = list(range(len(cv_names))) | |
| # Filter duplicates by name | |
| seen = set() | |
| unique_indices = [] | |
| for i in indices: | |
| if cv_names[i] not in seen: | |
| seen.add(cv_names[i]) | |
| unique_indices.append(i) | |
| matched = [cv_names[i] for i in unique_indices] | |
| texts = [cv_texts[i] for i in unique_indices] | |
| summary = summarize_match(jd_text, matched, texts) | |
| title = "β Match Result:" if len(matched) == 1 else f"β Matching {len(matched)} CVs:" | |
| return f"{title}\n\n" + "\n".join(matched) + f"\n\nπ Summary:\n{summary}" | |
| except Exception as e: | |
| return f"β Error during matching: {e}" | |
| def clear_data(): | |
| global cv_texts, cv_names, cv_vectors, faiss_index | |
| cv_texts, cv_names, cv_vectors, faiss_index = [], [], [], None | |
| return "π§Ή Cleared." | |
| with gr.Blocks() as app: | |
| gr.Markdown("## π CV Matcher with Groq API (Dynamic Matching)") | |
| # Upload | |
| file_input = gr.File(file_types=[".pdf", ".docx"], file_count="multiple", label="π€ Upload CVs (Max 10)") | |
| upload_button = gr.Button("π Upload & Index") | |
| upload_status = gr.Textbox(label="Upload Status") | |
| # Job Description Matching | |
| jd_input = gr.Textbox(label="π Paste Job Description", lines=8, placeholder="Paste job description here...") | |
| match_mode = gr.Radio(["Top 3 Matches", "All Uploaded CVs"], value="Top 3 Matches", label="Matching Mode") | |
| match_button = gr.Button("π Match CVs") | |
| result_output = gr.Textbox(label="Match Results", lines=25) | |
| # Clear Session | |
| clear_button = gr.Button("π§Ή Clear All") | |
| clear_status = gr.Textbox(label="Clear Status") | |
| # Actions | |
| upload_button.click(upload_cvs, inputs=[file_input], outputs=[upload_status]) | |
| match_button.click(match_jd, inputs=[jd_input, match_mode], outputs=[result_output]) | |
| clear_button.click(clear_data, inputs=[], outputs=[clear_status]) | |
| app.launch() | |