Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import requests | |
| import os | |
| from dotenv import load_dotenv | |
| import tempfile | |
| # Load environment variables | |
| load_dotenv() | |
| def get_sample_cv(): | |
| """ | |
| Return the sample CV markdown content for reference | |
| """ | |
| try: | |
| with open('Sample.md', 'r', encoding='utf-8') as f: | |
| return f.read() | |
| except FileNotFoundError: | |
| return "Sample.md file not found in the current directory." | |
| except Exception as e: | |
| return f"Error reading Sample.md: {str(e)}" | |
| def get_cv_formatting_instructions(): | |
| """ | |
| Return detailed CV formatting instructions from external markdown file | |
| """ | |
| try: | |
| with open('Instructions.md', 'r', encoding='utf-8') as f: | |
| return f.read() | |
| except FileNotFoundError: | |
| return "Instructions.md file not found in the current directory." | |
| except Exception as e: | |
| return f"Error reading Instructions.md: {str(e)}" | |
| def convert_markdown_to_pdf(markdown_text): | |
| """ | |
| Convert markdown text to PDF and HTML using the external API endpoints | |
| Args: | |
| markdown_text (str): The markdown text to convert | |
| Returns: | |
| tuple: (pdf_path, html_content, status_message) | |
| """ | |
| if not markdown_text.strip(): | |
| return None, "", "Please enter some markdown text." | |
| # Get bearer token from environment | |
| bearer_token = os.getenv('BEARER_TOKEN') | |
| if not bearer_token or bearer_token == 'your_bearer_token_here': | |
| return None, "", "❌ Bearer token not configured. Please set BEARER_TOKEN in .env file." | |
| try: | |
| headers = { | |
| 'Authorization': f'Bearer {bearer_token}', | |
| 'Content-Type': 'text/markdown' | |
| } | |
| # Get base URL from environment | |
| base_url = os.getenv('API_BASE_URL', 'https://nirav-madhani-resume-server.hf.space') | |
| # Get PDF directly from API | |
| pdf_url = f"{base_url}/convert/pdf" | |
| print(f"📡 Making request to {pdf_url}") | |
| pdf_response = requests.post(pdf_url, data=markdown_text, headers=headers, timeout=30) | |
| if pdf_response.status_code != 200: | |
| return None, "", f"❌ PDF API request failed with status {pdf_response.status_code}: {pdf_response.text}" | |
| # Save PDF to temporary file | |
| with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf', mode='w+b') as temp_pdf: | |
| temp_pdf.write(pdf_response.content) | |
| pdf_path = temp_pdf.name | |
| # Get HTML for preview | |
| html_url = f"{base_url}/convert/html" | |
| print(f"📡 Making request to {html_url}") | |
| html_response = requests.post(html_url, data=markdown_text, headers=headers, timeout=30) | |
| if html_response.status_code != 200: | |
| # PDF worked but HTML failed - still return PDF | |
| return pdf_path, "", f"✅ PDF generated successfully! (HTML preview failed: {html_response.status_code})" | |
| html_content = html_response.text | |
| return pdf_path, html_content, "✅ PDF and HTML generated successfully via API!" | |
| except requests.exceptions.RequestException as e: | |
| return None, "", f"❌ Network error: {str(e)}" | |
| except Exception as e: | |
| return None, "", f"❌ Error generating PDF: {str(e)}" | |
| def process_conversion(markdown_text): | |
| """ | |
| Process the markdown conversion and return results for Gradio interface | |
| Args: | |
| markdown_text (str): The markdown text to convert | |
| Returns: | |
| tuple: (pdf_file_path, html_content, status_message) | |
| """ | |
| pdf_path, html_content, message = convert_markdown_to_pdf(markdown_text) | |
| return pdf_path, html_content, message | |
| # MCP Tool Functions (callable by AI assistants) | |
| def mcp_get_sample_cv(): | |
| """MCP tool: Get sample CV markdown | |
| Returns: | |
| str: The sample CV markdown content | |
| """ | |
| return get_sample_cv() | |
| def mcp_get_cv_instructions(): | |
| """MCP tool: Get CV formatting instructions | |
| Returns: | |
| str: The CV formatting instructions | |
| """ | |
| return get_cv_formatting_instructions() | |
| def mcp_convert_cv(markdown_text: str): | |
| """MCP tool: Convert CV markdown to PDF | |
| Args: | |
| markdown_text (str): The markdown text to convert to PDF | |
| Returns: | |
| str: The conversion result message | |
| """ | |
| pdf_path, html_content, message = process_conversion(markdown_text) | |
| return f"Conversion result: {message}" | |
| # Create Gradio interface | |
| with gr.Blocks(title="CV Markdown to PDF Converter", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown("# 📄 CV Markdown to PDF Converter") | |
| gr.Markdown("Convert your CV markdown to professional PDF format. Use the Instructions & Sample tab to learn the proper formatting.") | |
| with gr.Tabs(): | |
| with gr.TabItem("🚀 Convert CV"): | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Markdown("## Input") | |
| markdown_input = gr.Textbox( | |
| label="CV Markdown Text", | |
| placeholder="Enter your CV markdown here... (see Instructions & Sample tab for formatting guide)", | |
| lines=20, | |
| max_lines=30 | |
| ) | |
| with gr.Column(scale=1): | |
| gr.Markdown("## Output") | |
| with gr.Tabs(): | |
| with gr.TabItem("📄 PDF Download"): | |
| pdf_output = gr.File( | |
| label="Generated PDF", | |
| file_types=[".pdf"] | |
| ) | |
| with gr.TabItem("🌐 HTML Preview"): | |
| html_output = gr.HTML( | |
| label="HTML Preview", | |
| value="HTML preview will appear here after conversion..." | |
| ) | |
| status_message = gr.Textbox( | |
| label="Status", | |
| interactive=False, | |
| lines=2 | |
| ) | |
| with gr.Row(): | |
| convert_btn = gr.Button("🚀 Convert to PDF", variant="primary", size="lg") | |
| # Event handler | |
| convert_btn.click( | |
| fn=process_conversion, | |
| inputs=[markdown_input], | |
| outputs=[pdf_output, html_output, status_message] | |
| ) | |
| with gr.TabItem("📋 Instructions & Sample"): | |
| with gr.Tabs(): | |
| with gr.TabItem("📖 Formatting Instructions"): | |
| gr.Markdown(get_cv_formatting_instructions()) | |
| with gr.TabItem("📄 Sample CV"): | |
| gr.Markdown("## Sample CV Markdown") | |
| gr.Markdown("Below is a complete sample CV showing all the formatting patterns:") | |
| sample_cv_display = gr.Code( | |
| value=get_sample_cv(), | |
| language="markdown", | |
| label="Sample CV Markdown Code", | |
| lines=30, | |
| max_lines=50 | |
| ) | |
| copy_sample_btn = gr.Button("📋 Copy Sample to Converter", variant="secondary") | |
| # Copy sample to main input | |
| copy_sample_btn.click( | |
| fn=get_sample_cv, | |
| outputs=[markdown_input] | |
| ) | |
| # Example CV templates | |
| with gr.Row(): | |
| gr.Examples( | |
| examples=[ | |
| [get_sample_cv()], | |
| ["""--- | |
| name: John Doe | |
| header: | |
| - text: | | |
| <span style="font-size: 1.2em; font-weight: bold;">Full Stack Developer</span> | |
| - text: <span class="iconify" data-icon="tabler:phone"></span> (555) 987-6543 | |
| newLine: true | |
| - text: <span class="iconify" data-icon="tabler:mail"></span> john.doe@email.com | |
| link: mailto:john.doe@email.com | |
| --- | |
| ## Experience | |
| [L2]Tech Startup Inc.[/L2] [L2R]San Francisco, CA[/L2R] | |
| [L3]Full Stack Developer[/L3] [L3R]Jan 2022 - Present[/L3R] | |
| - Designed and implemented scalable web applications serving 10K+ users | |
| - Reduced page load times by 40% through optimization techniques | |
| - Led migration from monolith to microservices architecture | |
| ## Education | |
| [L2]University of California[/L2] GPA 3.8 [L2R]Berkeley, CA[/L2R] | |
| [L3]B.S. in Computer Science[/L3] [L3R]2018 - 2022[/L3R] | |
| ## Skills | |
| **Programming:** Python, JavaScript, TypeScript, Java | |
| <br> | |
| **Frameworks:** React, Node.js, Django, Spring Boot | |
| <br> | |
| **Databases:** PostgreSQL, MongoDB, Redis | |
| """], | |
| ], | |
| inputs=[markdown_input], | |
| label="📝 CV Templates" | |
| ) | |
| # Register MCP tools | |
| gr.api(mcp_get_sample_cv) | |
| gr.api(mcp_get_cv_instructions) | |
| gr.api(mcp_convert_cv) | |
| # Launch the app with MCP enabled | |
| if __name__ == "__main__": | |
| demo.launch( | |
| mcp_server=True | |
| ) | |