Spaces:
Build error
Build error
| import gradio as gr | |
| import pdfplumber | |
| from fetcher import fetch_jobs | |
| from formatter import format_jobs | |
| from cover_letter import generate_cover_letter | |
| # store jobs globally so cover letter tab can access them | |
| job_store = [] | |
| def read_cv(cv_file): | |
| if cv_file is None: | |
| return "" | |
| try: | |
| with pdfplumber.open(cv_file.name) as pdf: | |
| text = "" | |
| for page in pdf.pages: | |
| text += page.extract_text() or "" | |
| return text | |
| except Exception as e: | |
| return f"Could not read CV: {e}" | |
| def search_jobs(job_title): | |
| global job_store | |
| jobs = fetch_jobs(job_title) | |
| job_store = jobs | |
| if not jobs: | |
| return "No jobs found. Try a broader search term." | |
| formatted = format_jobs(jobs, job_title, "") | |
| return formatted | |
| def create_cover_letter(job_number, cv_file): | |
| global job_store | |
| cv_text = read_cv(cv_file) | |
| if not cv_text: | |
| return "Please upload your CV first." | |
| if not job_store: | |
| return "Please search for jobs first." | |
| try: | |
| index = int(job_number) - 1 | |
| job = job_store[index] | |
| except Exception: | |
| return "Invalid job number. Please enter a number from the job results." | |
| return generate_cover_letter( | |
| job["title"], | |
| job["company"], | |
| job["description"], | |
| cv_text | |
| ) | |
| with gr.Blocks(title="AI Job Finder Agent") as ui: | |
| gr.Markdown("# 🤖 AI Job Finder Agent") | |
| gr.Markdown("Find remote jobs and generate tailored cover letters from your CV") | |
| with gr.Tab("🔍 Find Jobs"): | |
| job_input = gr.Textbox( | |
| label="What role are you looking for?", | |
| placeholder="e.g. Python Developer, Designer, Data Analyst..." | |
| ) | |
| search_btn = gr.Button("Find Jobs", variant="primary") | |
| job_results = gr.Markdown() | |
| status_text = gr.Textbox(label="Status", interactive=False, value="Idle") | |
| def search_jobs_with_status(job_title): | |
| if not job_title or not job_title.strip(): | |
| return "", "Please enter a search query." | |
| return search_jobs(job_title), "Search completed" | |
| search_btn.click( | |
| fn=search_jobs_with_status, | |
| inputs=[job_input], | |
| outputs=[job_results, status_text] | |
| ) | |
| with gr.Tab("✉️ Generate Cover Letter"): | |
| gr.Markdown("Upload your CV and enter the job number from the search results") | |
| cv_upload = gr.File(label="Upload CV (PDF)", file_types=[".pdf"]) | |
| job_number = gr.Textbox( | |
| label="Job Number", | |
| placeholder="e.g. 1, 2, 3..." | |
| ) | |
| cl_btn = gr.Button("Generate Cover Letter", variant="primary") | |
| cl_output = gr.Markdown() | |
| cl_status = gr.Textbox(label="Status", interactive=False, value="Idle") | |
| def create_cover_letter_with_status(job_number, cv_file): | |
| if not job_number or not str(job_number).isdigit(): | |
| return "", "Invalid job number" | |
| if not cv_file: | |
| return "", "Upload CV first" | |
| return create_cover_letter(job_number, cv_file), "Cover letter generated" | |
| cl_btn.click( | |
| fn=create_cover_letter_with_status, | |
| inputs=[job_number, cv_upload], | |
| outputs=[cl_output, cl_status] | |
| ) | |
| ui.launch() | |