Download app.py from abersbail/tiny-code-only-tts: direct link, hf CLI and curl.
- Browser
- Download file 9.33 kB
-
https://huggingface.co/spaces/abersbail/tiny-code-only-tts/resolve/main/app.py
- Command line
-
hf download hf://spaces/abersbail/tiny-code-only-tts/app.py
-
curl -L -o app.py https://huggingface.co/spaces/abersbail/tiny-code-only-tts/resolve/main/app.py
9.33 kB
| import os | |
| import json | |
| import pandas as pd | |
| import gradio as gr | |
| from langgraph_agent import LangGraphResumeAnalyzer | |
| import utils | |
| # Instantiate LangGraph Agent | |
| analyzer = LangGraphResumeAnalyzer() | |
| # FIXED CSS preventing vibrating / trembling layout bug by locking vertical scrollbar gutter permanently | |
| CUSTOM_CSS = """ | |
| html { | |
| overflow-y: scroll !important; | |
| scroll-behavior: smooth !important; | |
| } | |
| body { | |
| background-color: #090d16 !important; | |
| font-family: 'Inter', system-ui, -apple-system, sans-serif !important; | |
| color: #e2e8f0 !important; | |
| margin: 0 !important; | |
| padding: 0 !important; | |
| min-height: 100vh !important; | |
| } | |
| .gradio-container { | |
| background-color: #090d16 !important; | |
| max-width: 1400px !important; | |
| margin: 0 auto !important; | |
| padding: 20px !important; | |
| width: 100% !important; | |
| box-sizing: border-box !important; | |
| } | |
| .card-panel { | |
| background: linear-gradient(145deg, #131b2e, #0f172a); | |
| border: 1px solid rgba(56, 189, 248, 0.2); | |
| border-radius: 16px; | |
| padding: 20px; | |
| box-shadow: 0 8px 32px rgba(0,0,0,0.4); | |
| height: auto !important; | |
| contain: content; | |
| } | |
| .btn-primary-audit { | |
| background: linear-gradient(135deg, #0284c7, #4f46e5) !important; | |
| color: white !important; | |
| font-weight: 800 !important; | |
| border-radius: 12px !important; | |
| font-size: 1.1rem !important; | |
| box-shadow: 0 4px 14px rgba(2, 132, 199, 0.4) !important; | |
| } | |
| """ | |
| def handle_run_audit(file_obj, text_resume, job_desc): | |
| """ | |
| Executes LangGraph pipeline for PDF documents or images via NVIDIA Nemotron OCR & PyPDF. | |
| """ | |
| res = analyzer.run_langgraph_pipeline( | |
| file_input=file_obj, | |
| text_input=text_resume, | |
| job_description=job_desc | |
| ) | |
| analysis = res["analysis"] | |
| ocr_info = res["ocr_result"] | |
| overall_score = analysis.get("overall_ats_score_pct", 85) | |
| ats_gauge_html = utils.generate_ats_score_html(overall_score) | |
| subscores_html = utils.generate_subscores_html( | |
| keyword_pct=analysis.get("keyword_match_pct", 82), | |
| skills_pct=analysis.get("skills_match_pct", 88), | |
| experience_pct=analysis.get("experience_fit_pct", 85), | |
| format_pct=analysis.get("format_quality_pct", 90) | |
| ) | |
| skill_badges_html = utils.format_skill_badges( | |
| analysis.get("matched_skills", []), | |
| analysis.get("missing_skills", []) | |
| ) | |
| contact = analysis.get("contact_info", {}) | |
| summary_md = f""" | |
| ### π€ Candidate Profile & Key Info | |
| - **Full Name**: `{analysis.get('candidate_name', 'Alex Chen')}` | |
| - **Estimated Experience**: `{analysis.get('estimated_years_experience', '6+ Years')}` | |
| - **Email**: `{contact.get('email', 'N/A')}` | **Location**: `{contact.get('location', 'N/A')}` | |
| #### π Executive Recruiter Assessment | |
| {analysis.get('executive_summary', 'No summary available.')} | |
| #### π― Key Candidate Strengths | |
| """ | |
| for strg in analysis.get("key_strengths", []): | |
| summary_md += f"- **{strg}**\n" | |
| summary_md += "\n#### π‘ Actionable Recommendations to Boost ATS Score to 98%+\n" | |
| for tip in analysis.get("improvement_tips", []): | |
| summary_md += f"- {tip}\n" | |
| # AI Tailored Resume Rewriter Bullets | |
| bullets_md = "### βοΈ AI Tailored Resume Bullet Point Rewriter\n*Copy & paste these optimized bullets into your resume to maximize ATS callback rates:*\n\n" | |
| for idx, bullet in enumerate(analysis.get("optimized_resume_bullets", [])): | |
| bullets_md += f"**{idx+1}.** `{bullet}`\n\n" | |
| # OCR Info | |
| ocr_meta_md = f""" | |
| ### ποΈ NVIDIA Nemotron OCR & PDF Detection Engine | |
| - **Engine Used**: `{ocr_info.get('model_used', 'NVIDIA Nemotron OCR v2')}` | |
| - **Total Lines Extracted**: `{ocr_info.get('line_count', 0)}` | |
| - **Extraction Status**: `{ocr_info.get('status', 'SUCCESS')}` | |
| """ | |
| detections_list = ocr_info.get("detections", []) | |
| df_det = pd.DataFrame(detections_list) if detections_list else pd.DataFrame(columns=["text", "confidence"]) | |
| full_report_json = json.dumps({ | |
| "candidate": analysis.get('candidate_name'), | |
| "overall_ats_score_pct": overall_score, | |
| "subscores": { | |
| "keywords": analysis.get("keyword_match_pct"), | |
| "skills": analysis.get("skills_match_pct"), | |
| "experience": analysis.get("experience_fit_pct"), | |
| "formatting": analysis.get("format_quality_pct") | |
| }, | |
| "ocr_engine": ocr_info.get('model_used'), | |
| "analysis": analysis | |
| }, indent=2) | |
| return ( | |
| ats_gauge_html, | |
| subscores_html, | |
| skill_badges_html, | |
| summary_md, | |
| bullets_md, | |
| res["timeline"], | |
| ocr_meta_md, | |
| df_det, | |
| res["resume_text"], | |
| full_report_json | |
| ) | |
| def handle_rag_chat(user_question: str): | |
| return analyzer.answer_rag_question(user_question) | |
| with gr.Blocks(title="AI Resume Analyzer (RAG + LangGraph)") as demo: | |
| gr.Markdown( | |
| """ | |
| # π Advanced AI Resume Analyzer (RAG + LangGraph) | |
| ### Multimodal PDF & Image OCR via NVIDIA Nemotron OCR v2/v1 & Groq LLM ATS Auditor | |
| **Engineer / Creator:** `abersabil` (`@abersbail`) | **User ID:** `69b2ede7cec72416131a3260` | |
| """ | |
| ) | |
| with gr.Tabs(): | |
| # TAB 1: LangGraph ATS Audit & Matching | |
| with gr.TabItem("π LangGraph ATS Audit & Matching"): | |
| with gr.Row(): | |
| with gr.Column(scale=1, elem_classes=["card-panel"]): | |
| gr.Markdown("### π₯ Upload PDF / Image Resume & Job Description") | |
| resume_file_input = gr.File( | |
| label="Upload Resume File (.pdf, .png, .jpg, .jpeg, .webp)", | |
| file_types=[".pdf", ".png", ".jpg", ".jpeg", ".webp"] | |
| ) | |
| resume_text_area = gr.Textbox( | |
| value=utils.DEFAULT_SAMPLE_RESUME, | |
| label="OR Paste Resume Text directly", | |
| lines=7 | |
| ) | |
| job_desc_area = gr.Textbox( | |
| value=utils.DEFAULT_JOB_DESCRIPTION, | |
| label="Target Job Description (JD)", | |
| lines=5 | |
| ) | |
| btn_audit = gr.Button("π Run LangGraph RAG Audit", elem_classes=["btn-primary-audit"]) | |
| langgraph_timeline = gr.Textbox(label="LangGraph State Machine Stream", lines=6, interactive=False) | |
| with gr.Column(scale=1): | |
| ats_score_gauge = gr.HTML(utils.generate_ats_score_html(88)) | |
| ats_subscores_box = gr.HTML(utils.generate_subscores_html(85, 90, 85, 95)) | |
| skill_badges_box = gr.HTML("Click 'Run LangGraph RAG Audit' to analyze candidate skills.") | |
| executive_summary_box = gr.Markdown("Candidate evaluation summary will appear here.") | |
| tailored_bullets_box = gr.Markdown("Optimized resume bullets will appear here.") | |
| # TAB 2: NVIDIA Nemotron OCR Scanner View | |
| with gr.TabItem("ποΈ NVIDIA Nemotron OCR Inspector"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| ocr_metadata_box = gr.Markdown("Run audit to view NVIDIA Nemotron OCR v2/v1 detection metrics.") | |
| ocr_detections_df = gr.Dataframe(label="Detected Lines & Confidence Scores") | |
| with gr.Column(scale=1): | |
| gr.Markdown("### π Extracted Resume Raw Text") | |
| ocr_raw_text_box = gr.Textbox(lines=18, interactive=False) | |
| # TAB 3: LangGraph RAG Candidate Chatbot | |
| with gr.TabItem("π¬ Candidate RAG Chatbot"): | |
| gr.Markdown("### π€ Ask RAG Questions About Candidate Qualifications") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| rag_question_input = gr.Textbox( | |
| label="Type Question about Candidate", | |
| placeholder="e.g., What PyTorch & RAG experience does the candidate have?", | |
| lines=2 | |
| ) | |
| btn_ask_rag = gr.Button("π Query RAG Vector Index", variant="primary") | |
| with gr.Column(scale=1): | |
| rag_answer_output = gr.Textbox(label="Grounded RAG Answer", lines=8, interactive=False) | |
| # TAB 4: Full Audit Report Export | |
| with gr.TabItem("π Candidate Report Export"): | |
| gr.Markdown("### π Downloadable Candidate Evaluation JSON Report") | |
| full_report_code = gr.Code(language="json", label="JSON Candidate Audit Report") | |
| # Event Bindings | |
| btn_audit.click( | |
| fn=handle_run_audit, | |
| inputs=[resume_file_input, resume_text_area, job_desc_area], | |
| outputs=[ | |
| ats_score_gauge, ats_subscores_box, skill_badges_box, | |
| executive_summary_box, tailored_bullets_box, langgraph_timeline, | |
| ocr_metadata_box, ocr_detections_df, ocr_raw_text_box, full_report_code | |
| ] | |
| ) | |
| btn_ask_rag.click( | |
| fn=handle_rag_chat, | |
| inputs=[rag_question_input], | |
| outputs=[rag_answer_output] | |
| ) | |
| if __name__ == "__main__": | |
| demo.queue() | |
| demo.launch(server_name="0.0.0.0", server_port=7860, css=CUSTOM_CSS) | |