Spaces:
Sleeping
Sleeping
File size: 7,718 Bytes
5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 651b93a 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 b1695a3 5dd6b73 b1695a3 13a2c93 b1695a3 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 13a2c93 5dd6b73 |
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 |
# Install dependensi yang dibutuhkan oleh Hugging Face Spaces
#!pip install -q gradio google-generativeai pymupdf
import gradio as gr
import google.generativeai as genai
import fitz # PyMuPDF
import json
import os
import urllib.parse
# --- KONFIGURASI API KEY DARI HUGGING FACE SECRETS ---
API_CONFIGURED = False
try:
api_key = os.environ.get('GEMINI_API_KEY')
if api_key:
genai.configure(api_key=api_key)
model = genai.GenerativeModel('gemini-pro-latest')
API_CONFIGURED = True
print("β
Konfigurasi API dan model berhasil.")
else:
print("π Secret 'GEMINI_API_KEY' tidak ditemukan.")
except Exception as e:
print(f"π Terjadi error saat inisialisasi: {e}")
# --- FUNGSI-FUNGSI UTAMA ---
def ekstrak_teks_dari_pdf(path_file_pdf):
try:
with fitz.open(path_file_pdf) as dokumen:
teks_lengkap = "".join(halaman.get_text() for halaman in dokumen)
return teks_lengkap
except Exception as e:
raise gr.Error(f"Gagal membaca file PDF: {e}")
def generate_search_links(keywords):
"""Membuat tautan pencarian dari kata kunci untuk berbagai platform."""
if not keywords:
return {}
keywords_encoded = urllib.parse.quote_plus(keywords)
keywords_hyphenated = keywords.lower().replace(" ", "-").replace("(", "").replace(")", "")
links = {
"LinkedIn": f"https://www.linkedin.com/jobs/search/?keywords={keywords_encoded}&location=Indonesia",
"JobStreet": f"https://id.jobstreet.com/id/{keywords_hyphenated}-jobs/",
"Glints": f"https://glints.com/id/opportunities/jobs/explore?keyword={keywords_encoded}",
"Indeed": f"https://id.indeed.com/jobs?q={keywords_encoded}",
"Google Jobs": f"https://www.google.com/search?q={keywords_encoded}+jobs+in+Indonesia&ibp=htl;jobs"
}
return links
def format_output_markdown(analysis_json, links):
"""Menyusun laporan komprehensif DAN tautan pencarian menjadi satu output."""
jabatan = analysis_json.get("jabatan_ideal", "N/A")
alasan_list = analysis_json.get("alasan_kecocokan", [])
deskripsi_list = analysis_json.get("deskripsi_pekerjaan", [])
potensi_list = analysis_json.get("potensi_karir", [])
gaji = analysis_json.get("kisaran_gaji", {})
kelebihan_list = analysis_json.get("kelebihan_tambahan", [])
alasan_md = "\n".join([f"- {item}" for item in alasan_list])
deskripsi_md = "\n".join([f"- {item}" for item in deskripsi_list])
potensi_md = "\n".join([f"- {item}" for item in potensi_list])
kelebihan_md = "\n".join([f"- {item}" for item in kelebihan_list])
gaji_md = f"""
| Level | Estimasi Gaji / Bulan |
| :--- | :--- |
| **Junior** | {gaji.get("junior", "N/A")} |
| **Mid-Level** | {gaji.get("mid_level", "N/A")} |
| **Senior / Lead** | {gaji.get("senior", "N/A")} |
> (Estimasi berdasarkan data pasar kerja di Indonesia)
"""
# ==================================================================
# BAGIAN BARU: Membuat daftar tautan pencarian
# ==================================================================
markdown_links = ""
for site, url in links.items():
markdown_links += f"- **[{site}]({url})**\n"
return f"""
### π― {jabatan}
***
#### π§© Alasan Kecocokan
{alasan_md}
#### πΌ Deskripsi Pekerjaan Umum
Seorang **{jabatan.split('(')[0].strip()}** bertanggung jawab untuk:
{deskripsi_md}
#### π Potensi Jenjang Karir
Dari posisi ini, Anda dapat berkembang menjadi:
{potensi_md}
#### π° Kisaran Gaji (Indonesia)
{gaji_md}
#### π Kelebihan Tambahan untuk Karirmu
{kelebihan_md}
***
### π Klik untuk Mencari Lowongan Terbaru
{markdown_links}
"""
def analyze_career_path(cv_file):
"""Fungsi utama pipeline: Analisis CV -> Buat Laporan -> Buat Link."""
if not API_CONFIGURED:
raise gr.Error("API Key Gemini belum terkonfigurasi. Periksa Logs aplikasi.")
if cv_file is None:
raise gr.Error("Mohon upload file CV (PDF) Anda.")
try:
print("--- Memulai Proses Analisis Karir ---")
print("1. Mengekstrak teks dari PDF...")
teks_cv = ekstrak_teks_dari_pdf(cv_file.name)
if not teks_cv:
raise gr.Error("PDF kosong atau tidak dapat dibaca.")
print("β
Teks berhasil diekstrak.")
print("2. Mengirim permintaan analisis karir ke Gemini...")
prompt_analisis_karir = f"""
Anda adalah seorang "Career Analyst AI" yang sangat berpengalaman. Tugas Anda adalah membaca teks CV, menganalisisnya secara mendalam, dan membuat laporan peluang karir yang komprehensif.
Teks CV:
---
{teks_cv}
---
Lakukan analisis dan berikan output dalam format JSON yang ketat dengan struktur berikut:
- "jabatan_ideal": Tentukan satu jabatan paling ideal untuk kandidat ini, termasuk spesialisasi jika ada (Contoh: "Frontend Developer (Web & Mobile)").
- "alasan_kecocokan": Buat sebuah array (list) berisi 3-4 poin utama MENGAPA kandidat ini sangat cocok untuk jabatan tersebut, hubungkan langsung dengan data dari CV.
- "deskripsi_pekerjaan": Buat sebuah array (list) berisi 5 poin deskripsi pekerjaan umum untuk jabatan ideal tersebut.
- "potensi_karir": Buat sebuah array (list) berisi 3-4 jalur pengembangan karir dari posisi ini.
- "kisaran_gaji": Buat sebuah objek JSON berisi estimasi gaji bulanan di Indonesia untuk level "junior", "mid_level", dan "senior". Gunakan format string seperti "Rp 6 - 9 juta".
- "kelebihan_tambahan": Buat sebuah array (list) berisi 1-2 poin saran atau kelebihan unik yang dimiliki kandidat dari CV-nya.
Pastikan output hanya berupa JSON saja.
"""
generation_config = genai.types.GenerationConfig(response_mime_type="application/json")
response = model.generate_content(prompt_analisis_karir, generation_config=generation_config)
response_json = json.loads(response.text)
print("β
Laporan karir komprehensif berhasil diterima.")
# ==================================================================
# LANGKAH TAMBAHAN: Gunakan hasil analisis untuk membuat link
# ==================================================================
print("3. Membuat tautan pencarian dari hasil analisis...")
keywords_from_analysis = response_json.get("jabatan_ideal", "")
search_links = generate_search_links(keywords_from_analysis)
print("4. Menyusun output akhir...")
final_output = format_output_markdown(response_json, search_links)
print("--- Proses Selesai ---")
return final_output
except Exception as e:
print(f"π ERROR DALAM FUNGSI ANALISIS: {e}")
raise gr.Error(f"Terjadi kesalahan: {e}")
# --- MEMBUAT INTERFACE GRADIO ---
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# π Aplikasi Analis Peluang Karir Personal")
gr.Markdown("Upload CV Anda, dan biarkan AI membuat laporan komprehensif tentang jalur karir terbaik Anda, lengkap dengan tautan pencarian kerja!")
with gr.Row():
with gr.Column(scale=1):
cv_pdf = gr.File(label="Upload CV Anda (PDF)", file_types=[".pdf"])
analyze_button = gr.Button("π Analisis Karir Saya", variant="primary")
with gr.Column(scale=2):
output_analysis = gr.Markdown(label="Laporan Peluang Karir Anda")
analyze_button.click(
fn=analyze_career_path,
inputs=[cv_pdf],
outputs=[output_analysis],
show_progress='full'
)
if __name__ == "__main__":
demo.launch() |