Spaces:
Runtime error
Runtime error
| import os | |
| from pathlib import Path | |
| import litellm | |
| from crewai import Agent, Task, Crew, Process | |
| from crewai_tools import SerperDevTool | |
| import pdfplumber | |
| from docx import Document | |
| import gradio as gr | |
| # Set up API keys | |
| litellm.api_key = os.getenv('GOOGLE_API_KEY') | |
| os.environ['SERPER_API_KEY'] = os.getenv('SERPER_API_KEY') | |
| # Define the LLM | |
| llm = "gemini/gemini-1.5-flash-exp-0827" # Your LLM model | |
| # Initialize the tool for internet searching capabilities | |
| tool = SerperDevTool() | |
| # Create the CV Analysis Agent | |
| cv_analysis_agent = Agent( | |
| role="CV Analyzer", | |
| goal='Analyze the given CV and extract key skills and experiences and make improvements if needed for portfolio creation.', | |
| verbose=True, | |
| memory=True, | |
| backstory=( | |
| "You are an expert CV Analyzer with a keen eye for detail. Your role is to meticulously examine the provided CV, " | |
| "identifying and extracting key skills, experiences, accomplishments, and areas for improvement. " | |
| "Your analysis should highlight strengths and suggest enhancements that would make the portfolio more competitive." | |
| ), | |
| tools=[tool], | |
| llm=llm, | |
| allow_delegation=True | |
| ) | |
| # Create the Portfolio Generation Agent | |
| portfolio_generation_agent = Agent( | |
| role='Portfolio Generator', | |
| goal='Generate a professional HTML/CSS/JS responsive landing portfolio webpage based on {cv} analysis.', | |
| verbose=True, | |
| memory=True, | |
| backstory=( | |
| "As a Responsive Portfolio Generator, your expertise lies in creating visually appealing and user-friendly web pages. " | |
| "Based on the CV analysis, you will generate a professional HTML/CSS/JS portfolio. " | |
| "Ensure the design reflects the individual's strengths and experiences while incorporating effective functionality. " | |
| "Consider responsiveness, color schemes, and navigation for an optimal user experience." | |
| ), | |
| tools=[tool], | |
| llm=llm, | |
| allow_delegation=False | |
| ) | |
| # Research task for CV analysis | |
| cv_analysis_task = Task( | |
| description=( | |
| "Analyze the provided {cv} in detail. Identify and summarize key skills, experiences, and notable accomplishments. " | |
| "Highlight educational background and suggest potential enhancements to improve the overall presentation and competitiveness of the CV." | |
| ), | |
| expected_output='A detailed summary of skills, experiences, accomplishments, and improvement suggestions formatted for a portfolio.', | |
| tools=[tool], | |
| agent=cv_analysis_agent, | |
| ) | |
| # Writing task for portfolio generation with enhanced UI requirements | |
| portfolio_task = Task( | |
| description=( | |
| "Generate a responsive HTML/CSS portfolio webpage based on the given CV analysis. " | |
| "Include a navbar with the individual's name, and sections for skills, projects, experiences, certifications, and contact information. " | |
| "Ensure the layout is clean and visually appealing with a light/dark theme toggle option. " | |
| "Embed CSS/JS directly into the HTML for easy deployment, and optimize for both desktop and mobile viewing." | |
| ), | |
| expected_output='A complete and responsive HTML document ready for deployment, showcasing the individual’s strengths.', | |
| tools=[tool], | |
| agent=portfolio_generation_agent, | |
| async_execution=True, | |
| ) | |
| # Function to read CV from PDF or DOCX file | |
| def read_cv_file(file_path): | |
| ext = os.path.splitext(file_path)[1].lower() | |
| cv_content = "" | |
| if ext == '.pdf': | |
| with pdfplumber.open(file_path) as pdf: | |
| for page in pdf.pages: | |
| cv_content += page.extract_text() | |
| elif ext == '.docx': | |
| doc = Document(file_path) | |
| for para in doc.paragraphs: | |
| cv_content += para.text + "\n" | |
| else: | |
| raise ValueError("Unsupported file format. Please use .pdf or .docx.") | |
| return cv_content.strip() | |
| # Create a Crew for processing | |
| crew = Crew( | |
| agents=[cv_analysis_agent, portfolio_generation_agent], | |
| tasks=[cv_analysis_task, portfolio_task], | |
| process=Process.sequential, | |
| ) | |
| # Function to process CV and generate portfolio | |
| def process_cv(file): | |
| try: | |
| cv_file_content = read_cv_file(file.name) | |
| result = crew.kickoff(inputs={'cv': cv_file_content}) | |
| # Print the entire result object to explore its contents (for debugging) | |
| print(result) | |
| # Convert the result to string | |
| html_output = str(result) | |
| # Use replace to remove '''html''' and ''' from the output | |
| clean_html_output = html_output.replace("```html", '').replace("```", '').strip() | |
| return clean_html_output # Return the cleaned HTML | |
| except Exception as e: | |
| return f"Error: {e}" | |
| def save_html_to_file(html_content): | |
| output_file_path = "Portfolio_generated_by_FiftyBit.html" | |
| with open(output_file_path, "w") as f: | |
| f.write(html_content) | |
| return output_file_path | |
| import html | |
| def upload_file(filepath): | |
| name = Path(filepath).name | |
| html_content = process_cv(filepath) # Get HTML content from the CV | |
| # Clean the HTML content and escape it for proper iframe embedding | |
| clean_html_output = html_content.replace("```html", '').replace("```", '').strip() | |
| escaped_html_content = html.escape(clean_html_output) # Escape HTML content | |
| # Debugging print to check the escaped HTML content | |
| #print("Escaped HTML content:", escaped_html_content) | |
| # Save the cleaned HTML content to a file (if you still want this feature) | |
| file_path = save_html_to_file(clean_html_output) | |
| # Return a full HTML string with embedded iframe for preview | |
| iframe_html = f""" | |
| <iframe srcdoc="{escaped_html_content}" style="width:100%; height:1000px; border:none; overflow:auto;"></iframe> | |
| """ | |
| return iframe_html, gr.UploadButton(visible=False), gr.DownloadButton(label=f"Download Code", value=file_path, visible=True) | |
| def download_file(): | |
| return [gr.UploadButton(label=f"Regenerate", visible=True), gr.DownloadButton(visible=False)] | |
| # Gradio App | |
| with gr.Blocks() as demo: | |
| gr.Markdown("<center><h1> CV-2-Portfolio Site Generator</center></h1>") | |
| gr.Markdown("<center><h2>Upload your CV in PDF or DOCX format for analysis and portfolio webpage generation.</center></h2>") | |
| u = gr.UploadButton("Upload CV (.pdf or .docx)", file_count="single") | |
| d = gr.DownloadButton("Download Portfolio", visible=False) | |
| # Use gr.HTML with larger iframe size to display the full preview | |
| output_preview = gr.HTML( | |
| value="<div style='width:100%; height:1000px; border:1px solid #ccc; text-align:center;'>Upload a file to preview the generated portfolio</div>" | |
| ) | |
| # Connect the upload button to the upload_file function and update the output preview | |
| u.upload(upload_file, u, [output_preview, u, d]) | |
| # Handle download button click | |
| d.click(download_file, None, [u, d]) | |
| demo.launch(debug=True) |