File size: 6,481 Bytes
f7ef9f6
a325830
40ca111
 
f7ef9f6
40ca111
 
a325830
40ca111
a325830
40ca111
 
ecb0859
40ca111
 
 
 
 
d60f2e2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dbf5679
d60f2e2
 
40ca111
d60f2e2
 
 
 
 
 
 
 
 
 
40ca111
d60f2e2
 
40ca111
 
 
 
f7ef9f6
 
40ca111
 
 
f7ef9f6
 
54188da
40ca111
 
 
 
800796c
f7ef9f6
800796c
f7ef9f6
54188da
40ca111
 
 
f7ef9f6
40ca111
 
 
ecb0859
 
 
f7ef9f6
40ca111
a325830
ecb0859
 
40ca111
e433088
a325830
ecb0859
40ca111
a325830
f7ef9f6
a325830
40ca111
 
 
f7ef9f6
643d9db
f7ef9f6
 
643d9db
f7ef9f6
 
 
40ca111
 
 
d9103af
40ca111
98032d3
d9103af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f7ef9f6
 
 
d9103af
 
 
 
 
 
f7ef9f6
 
d9103af
 
1ff4c99
d9103af
 
40ca111
a325830
 
40ca111
 
 
a325830
40ca111
f7ef9f6
98032d3
 
40ca111
f7ef9f6
98032d3
 
40ca111
98032d3
 
 
40ca111
98032d3
 
 
 
 
 
a325830
f7ef9f6
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# Import Library yang Diperlukan
import gradio as gr
import gspread
from oauth2client.service_account import ServiceAccountCredentials
from llama_cpp import Llama
from llama_index.core import VectorStoreIndex, Settings
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.llama_cpp import LlamaCPP
from huggingface_hub import hf_hub_download
from llama_index.core.llms import ChatMessage
from llama_index.core.chat_engine.condense_plus_context import CondensePlusContextChatEngine
from llama_index.core.schema import Document

# ===================================
# 1๏ธโƒฃ Fungsi untuk Membaca Google Spreadsheet
# ===================================
def read_google_sheet():
    try:
        # Tentukan scope akses ke Google Sheets & Drive
        scope = ["https://www.googleapis.com/auth/spreadsheets", "https://www.googleapis.com/auth/drive"]
        
        # Load kredensial dari file credentials.json
        creds = ServiceAccountCredentials.from_json_keyfile_name("credentials.json", scope)
        client = gspread.authorize(creds)
        
        # ๐Ÿ“Œ Gunakan ID Spreadsheet (lebih aman)
        SPREADSHEET_ID = "1e_cNMhwF-QYpyYUpqQh-XCw-OdhWS6EuYsoBUsVtdNg"  # ๐Ÿ”น Ganti dengan ID spreadsheet Anda
        SHEET_NAME = "datatarget"  # ๐Ÿ”น Ganti dengan nama sheet
        
        # Buka spreadsheet dan worksheet
        spreadsheet = client.open_by_key(SPREADSHEET_ID)
        sheet = spreadsheet.worksheet(SHEET_NAME)

        # Ambil semua data dalam bentuk list (baris & kolom)
        data = sheet.get_all_values()

        # Format ulang data menjadi satu teks panjang (dapat disesuaikan)
        formatted_text = "\n".join([" | ".join(row) for row in data])
        
        return formatted_text
    
    except gspread.exceptions.SpreadsheetNotFound:
        return "โŒ ERROR: Spreadsheet tidak ditemukan. Pastikan ID/nama benar!"
    
    except gspread.exceptions.WorksheetNotFound:
        return "โŒ ERROR: Worksheet tidak ditemukan. Periksa kembali nama sheet!"
    
    except Exception as e:
        return f"โŒ ERROR: {str(e)}"

# ===================================
# 2๏ธโƒฃ Fungsi untuk Mengunduh Model Llama
# ===================================
def initialize_llama_model():
    model_path = hf_hub_download(
        repo_id="TheBLoke/zephyr-7b-beta-GGUF",  # ๐Ÿ“Œ Repo model HuggingFace
        filename="zephyr-7b-beta.Q4_K_M.gguf",  # ๐Ÿ“Œ Nama file model
        cache_dir="./models"
    )
    return model_path

