File size: 11,374 Bytes
62ab0d5
 
36ff3a8
62ab0d5
 
 
 
 
 
 
 
 
36ff3a8
 
 
 
62ab0d5
36ff3a8
 
 
62ab0d5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36ff3a8
 
62ab0d5
 
 
 
36ff3a8
 
62ab0d5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36ff3a8
62ab0d5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import gradio as gr
import os
import google.generativeai as genai
from docx import Document as DocxDocument
from docx.shared import Pt
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
import pypandoc
from datetime import datetime
import fitz  # PyMuPDF
from docx import Document
import zipfile

# Gemini API-Key aus Umgebungsvariablen holen
gemini_api_key = os.getenv('GEMINI_API_KEY')
if not gemini_api_key:
    raise ValueError("Bitte setzen Sie die Umgebungsvariable GEMINI_API_KEY.")

# Gemini initialisieren
genai.configure(api_key=gemini_api_key)
model = genai.GenerativeModel('gemini-pro')

def extract_text_from_file(file_path):
    if file_path.endswith('.docx'):
        doc = DocxDocument(file_path)
        return '\n'.join([para.text for para in doc.paragraphs])
    elif file_path.endswith('.pdf'):
        text = ""
        with fitz.open(file_path) as pdf_doc:
            for page in pdf_doc:
                text += page.get_text()
        return text
    else:
        return ""

def extract_text_from_zip(zip_path):
    extracted_text = ""
    with zipfile.ZipFile(zip_path, 'r') as zip_ref:
        zip_ref.extractall('/tmp/certificates')
        for file_name in zip_ref.namelist():
            file_path = os.path.join('/tmp/certificates', file_name)
            extracted_text += extract_text_from_file(file_path) + "\n"
    return extracted_text

def generate_body(job_description, language, cv_text=None, certificates_text=None):
    cv_text = f"Hier ist der Lebenslauf des Kandidaten:\n{cv_text}\n" if cv_text else ""
    certificates_text = f"Hier sind die Zertifikate des Kandidaten:\n{certificates_text}\n" if certificates_text else ""

    prompt = f"{cv_text}{certificates_text}Schreiben Sie ein professionelles Bewerbungsschreiben auf {language} ohne Anrede. Erstellen Sie nur den Textkörper basierend auf dieser Stellenbeschreibung:\n{job_description}"

    response = model.generate_content(prompt)
    return response.text.strip()

def evaluate_match(job_description, cv_text, language):
    prompt = f"Bewerten Sie, wie gut der folgende Lebenslauf zur Stellenbeschreibung passt:\n\nStellenbeschreibung:\n{job_description}\n\nLebenslauf:\n{cv_text}\n\nGeben Sie eine Zusammenfassung der Stärken und Schwächen sowie eine Übereinstimmungsbewertung zwischen 0 und 100 ab, auf {language}."

    response = model.generate_content(prompt)
    return response.text.strip()

