Spaces:
Sleeping
Sleeping
File size: 5,903 Bytes
4f4d6f1 446c80c 4f4d6f1 446c80c d76087e 446c80c 4f4d6f1 446c80c 4f4d6f1 446c80c 4f4d6f1 446c80c 720a543 446c80c 720a543 446c80c 720a543 4f4d6f1 720a543 446c80c 720a543 4f4d6f1 720a543 4f4d6f1 446c80c 720a543 4f4d6f1 720a543 446c80c 720a543 446c80c 720a543 446c80c 720a543 446c80c 4f4d6f1 720a543 4f4d6f1 720a543 4f4d6f1 720a543 4f4d6f1 |
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 |
# 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
# --- 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-flash-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 clean_and_parse_json(raw_text):
"""Fungsi andal untuk membersihkan dan mem-parsing JSON dari teks mentah."""
start_index = raw_text.find('{')
end_index = raw_text.rfind('}')
if start_index == -1 or end_index == -1:
raise json.JSONDecodeError("Tidak ditemukan blok JSON valid dalam respons.", raw_text, 0)
json_str = raw_text[start_index:end_index+1]
return json.loads(json_str)
def format_output_markdown(hasil_penilaian):
"""Menyusun hasil penilaian menjadi string Markdown yang rapi."""
skor = hasil_penilaian.get('skor_keseluruhan', 0)
penilaian = hasil_penilaian.get('penilaian_per_kategori', {})
kelebihan = "\n".join([f"- {poin}" for poin in hasil_penilaian.get('poin_kelebihan', [])])
perbaikan = "\n".join([f"- {poin}" for poin in hasil_penilaian.get('poin_perbaikan', [])])
# Membuat progress bar untuk setiap kategori
progress_bars = ""
for kategori, nilai in penilaian.items():
# Mengganti underscore dengan spasi dan membuat judul
nama_kategori = kategori.replace("_", " ").title()
progress_bars += f"**{nama_kategori}**\n`{'β' * int(nilai/10)}{'β' * (10 - int(nilai/10))}` {nilai}/100\n"
return f"""
### HASIL PENILAIAN CV ANDA
**β Skor Keseluruhan: {skor} / 100**
***
{progress_bars}
***
**β
Hal yang Sudah Baik:**
{kelebihan}
**π‘ Poin yang Perlu Diperbaiki:**
{perbaikan}
"""
def score_cv(cv_file):
"""Fungsi utama yang dijalankan Gradio untuk menilai CV."""
if not API_CONFIGURED:
raise gr.Error("API Key Gemini belum terkonfigurasi. Periksa Logs aplikasi di Hugging Face.")
if cv_file is None:
raise gr.Error("Mohon upload file CV (PDF) Anda.")
try:
print("--- Memulai Proses Penilaian CV ---")
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 penilaian ke Gemini...")
prompt_penilaian = f"""
Anda adalah seorang career coach dan perekrut profesional. Tugas Anda adalah menilai kualitas sebuah CV berdasarkan kriteria standar industri.
Teks CV:
---
{teks_cv}
---
Lakukan penilaian berdasarkan kriteria berikut dan berikan output dalam format JSON yang ketat.
Kriteria Penilaian:
1. Kelengkapan_Informasi (0-100): Apakah ada nama, kontak, ringkasan, pengalaman, pendidikan, dan skill?
2. Keterbacaan_dan_Format (0-100): Apakah formatnya rapi, mudah dibaca, dan menggunakan bullet points dengan baik?
3. Dampak_Pengalaman_Kerja (0-100): Apakah deskripsi pengalaman menggunakan kata kerja aktif dan hasil yang terukur (angka/metrik)? Semakin banyak metrik, semakin tinggi nilainya.
Instruksi Output JSON:
Berikan output dalam format JSON dengan struktur berikut:
- "skor_keseluruhan": Rata-rata dari ketiga skor kategori (angka 0-100).
- "penilaian_per_kategori": Objek berisi skor untuk "kelengkapan_informasi", "keterbacaan_dan_format", dan "dampak_pengalaman_kerja".
- "poin_kelebihan": Sebuah array (list) berisi 2-3 poin positif dari CV ini.
- "poin_perbaikan": Sebuah array (list) berisi 3-4 poin saran yang paling penting dan actionable untuk meningkatkan kualitas CV.
Pastikan output hanya berupa JSON saja tanpa teks tambahan.
"""
response = model.generate_content(prompt_penilaian)
hasil_penilaian = clean_and_parse_json(response.text)
print("β
Penilaian berhasil diterima.")
print("3. Menyusun output akhir...")
final_output = format_output_markdown(hasil_penilaian)
print("--- Proses Selesai ---")
return final_output
except Exception as e:
print(f"π ERROR DALAM FUNGSI PENILAIAN: {e}")
raise gr.Error(f"Terjadi kesalahan: {e}")
# --- MEMBUAT INTERFACE GRADIO ---
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("# π‘ Aplikasi Penilai Kualitas CV (CV Scorer)")
gr.Markdown("Upload CV Anda dalam format PDF untuk mendapatkan skor dan saran perbaikan instan berdasarkan standar industri.")
with gr.Row():
with gr.Column(scale=1):
cv_pdf = gr.File(label="Upload CV Anda (PDF)", file_types=[".pdf"])
score_button = gr.Button("β¨ Nilai CV Saya", variant="primary")
with gr.Column(scale=2):
output_score = gr.Markdown(label="Hasil Penilaian")
score_button.click(
fn=score_cv,
inputs=[cv_pdf],
outputs=[output_score],
show_progress='full'
)
if __name__ == "__main__":
demo.launch() |