from reportlab.pdfgen import canvas from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfbase import pdfmetrics from PyPDF2 import PdfReader from PyPDF2 import PdfWriter import openai import uuid import os import gradio as gr # 確保字體文件和模板文件存在於同一目錄 pdfmetrics.registerFont(TTFont("ArialUnicode", "./Arial Unicode.ttf")) def draw_data_on_template(template_path, name, email, phone, education, experience, skills, social_media): try: temp_pdf_path = f"./{uuid.uuid4()}_temp.pdf" c = canvas.Canvas(temp_pdf_path) c.setFont("ArialUnicode", 22) c.drawString(15, 750, f"Name: {name}") c.drawString(15, 680, f"Email: {email}") c.drawString(15, 610, f"Phone: {phone}") c.drawString(15, 540, f"Education: {education}") c.drawString(15, 470, f"Work Experience: {experience}") c.drawString(15, 340, f"Skills: {skills}") c.drawString(15, 200, f"Social Media: {social_media}") c.save() # 加載模板 PDF reader = PdfReader(template_path) template_page = reader.pages[0] content_reader = PdfReader(temp_pdf_path) content_page = content_reader.pages[0] template_page.merge_page(content_page) merged_pdf_path = f"./{uuid.uuid4()}_merged.pdf" writer = PdfWriter() writer.add_page(template_page) with open(merged_pdf_path, "wb") as output_file: writer.write(output_file) os.remove(temp_pdf_path) return merged_pdf_path except Exception as e: return f"Error in Drawing Data on Template: {str(e)}" def recommend_jobs(api_key, skills): try: openai.api_key = api_key skills_list = [skill.strip() for skill in skills.split(",") if skill.strip()] if not skills_list: return "Error: No valid skills provided." prompt = f"請用正體中文回覆,根據以下技能推薦適合的職位:{', '.join(skills_list)}" response = openai.ChatCompletion.create( model="gpt-4", messages=[{"role": "user", "content": prompt}] ) if not response.choices: return "Error: OpenAI API returned no results." return response.choices[0].message['content'].strip() except Exception as e: return f"Error in Job Recommendation: {str(e)}" def validate_and_process(api_key, name, email, phone, education, experience, skills, social_media): errors = [] if not name.strip(): errors.append("Name不能為空.") if not email.strip(): errors.append("Email不能為空.") if not phone.strip(): errors.append("Phone不能為空.") if not education.strip(): errors.append("Education不能為空.") if not skills.strip(): errors.append("Skills不能為空.") if errors: return None, "\n".join(errors), "請填寫完整後重試!" template_path = "./resume_null.pdf" # 確保模板文件上傳至同一目錄 merged_pdf = draw_data_on_template(template_path, name, email, phone, education, experience, skills, social_media) if isinstance(merged_pdf, str) and merged_pdf.startswith("Error"): return None, merged_pdf, "Merging with template failed." job_recommendations = recommend_jobs(api_key, skills) if job_recommendations.startswith("Error"): return merged_pdf, "Resume generated successfully!", job_recommendations return merged_pdf, "Resume generated successfully!", job_recommendations with gr.Blocks() as demo: gr.Markdown("# 自動生成簡歷工具") api_key = gr.Textbox(label="OpenAI API Key", placeholder="請輸入您的 OpenAI API Key", type="password") name = gr.Textbox(label="Name(必填)", placeholder="例:王小明") email = gr.Textbox(label="Email(必填)", placeholder="a1234567890@example.com") phone = gr.Textbox(label="Phone(必填)", placeholder="0912345678") education = gr.Textbox(label="Education(必填)", placeholder="例:學位、主修、學校") experience = gr.Textbox(label="Work Experience", placeholder="例:實習、兼職工作") skills = gr.Textbox(label="Skills(必填)", placeholder="例:Python, Teaching, Data Analysis (多項技能用,分隔)") social_media = gr.Textbox(label="Social Media", placeholder="例:LinkedIn URL") pdf_output = gr.File(label="Download Your Resume") status = gr.Textbox(label="Status / Error", interactive=False) job_recommendations = gr.Textbox(label="Recommended Jobs", interactive=False) generate_button = gr.Button("Generate Resume & Recommend Jobs") generate_button.click( validate_and_process, inputs=[api_key, name, email, phone, education, experience, skills, social_media], outputs=[pdf_output, status, job_recommendations] ) demo.launch()