# ===================================
# 3๏ธโƒฃ Inisialisasi Model dan Pengaturan
# ===================================
def initialize_settings(model_path):
    Settings.llm = LlamaCPP(
        model_path=model_path,
        temperature=0.7,
    )

# ===================================
# 4๏ธโƒฃ Inisialisasi Index dari Data Spreadsheet
# ===================================
def initialize_index():
    # ๐Ÿ”น Ambil teks dari Google Spreadsheet
    text_data = read_google_sheet()

    # ๐Ÿ”น Konversi teks ke dalam format dokumen yang benar
    document = Document(text=text_data)  # ๐Ÿ”น Ubah teks menjadi objek `Document`
    documents = [document]  # ๐Ÿ”น Masukkan ke dalam list

    # ๐Ÿ”น Proses data menjadi node untuk vektor embedding
    parser = SentenceSplitter(chunk_size=150, chunk_overlap=10)
    nodes = parser.get_nodes_from_documents(documents)  # โœ… Sekarang `documents` adalah list of `Document`

    # ๐Ÿ”น Gunakan model embedding
    embedding = HuggingFaceEmbedding("sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")
    Settings.embed_model = embedding

    # ๐Ÿ”น Buat index vektor
    index = VectorStoreIndex(nodes)
    return index

# ===================================
# 5๏ธโƒฃ Inisialisasi Mesin Chatbot
# ===================================
def initialize_chat_engine(index):
    retriever = index.as_retriever(similarity_top_k=3)
    chat_engine = CondensePlusContextChatEngine.from_defaults(
        retriever=retriever,
        verbose=True,
    )
    return chat_engine

# ===================================
# 6๏ธโƒฃ Fungsi untuk Menghasilkan Respons Chatbot
# ===================================
def generate_response(message, history):
    if history is None:
        history = []
    
    # ๐Ÿ”น Ambil data terbaru dari Google Spreadsheet setiap kali ada pertanyaan
    text_data = read_google_sheet()
    document = Document(text=text_data)
    documents = [document]

    # ๐Ÿ”น Perbarui index dengan data terbaru
    parser = SentenceSplitter(chunk_size=150, chunk_overlap=10)
    nodes = parser.get_nodes_from_documents(documents)
    index = VectorStoreIndex(nodes)
    retriever = index.as_retriever(similarity_top_k=3)

    # ๐Ÿ”น Buat ulang chat engine dengan index yang diperbarui
    chat_engine = CondensePlusContextChatEngine.from_defaults(
        retriever=retriever,
        verbose=True,
    )

    chat_messages = [
        ChatMessage(
            role="system",
            content="Anda adalah chatbot yang cerdas dan sopan. "
            "Jawablah semua pertanyaan dalam bahasa Indonesia dengan jelas dan mudah dipahami. "
            "Gunakan gaya bahasa yang profesional tetapi tetap ramah. "
            "Jika informasi tidak tersedia di dokumen, beritahukan dengan sopan bahwa Anda tidak memiliki informasi tersebut. "
            "Jangan menjawab dalam bahasa lain selain Bahasa Indonesia. "
            "Fokuslah memberikan jawaban yang akurat dan relevan sesuai dengan dokumen yang tersedia."
        ),
    ]

    # ๐Ÿ”น Gunakan chat engine baru untuk menjawab pertanyaan
    response = chat_engine.stream_chat(message)
    text = "".join(response.response_gen)

    history.append((message, text))
    return history

# ===================================
# 7๏ธโƒฃ Fungsi Utama untuk Menjalankan Aplikasi
# ===================================
def main():
    # ๐Ÿ”น Unduh model dan inisialisasi pengaturan
    model_path = initialize_llama_model()
    initialize_settings(model_path)  

    # ๐Ÿ”น Inisialisasi index dan chat engine
    index = initialize_index()
    chat_engine = initialize_chat_engine(index)  

    # ๐Ÿ”น Fungsi untuk chat
    def chatbot_response(message, history):
        return generate_response(message, history, chat_engine)  

    # ๐Ÿ”น Luncurkan Gradio UI
    gr.Interface(
        fn=chatbot_response,
        inputs=["text"],
        outputs=["text"],
    ).launch()

if __name__ == "__main__":
    main()