def create_application_letter(name, sender_street, sender_zip, sender_city, email, phone, job_position, employer_name, employer_street, employer_zip, employer_city, greeting_option, employer_contact_name, job_id, start_date, job_description, language, output_format, cv_file=None, certificates_file=None):
    cv_text = extract_text_from_file(cv_file) if cv_file else None
    
    certificates_text = extract_text_from_zip(certificates_file) if certificates_file else ""

    body = generate_body(job_description, language, cv_text=cv_text, certificates_text=certificates_text)

    doc = Document()

    header = doc.sections[0].header
    header_paragraph = header.paragraphs[0]
    header_paragraph.text = f"{name} | {sender_street}, {sender_zip} {sender_city} | {email} | {phone}"
    header_paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT

    for run in header_paragraph.runs:
        run.font.size = Pt(10)

    doc.add_paragraph(f"{employer_name}\n{employer_contact_name if greeting_option == 'Known' else ''}\n{employer_street}\n{employer_zip} {employer_city}")

    current_date = datetime.now().strftime('%d.%m.%Y')
    paragraph = doc.add_paragraph()
    paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
    run = paragraph.add_run(f"{employer_city}, {current_date}")
    run.font.size = Pt(11)

    doc.add_paragraph(f"Bewerbung als {job_position}\nKennnummer {job_id}\n", style='Heading 2')

    if language == "German":
        if greeting_option == "Known" and employer_contact_name:
            doc.add_paragraph(f"Sehr geehrter Herr {employer_contact_name},\n")
        else:
            doc.add_paragraph("Sehr geehrte Damen und Herren,\n")
    else:
        if greeting_option == "Known" and employer_contact_name:
            doc.add_paragraph(f"Dear {employer_contact_name},\n")
        else:
            doc.add_paragraph("Dear Sir/Madam,\n")

    doc.add_paragraph(body)

    closing_text = (
        f"\nIch unterstütze Ihr Team gerne ab dem {start_date} und freue mich über die Einladung zu einem persönlichen Vorstellungsgespräch."
        if language == "German" else
        f"\nI am eager to join your team starting on {start_date} and look forward to the opportunity to discuss my application further."
    )
    doc.add_paragraph(closing_text)
    doc.add_paragraph("\nMit freundlichen Grüßen,\n\n" if language == "German" else "\nSincerely,\n\n")
    doc.add_paragraph(f"{name}\n")

    for paragraph in doc.paragraphs:
        for run in paragraph.runs:
            run.font.size = Pt(11)

    output_filename_docx = f'{name}_Bewerbungsschreiben.docx'
    doc.save(output_filename_docx)

    if output_format == "PDF":
        output_filename_pdf = f'{name}_Bewerbungsschreiben.pdf'
        pypandoc.convert_file(output_filename_docx, 'pdf', outputfile=output_filename_pdf)
        os.remove(output_filename_docx)
        return output_filename_pdf
    else:
        return output_filename_docx

def generate_and_download(name, sender_street, sender_zip, sender_city, email, phone, job_position, employer_name, employer_street, employer_zip, employer_city, greeting_option, employer_contact_name, job_id, start_date, job_description, language, output_format, cv_file, certificates_file, perform_evaluation):
    output_filename = create_application_letter(name, sender_street, sender_zip, sender_city, email, phone, job_position, employer_name, employer_street, employer_zip, employer_city, greeting_option, employer_contact_name, job_id, start_date, job_description, language, output_format, cv_file=cv_file, certificates_file=certificates_file)
    
    evaluation_result = ""
    if perform_evaluation and cv_file:
        cv_text = extract_text_from_file(cv_file)
        evaluation_result = evaluate_match(job_description, cv_text, language)
    
    return output_filename, evaluation_result

description = """
# Professioneller Bewerbungsschreiben-Generator

Willkommen beim ultimativen Tool zum Erstellen professioneller Bewerbungsschreiben mit Leichtigkeit. Dieses Tool nutzt die Kraft von **Google Gemini**, einem hochmodernen Sprachmodell, um automatisch einen maßgeschneiderten Bewerbungstext basierend auf der von Ihnen bereitgestellten Stellenbeschreibung zu erstellen.

Sie können optional Ihren Lebenslauf im DOCX- oder PDF-Format hochladen und Ihre Zertifikate als ZIP-Datei, um ein persönlicheres Bewerbungsschreiben zu erstellen. Sie können auch wählen, ob Sie eine Bewertung darüber erhalten möchten, wie gut Ihr Lebenslauf zur Stellenbeschreibung passt. Füllen Sie einfach die erforderlichen Felder aus und in wenigen Sekunden erhalten Sie ein wunderschön formatiertes Bewerbungsschreiben, das Sie entweder im DOCX- oder PDF-Format herunterladen können.

Starten Sie Ihren Weg zu Ihrer nächsten Karrierechance mit einem überzeugenden Bewerbungsschreiben, das speziell für Sie erstellt wurde!
"""

