resume / app.py
LALAa11's picture
Update app.py
1626c71 verified
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()