chatbot / app.py
irhamni's picture
Rename app (4).py to app.py
e85e049 verified
# -*- coding: utf-8 -*-
"""app.ipynb
Automatically generated by Colab.
Original file is located at
https://colab.research.google.com/drive/1aiG3WNZzfqKvIQLQ8wVnGMoPiXIWvmNZ
"""
import pandas as pd
from sentence_transformers import SentenceTransformer, util
import gradio as gr
import numpy as np
# --- 1. Konfigurasi dan Pemuatan Data ---
# Nama file CSV yang diunggah
CSV_FILE_NAME = "perpustakaan_faq (2).csv"
# Inisialisasi Model Sentence Transformer berbasis IndoBERT
# Menggunakan model Sentence Transformer yang fine-tuned untuk Bahasa Indonesia
# Pilihan: 'paraphrase-multilingual-mpnet-base-v2' (Multilingual, performa kuat)
# atau model khusus IndoBERT jika tersedia versi S-BERT-nya.
# Karena ketersediaan, kita pakai multilingual yang terbukti kuat di B. Indonesia.
# Jika ingin murni IndoBERT, bisa menggunakan 'indobenchmark/indobert-base-p1'
# dan menyesuaikan proses untuk semantic search.
# Kita gunakan model yang sudah teruji kuat untuk similarity di B. Indonesia:
MODEL_NAME = 'paraphrase-multilingual-mpnet-base-v2'
# Pilihan ini merupakan model multilingual terbaik yang mendukung Indonesia dan
# lebih mudah diintegrasikan dengan S-BERT daripada IndoBERT murni.
try:
print(f"Mengunduh dan memuat model Indo-friendly Sentence Transformer: {MODEL_NAME}...")
# Model ini akan tetap memberikan hasil yang lebih baik daripada all-MiniLM-L6-v2
# untuk bahasa Indonesia karena sifat multilingualnya.
model = SentenceTransformer(MODEL_NAME)
print("Model berhasil dimuat.")
except Exception as e:
print(f"Error memuat model: {e}. Pastikan koneksi internet.")
# Jika gagal, bisa coba fallback ke model yang lebih kecil
MODEL_NAME = 'all-MiniLM-L6-v2'
print(f"Mencoba fallback ke model: {MODEL_NAME}")
model = SentenceTransformer(MODEL_NAME)
# Pemuatan data dari file CSV
def load_and_preprocess_data(csv_data_path):
"""Memuat data FAQ dari CSV dan menghasilkan embeddings."""
try:
# Memuat CSV dari path yang diakses
df = pd.read_csv(csv_data_path)
print(f"Data berhasil dimuat. Total {len(df)} FAQ ditemukan.")
# Ambil kolom yang dibutuhkan (user_query -> Question, chatbot_response -> Answer)
df = df.rename(columns={'user_query': 'Question', 'chatbot_response': 'Answer'})
df['Question'] = df['Question'].astype(str).str.strip()
df['Answer'] = df['Answer'].astype(str).str.strip()
# Generate Embeddings untuk semua pertanyaan FAQ
print("Mulai menghasilkan embeddings untuk pertanyaan FAQ dengan model Indo-friendly...")
corpus_embeddings = model.encode(df['Question'].tolist(), convert_to_tensor=True)
print("Embeddings selesai dibuat.")
return df, corpus_embeddings
except Exception as e:
print(f"Error saat memproses data: {e}")
return None, None
# Menggunakan data yang diunggah
df_faq, corpus_embeddings = load_and_preprocess_data(CSV_FILE_NAME)
if df_faq is None:
raise Exception("Gagal memuat atau memproses data FAQ. Chatbot tidak dapat dijalankan.")
# --- 2. Fungsi Chatbot (Semantic Search) ---
def library_chatbot(user_input, top_k=1, score_threshold=0.6):
"""
Fungsi inti chatbot: Menerima input pengguna, mencari pertanyaan paling mirip
secara semantik (menggunakan IndoBERT-friendly embeddings), dan mengembalikan jawabannya.
"""
if not user_input:
return "Silakan ajukan pertanyaan terkait perpustakaan!"
# 1. Encode input pengguna menggunakan model yang sudah dilatih
query_embedding = model.encode(user_input, convert_to_tensor=True)
# 2. Hitung Cosine Similarity antara input pengguna dan semua pertanyaan FAQ
# util.semantic_search mengembalikan hasil yang sudah diurutkan
hits = util.semantic_search(query_embedding, corpus_embeddings, top_k=top_k)
# Ambil hasil terbaik
best_hit = hits[0][0] # hits adalah list of list
# 3. Tentukan apakah skor kemiripan cukup tinggi
score = best_hit['score']
if score >= score_threshold:
# Ditemukan jawaban yang relevan
index = best_hit['corpus_id']
# matched_question = df_faq.iloc[index]['Question'] # Untuk debug
response_answer = df_faq.iloc[index]['Answer']
return response_answer
else:
# Skor terlalu rendah, anggap tidak ada jawaban yang relevan di data FAQ
return (
"Mohon maaf, saya tidak menemukan jawaban yang cocok untuk pertanyaan Anda "
"dalam data FAQ yang tersedia. Coba tanyakan dengan kata kunci yang berbeda "
"atau hubungi staf perpustakaan secara langsung."
)
# --- 3. Antarmuka Gradio ---
# Membuat list pertanyaan contoh untuk memudahkan user
example_questions = [
"Saya mau pinjam buku, bagaimana prosedurnya?",
"Apa syarat buat kartu anggota perpustakaan?",
"Jam berapa perpustakaan ini mulai buka?",
"Saya ingin menggunakan internet, apakah tersedia wifi gratis?",
"Kalau telat mengembalikan, dendanya berapa?",
]
# Definisi antarmuka Gradio
iface = gr.Interface(
fn=library_chatbot,
inputs=gr.Textbox(lines=2, placeholder="Ketik pertanyaan Anda tentang perpustakaan..."),
outputs=gr.Textbox(label="Jawaban Chatbot"),
title="📚 Chatbot FAQ Perpustakaan (IndoBERT-Friendly)",
description=(
f"Chatbot ini menggunakan model Semantic Search ({MODEL_NAME}) untuk menjawab pertanyaan Anda "
"berdasarkan data FAQ perpustakaan. Tanyakan hal-hal terkait peminjaman, keanggotaan, atau layanan."
),
examples=example_questions
)
# Jalankan antarmuka Gradio
iface.launch()