with gr.Blocks() as demo:
    gr.Markdown(description)

    with gr.Row():
        with gr.Column():
            sender_name = gr.Textbox(label="Absendername", placeholder="Geben Sie Ihren vollständigen Namen ein", value="Maximilian Müller")
            sender_street = gr.Textbox(label="Straße des Absenders", placeholder="Geben Sie Ihre Straßenadresse ein", value="Beispielstraße 42")
            sender_zip = gr.Textbox(label="PLZ des Absenders", placeholder="Geben Sie Ihre Postleitzahl ein", value="10115")
            sender_city = gr.Textbox(label="Stadt des Absenders", placeholder="Geben Sie Ihre Stadt ein", value="Berlin")
            sender_email = gr.Textbox(label="E-Mail des Absenders", placeholder="Geben Sie Ihre E-Mail-Adresse ein", value="[email protected]")
            sender_phone = gr.Textbox(label="Telefon des Absenders", placeholder="Geben Sie Ihre Telefonnummer ein", value="+49 170 1234567")
            certificates_file = gr.File(label="Zertifikate hochladen (optional, als .zip)", type="filepath", file_types=[".zip"])
        
        with gr.Column():
            job_position = gr.Textbox(label="Stellenbezeichnung", placeholder="Geben Sie die Stellenbezeichnung ein", value="Softwareentwickler")
            job_id = gr.Textbox(label="Job-ID", placeholder="Geben Sie die Job-ID ein", value="DEV-2024-01")
            start_date = gr.Textbox(label="Startdatum", placeholder="Geben Sie das Startdatum ein (z.B. 15.05.2020)", value="01.09.2024")
            job_description = gr.Textbox(label="Stellenbeschreibung", placeholder="Fügen Sie hier die Stellenbeschreibung ein", lines=11.5, value="Wir suchen einen engagierten Softwareentwickler, der unser Team bei der Erstellung innovativer Anwendungen unterstützt. Erfahrungen mit Python und Java sowie Kenntnisse agiler Methoden sind erforderlich.")
            language = gr.Dropdown(choices=["Englisch", "Deutsch"], label="Sprache auswählen", value="Deutsch")
            output_format = gr.Dropdown(choices=["DOCX", "PDF"], label="Ausgabeformat auswählen", value="DOCX")
            perform_evaluation = gr.Checkbox(label="Lebenslauf im Vergleich zur Stellenbeschreibung bewerten (optional)", value=False)
        
        with gr.Column():
            employer_name = gr.Textbox(label="Arbeitgebername", placeholder="Geben Sie den Namen des Arbeitgebers ein", value="Tech Innovations GmbH")
            employer_street = gr.Textbox(label="Straße des Arbeitgebers", placeholder="Geben Sie die Straßenadresse des Arbeitgebers ein", value="Innovationsstraße 1")
            employer_zip = gr.Textbox(label="PLZ des Arbeitgebers", placeholder="Geben Sie die Postleitzahl des Arbeitgebers ein", value="10115")
            employer_city = gr.Textbox(label="Stadt des Arbeitgebers", placeholder="Geben Sie die Stadt des Arbeitgebers ein", value="Berlin")
            greeting_option = gr.Dropdown(choices=["Bekannt", "Unbekannt"], label="Ist der Name des Empfängers bekannt?", value="Bekannt")
            employer_contact_name = gr.Textbox(label="Name des Ansprechpartners beim Arbeitgeber", placeholder="Geben Sie den Namen des Ansprechpartners ein (falls bekannt)", value="Herr Dr. Felix Schmidt", visible=True)
            cv_file = gr.File(label="Lebenslauf hochladen (optional)", type="filepath", file_types=[".docx", ".pdf"])
    
    generate_button = gr.Button("Bewerbungsschreiben erstellen")
    output_letter = gr.File(label="Laden Sie Ihr Bewerbungsschreiben herunter")
    evaluation_output = gr.Textbox(label="Bewertungsergebnis", placeholder="Die Bewertung wird hier angezeigt...", lines=7)

    generate_button.click(generate_and_download,
                          inputs=[sender_name, sender_street, sender_zip, sender_city, sender_email, sender_phone, job_position, employer_name, employer_street, employer_zip, employer_city, greeting_option, employer_contact_name, job_id, start_date, job_description, language, output_format, cv_file, certificates_file, perform_evaluation],
                          outputs=[output_letter, evaluation_output])

demo.launch(debug=True)