CV2 / app.py
firmanaziz's picture
Update app.py
d76087e verified
raw
history blame
5.9 kB
# 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()