File size: 5,594 Bytes
08e6a85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# -*- 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()