File size: 4,806 Bytes
d4c397a
 
 
 
 
1626c71
d4c397a
1626c71
d4c397a
1626c71
d4c397a
 
1626c71
d4c397a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1626c71
d4c397a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1626c71
d4c397a
 
 
 
1626c71
d4c397a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1626c71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d4c397a
 
1626c71
 
d4c397a
 
 
1626c71
 
 
 
 
d4c397a
 
 
 
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
import os
import gradio as gr
import requests
from huggingface_hub import InferenceClient

# πŸ”‘ Load API keys from environment
GEMINI_API_KEY = os.getenv("GOOGLE_AI_API_KEY")
HF_API_KEY = os.getenv("HUGGINGFACE_API_KEY")  # optional for private HF models

# Hugging Face Client (public model as fallback)
hf_client = InferenceClient(model="HuggingFaceH4/zephyr-7b-beta")

# ========== AI Functions ==========
def generate_with_huggingface(resume_text, job_desc):
    prompt = f"""
    You are an expert career assistant. 
    Resume:
    {resume_text}

    Job Description:
    {job_desc}

    Task:
    1. Create a customized resume version highlighting relevant skills and achievements.
    2. Write a professional cover letter tailored for this role.
    """
    response = hf_client.text_generation(
        prompt,
        max_new_tokens=800,
        temperature=0.7,
    )
    return response

def call_gemini_api(resume_text, job_desc):
    if not GEMINI_API_KEY:
        return None

    prompt = f"""
    You are an expert career assistant. 
    Resume:
    {resume_text}

    Job Description:
    {job_desc}

    Task:
    1. Create a customized resume version highlighting relevant skills and achievements.
    2. Write a professional cover letter tailored for this role.
    """
    url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent"
    headers = {
        "Content-Type": "application/json",
        "X-goog-api-key": GEMINI_API_KEY,
    }
    data = {"contents": [{"parts": [{"text": prompt}]}]}
    try:
        response = requests.post(url, headers=headers, json=data, timeout=30)
        result = response.json()
        if "candidates" in result:
            return result["candidates"][0]["content"]["parts"][0]["text"]
        else:
            return None
    except Exception:
        return None

def generate_documents(resume_text, job_desc):
    gemini_output = call_gemini_api(resume_text, job_desc)
    if gemini_output:
        output_text = gemini_output
        source = "βœ… Google Gemini"
    else:
        output_text = generate_with_huggingface(resume_text, job_desc)
        source = "⚠️ Gemini failed β†’ Using Hugging Face LLM"

    # Split Resume + Cover Letter
    if "Cover Letter" in output_text:
        parts = output_text.split("Cover Letter")
        resume_out = parts[0].strip()
        cover_letter_out = "Cover Letter" + parts[1].strip()
    else:
        resume_out = output_text
        cover_letter_out = ""

    return resume_out + f"\n\n(Source: {source})", cover_letter_out


# ========== Custom CSS ==========
custom_css = """
body {
    background: linear-gradient(-45deg, #ff9a9e, #fad0c4, #a1c4fd, #c2e9fb);
    background-size: 400% 400%;
    animation: gradientBG 12s ease infinite;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
@keyframes gradientBG {
    0% {background-position: 0% 50%;}
    50% {background-position: 100% 50%;}
    100% {background-position: 0% 50%;}
}
.gradio-container {
    animation: fadeIn 1.2s ease-in-out;
}
textarea, input {
    border-radius: 14px !important;
    box-shadow: 0px 4px 10px rgba(0,0,0,0.2) !important;
    padding: 10px !important;
}
button {
    background: linear-gradient(90deg, #667eea, #764ba2) !important;
    color: white !important;
    font-weight: bold !important;
    border-radius: 25px !important;
    transition: all 0.3s ease-in-out;
    padding: 12px 20px !important;
}
button:hover {
    transform: scale(1.07);
    box-shadow: 0px 6px 15px rgba(0,0,0,0.3);
}
@keyframes fadeIn {
    from {opacity: 0; transform: translateY(25px);}
    to {opacity: 1; transform: translateY(0);}
}
"""

# ========== Gradio UI ==========
with gr.Blocks(css=custom_css, title="AI Resume & Cover Letter Generator") as demo:
    gr.Markdown("<h1 style='text-align:center; color:white;'>πŸ“„ AI Resume & Cover Letter Generator</h1>")
    gr.Markdown("<p style='text-align:center; color:white; font-size:18px;'>Paste your Resume + Job Description β†’ Get a Customized Resume & Cover Letter</p>")

    with gr.Row():
        resume_input = gr.Textbox(label="πŸ“‘ Paste Resume / LinkedIn profile", lines=10, placeholder="Paste your resume text here...")
        job_input = gr.Textbox(label="πŸ’Ό Paste Job Description", lines=8, placeholder="Paste job description here...")

    generate_btn = gr.Button("✨ Generate Resume & Cover Letter")

    with gr.Tabs():
        with gr.Tab("🎯 Customized Resume"):
            resume_output = gr.Textbox(label="Customized Resume", lines=20)
        with gr.Tab("✍️ Cover Letter"):
            cover_output = gr.Textbox(label="Cover Letter", lines=20)

    generate_btn.click(generate_documents, inputs=[resume_input, job_input], outputs=[resume_output, cover_output])

demo.launch()