Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import google.generativeai as genai | |
| import fitz # PyMuPDF | |
| import json | |
| import os | |
| import urllib.parse | |
| import base64 # Diperlukan untuk client-side API call | |
| # --- KONFIGURASI API KEY (TETAP SAMA) --- | |
| 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): | |
| 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://www.jobstreet.co.id/id/job-search/{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 analyze_career_path(cv_file): | |
| """Fungsi utama pipeline: Analisis CV -> Buat Laporan JSON -> Buat Link -> Gabungkan.""" | |
| 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 ---") | |
| 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". Baca teks CV dan buat laporan peluang karir dalam format JSON. | |
| Teks CV: --- {teks_cv} --- | |
| Struktur JSON yang diinginkan: | |
| - "jabatan_ideal": Jabatan paling ideal untuk kandidat. | |
| - "alasan_kecocokan": Array (list) berisi 3-4 poin MENGAPA kandidat cocok. | |
| - "deskripsi_pekerjaan": Array (list) berisi 5 poin deskripsi pekerjaan umum. | |
| - "potensi_karir": Array (list) berisi 3-4 jalur pengembangan karir. | |
| - "kisaran_gaji": Objek JSON berisi estimasi gaji untuk level "junior", "mid_level", dan "senior". | |
| - "kelebihan_tambahan": Array (list) berisi 1-2 poin saran atau kelebihan unik kandidat. | |
| 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.") | |
| print("3. Membuat tautan pencarian dari hasil analisis...") | |
| keywords_from_analysis = response_json.get("jabatan_ideal", "") | |
| search_links = generate_search_links(keywords_from_analysis) | |
| # ================================================================== | |
| # PERUBAHAN PENTING: Menambahkan link ke dalam JSON | |
| # ================================================================== | |
| response_json["tautan_pencarian"] = search_links | |
| print("β Tautan pencarian ditambahkan ke JSON.") | |
| print("--- Proses Selesai ---") | |
| # Mengembalikan dictionary/JSON mentah | |
| return response_json | |
| 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("# π API Analis Peluang Karir Personal") | |
| gr.Markdown("Antarmuka ini dapat digunakan untuk pengujian. Endpoint API publik tersedia di `/run/predict` untuk integrasi ke website Anda.") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| cv_pdf = gr.File(label="Upload CV (PDF) untuk Uji Coba", file_types=[".pdf"]) | |
| analyze_button = gr.Button("π Analisis Karir Saya", variant="primary") | |
| with gr.Column(scale=2): | |
| # Menggunakan gr.JSON untuk menampilkan dan menghasilkan data JSON sebagai output API | |
| output_analysis = gr.JSON(label="Output JSON dari API") | |
| analyze_button.click( | |
| fn=analyze_career_path, | |
| inputs=[cv_pdf], | |
| outputs=[output_analysis], | |
| show_progress='full' | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |