import gradio as gr from parser import parse_resume # import json from langchain_docling.loader import ExportType from langchain_docling import DoclingLoader def process_file(file_path, resumes): loader = DoclingLoader(file_path=file_path, export_type=ExportType.MARKDOWN) job_description = loader.load()[0].page_content if not job_description.strip() or not resumes: return "Please provide both job description and at least one resume." print("[RESUME]", job_description) print("[CATEGORIES]", resumes) thinking, results = parse_resume(job_description, resumes) print("[THINKING]", thinking) print("[RESULTS]", results) # results = json.loads(results) # print("[SUCCESS JSON PARSING]") return thinking, results def process_input(job_description, file_upload, resumes): # resumes = [r for r in resumes if r and r.strip() != ""] # Remove empty print("[FILE UPLOAD]", file_upload) if file_upload: return process_file(file_upload, resumes) if not job_description.strip() or not resumes: return "Please provide both job description and at least one resume." print("[CATEGORIES]", resumes) thinking, results = parse_resume(job_description, resumes) print("[THINKING]", thinking) print("[RESULTS]", results) # results = json.loads(results) # print("[SUCCESS JSON PARSING]") return thinking, results # results = zip(*parse_resume(job_description, resumes)) # formatted_output = "" # for i, (resume, score) in enumerate(results, 1): # formatted_output += f"Resume #{i}:\nScore: {score:.2f}\nResume Snippet: {resume[:200]}...\n\n-------\n\n" # return formatted_output initial_parsing = [ {"name":"education", "type":"List[str]","description":"attended school, university, and other education programs"}, {"name":"experience", "type":"int", "description":"years of experience"}, {"name":"skills", "type":"List[str]", "description":"list of skills"}, {"name":"name", "type":"str", "description":"name of the person"}, {"name":"location", "type":"str", "description":"location of the person"}, {"name":"email", "type":"str", "description":"email of the person"}, {"name":"websites", "type":"List[str]", "description":"urls related of the person"}, {"name":"certifications", "type":"List[str]", "description":"list of certifications"}, {"name":"languages", "type":"List[str]", "description":"list of languages"}, {"name":"projects", "type":"List[str]", "description":"list of projects"}, {"name":"note", "type":"str", "description":"additional note which highlight the best or uniqueness of the person"} ] def toggle_textbox(file): print("[FILE TOOGLE]", file) # return gr.Textbox.update(interactive=False if file else True) is_file = bool(file) return gr.update(visible=not is_file), gr.update(visible=not is_file), gr.update(visible=is_file) def update_json(data, name, data_type, desc): if name: idx = -1 for i,x in enumerate(data): if name == x["name"]: idx = i break if idx != -1: if desc: data[idx]["description"] = desc if data_type: data[idx]["type"] = data_type elif desc: data.append( {"name":name, "type":data_type if data_type else "str", "description":desc} ) # if name and desc: # data.append( # {"name":name, "type":data_type if data_type else "str", "description":desc} # ) return data def delete_json(data, name): for i,x in enumerate(data): if x["name"] == name: data.pop(i) return data # UI definition with gr.Blocks() as demo: gr.Markdown("## 📝 CV / Resume Parsing") resumes_list = [] with gr.Row(): resume_count = gr.State(2) with gr.Column(): @gr.render(inputs=resume_count) def render_count(count): name = gr.Textbox( lines=1, placeholder="Category name", label="Name" ) data_type = gr.Textbox( lines=1, placeholder="Category data type", label="Data Type" ) desc = gr.Textbox( lines=1, placeholder="Category description", label="Description" ) update_json_button.click(update_json, inputs=[json_display, name, data_type, desc], outputs=json_display) # resumes_list.append( # {"name":name, "type":data_type, "description":desc} # ) # resumes_list.append(name) # resumes_list.append(data_type) # resumes_list.append(desc) # @gr.render(inputs=input_text) # def add_resume(): # new_input = gr.Textbox( # lines=6, # placeholder=f"Paste resume #{len(resumes_list)+1} here...", # label=f"Resume #{len(resumes_list)+1}" # ) # resumes_list.append(new_input) # return resumes_group.update(visible=True) # add_resume_btn = gr.Button("➕ Add Another Category") # add_resume_btn.click(lambda x: x + 1, resume_count, resume_count) update_json_button = gr.Button("Add / Edit Category") category_delete = gr.Textbox( lines=1, placeholder="Category Name", label="Remove Category By Name" ) delete_json_button = gr.Button("Delete Category") json_display = gr.JSON(value=initial_parsing, label="Parsing Categories", show_label=True) delete_json_button.click(delete_json, inputs=[json_display, category_delete], outputs=json_display) with gr.Column(): job_description = gr.Textbox( lines=16, placeholder="Paste Resume here...", label="CV / Resume" ) file_upload = gr.File( label="Input Resume File" ) output = gr.Textbox( lines=6, label="Parsing Result", interactive=False ) # output = gr.JSON(show_indices=True, label="Parsing Result", show_label=True) thinking_output = gr.Textbox( lines=6, label="Thinking Result", interactive=False ) submit_btn_2 = gr.Button("🚀 Parse Resume / CV", visible=False) submit_btn_2.click( fn=process_input, inputs=[job_description, file_upload, json_display], outputs=[thinking_output, output] ) submit_btn = gr.Button("🚀 Parse Resume / CV") submit_btn.click( fn=process_input, inputs=[job_description, file_upload, json_display], outputs=[thinking_output, output] ) file_upload.change(fn=toggle_textbox, inputs=file_upload, outputs=[job_description, submit_btn, submit_btn_2]) # add_resume_btn.click(add_resume, outputs=resumes_group) # add_resume_btn.click(lambda x: x + 1, resume_count, resume_count) demo.launch()