Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| from transformers import pipeline, AutoModelForQuestionAnswering, AutoTokenizer | |
| import gradio as gr | |
| import re | |
| import os | |
| # --- 1. Persiapan Data dan Model --- | |
| # Nama file CSV yang diunggah | |
| CSV_FILE = "perpustakaan_faq.csv" | |
| questions = [] | |
| answers = [] | |
| MODEL_LOADED = False | |
| qa_pipeline = None | |
| # Memuat data dari CSV | |
| try: | |
| df = pd.read_csv(CSV_FILE) | |
| # Kolom 'chatbot_response' akan dijadikan Konteks utama (Basis Pengetahuan) | |
| questions = df['user_query'].tolist() | |
| answers = df['chatbot_response'].tolist() | |
| except FileNotFoundError: | |
| print(f"Error: File '{CSV_FILE}' tidak ditemukan. Pastikan file berada di direktori yang sama.") | |
| except Exception as e: | |
| print(f"Error saat memuat atau memproses data CSV: {e}") | |
| # Inisialisasi Model Question Answering Bahasa Indonesia | |
| # Catatan: Jika model ini tetap gagal dimuat, sistem akan otomatis menggunakan fallback. | |
| try: | |
| model_name = "indobenchmark/indobert-base-uncased-squad" | |
| # Coba muat model dan tokenizer | |
| model = AutoModelForQuestionAnswering.from_pretrained(model_name) | |
| tokenizer = AutoTokenizer.from_pretrained(model_name) | |
| # Inisialisasi pipeline QA | |
| qa_pipeline = pipeline( | |
| "question-answering", | |
| model=model, | |
| tokenizer=tokenizer | |
| ) | |
| MODEL_LOADED = True | |
| print(f"Model {model_name} berhasil dimuat.") | |
| except Exception as e: | |
| print(f"Error memuat model Question Answering ({model_name}): {e}") | |
| MODEL_LOADED = False | |
| print("Menggunakan fallback (pencocokan kata kunci sederhana) karena model gagal dimuat.") | |
| # --- 2. Fungsi Logika Chatbot --- | |
| def preprocess_query(query): | |
| """Membersihkan dan menormalkan query.""" | |
| query = query.lower().strip() | |
| query = re.sub(r'[^\w\s]', '', query) | |
| return query | |
| def get_answer_from_qa_model(query): | |
| """ | |
| Mencari jawaban menggunakan Model Question Answering dari semua konteks (Answers). | |
| """ | |
| best_answer = "Maaf, saya tidak menemukan informasi yang relevan untuk pertanyaan Anda. Silakan coba pertanyaan lain atau hubungi meja informasi perpustakaan." | |
| best_score = 0.0 | |
| for original_answer in answers: | |
| try: | |
| result = qa_pipeline( | |
| question=query, | |
| context=original_answer | |
| ) | |
| if result['score'] > best_score: | |
| best_score = result['score'] | |
| best_answer = result['answer'] | |
| if best_score > 0.95: | |
| break | |
| except Exception: | |
| continue | |
| if best_score < 0.3: | |
| return "Maaf, saya tidak menemukan informasi yang relevan untuk pertanyaan Anda. Silakan coba pertanyaan lain atau hubungi meja informasi perpustakaan." | |
| return best_answer | |
| def get_answer_fallback(query): | |
| """ | |
| Fungsi fallback sederhana berdasarkan pencocokan kata kunci. | |
| """ | |
| if not answers: | |
| return "Maaf, data FAQ perpustakaan belum termuat." | |
| preprocessed_query = preprocess_query(query) | |
| best_match_answer = "Maaf, saya tidak menemukan informasi yang relevan untuk pertanyaan Anda. Silakan coba pertanyaan lain atau hubungi meja informasi perpustakaan." | |
| max_matches = 0 | |
| query_words = set(word for word in preprocessed_query.split() if len(word) > 3) | |
| for q_data, a_data in zip(questions, answers): | |
| q_data_words = set(word for word in preprocess_query(q_data).split() if len(word) > 3) | |
| matches = len(query_words.intersection(q_data_words)) | |
| if matches > max_matches: | |
| max_matches = matches | |
| best_match_answer = a_data | |
| if max_matches < 1: | |
| return "Maaf, saya tidak menemukan informasi yang relevan untuk pertanyaan Anda. Silakan coba pertanyaan lain atau hubungi meja informasi perpustakaan." | |
| return best_match_answer | |
| def chatbot_response(user_query, history): | |
| """ | |
| Fungsi utama yang dipanggil oleh Gradio. | |
| """ | |
| if not user_query or not user_query.strip(): | |
| return "Halo! Silakan ajukan pertanyaan seputar layanan perpustakaan." | |
| if MODEL_LOADED: | |
| response = get_answer_from_qa_model(user_query) | |
| else: | |
| response = get_answer_fallback(user_query) | |
| return response | |
| # --- 3. Implementasi Gradio Interface --- | |
| # Deskripsi Interface | |
| title = "🤖 Chatbot Layanan Perpustakaan" | |
| # Informasi model untuk ditampilkan di deskripsi | |
| model_info = ( | |
| "Model QA: **" + ("indobenchmark/indobert-base-uncased-squad" if MODEL_LOADED else "Fallback Keyword Match") + "** | " | |
| "Data Sumber: `perpustakaan_faq.csv`" | |
| ) | |
| description = ( | |
| "Ini adalah Chatbot Tanya Jawab (Question Answering) yang dibuat dari data " | |
| "FAQ Perpustakaan. Silakan ajukan pertanyaan seputar keanggotaan, peminjaman, kunjungan, atau fasilitas." | |
| f"\n\n---\n\n{model_info}" | |
| ) | |
| # Contoh pertanyaan untuk memandu pengguna | |
| examples = [ | |
| ["Berapa lama batas waktu peminjaman buku?"], | |
| ["Apa syarat utama jika saya mau buat kartu anggota perpustakaan?"], | |
| ["Apakah ada loker penitipan barang di sini?"], | |
| ["Bolehkah saya membawa laptop pribadi ke dalam perpustakaan?"] | |
| ] | |
| # Pembuatan Gradio Interface | |
| iface = gr.ChatInterface( | |
| fn=chatbot_response, | |
| title=title, | |
| description=description, | |
| examples=examples, | |
| chatbot=gr.Chatbot( | |
| height=400, | |
| label="Asisten Perpustakaan", | |
| # --- PERBAIKAN FATAL: Menghapus parameter 'type' yang menyebabkan TypeError --- | |
| # type="messages", | |
| ), | |
| ) | |
| if __name__ == "__main__": | |
| iface.launch() |