File size: 14,497 Bytes
d24bd61
332f4de
 
 
 
 
109534c
 
332f4de
 
 
 
 
 
 
20469f9
 
 
 
 
 
109534c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332f4de
109534c
 
332f4de
 
 
109534c
 
332f4de
 
 
109534c
 
332f4de
 
 
109534c
 
332f4de
 
 
109534c
 
332f4de
 
 
109534c
 
332f4de
 
 
109534c
 
332f4de
 
 
109534c
 
332f4de
 
 
109534c
 
332f4de
 
 
109534c
 
332f4de
 
 
36ccf13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332f4de
 
 
 
 
 
 
 
 
 
 
 
109534c
332f4de
 
109534c
ab768fb
655652e
332f4de
 
 
 
 
 
51c5391
 
ab768fb
 
 
332f4de
 
 
 
 
655652e
ab768fb
109534c
f1128cd
 
ab768fb
 
332f4de
 
 
 
6915dbd
 
 
332f4de
 
 
3534f8f
f8c2797
53da814
 
 
0298fd9
 
53da814
 
332f4de
 
 
 
 
 
20469f9
 
 
 
 
 
 
 
 
 
 
 
d24bd61
 
 
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
from fastapi import FastAPI
from langchain_qdrant import QdrantVectorStore
from qdrant_client import QdrantClient
from qdrant_client.http.models import Distance, VectorParams

from langchain_qdrant import FastEmbedSparse, QdrantVectorStore, RetrievalMode
from langchain_community.embeddings.fastembed import FastEmbedEmbeddings

from qdrant_client import QdrantClient, models
from qdrant_client.http.models import Distance, SparseVectorParams, VectorParams

from uuid import uuid4

from langchain_core.documents import Document

from typing import Union, List, Dict, Any
from pydantic import BaseModel, Field

class Data(BaseModel):
    items: Union[Dict[str, Any], List[Dict[str, Any]]] = Field(..., description="Either a dictionary or a list of dictionaries.")

# document_1 = Document(
#     page_content="I had chocolate chip pancakes and scrambled eggs for breakfast this morning.",
#     metadata={"source": "tweet"},
# )

# document_2 = Document(
#     page_content="The weather forecast for tomorrow is cloudy and overcast, with a high of 62 degrees Fahrenheit.",
#     metadata={"source": "news"},
# )

# document_3 = Document(
#     page_content="Building an exciting new project with LangChain - come check it out!",
#     metadata={"source": "tweet"},
# )

# document_4 = Document(
#     page_content="Robbers broke into the city bank and stole $1 million in cash.",
#     metadata={"source": "news"},
# )

# document_5 = Document(
#     page_content="Wow! That was an amazing movie. I can't wait to see it again.",
#     metadata={"source": "tweet"},
# )

# document_6 = Document(
#     page_content="Is the new iPhone worth the price? Read this review to find out.",
#     metadata={"source": "website"},
# )

# document_7 = Document(
#     page_content="The top 10 soccer players in the world right now.",
#     metadata={"source": "website"},
# )

# document_8 = Document(
#     page_content="LangGraph is the best framework for building stateful, agentic applications!",
#     metadata={"source": "tweet"},
# )

# document_9 = Document(
#     page_content="The stock market is down 500 points today due to fears of a recession.",
#     metadata={"source": "news"},
# )

# document_10 = Document(
#     page_content="I have a bad feeling I am going to get deleted :(",
#     metadata={"source": "tweet"},
# )

# documents = [
#     document_1,
#     document_2,
#     document_3,
#     document_4,
#     document_5,
#     document_6,
#     document_7,
#     document_8,
#     document_9,
#     document_10,
# ]
# uuids = [str(uuid4()) for _ in range(len(documents))]

# docs = documents


# from uuid import uuid4
# from langchain.schema import Document

document_1 = Document(
    page_content="Aduan: Saya tidak bisa login ke sistem e-learning.\nJawaban: Kami menemukan bahwa akun Anda terkunci setelah tiga kali gagal login. Kami telah membuka kunci akun dan menyarankan Anda untuk melakukan reset password menggunakan fitur 'Lupa Kata Sandi'.",
    metadata={"source": "Aduan"},
)

document_2 = Document(
    page_content="Request: Mohon bantuannya untuk mendapatkan akses ke folder tim di server.\nJawaban: Kami telah menambahkan akun Anda ke grup pengguna 'Tim IT' di Active Directory. Akses ke folder sekarang dapat dilakukan setelah Anda login ulang.",
    metadata={"source": "Request"},
)

document_3 = Document(
    page_content="Incident: Laporan printer di lantai 3 tidak bisa mencetak.\nJawaban: Kami melakukan restart pada spooler service di perangkat printer dan membersihkan antrian cetak yang bermasalah. Printer sudah kembali normal.",
    metadata={"source": "Incident"},
)

document_4 = Document(
    page_content="Aduan: Email saya sering masuk ke folder spam penerima.\nJawaban: Kami periksa konfigurasi SPF, DKIM, dan DMARC pada domain Anda. Ternyata ada konfigurasi SPF yang tidak lengkap. Kami telah memperbaikinya dan hasil pengujian sudah menunjukkan pengiriman email berjalan normal.",
    metadata={"source": "Aduan"},
)

document_5 = Document(
    page_content="Request: Saya membutuhkan instalasi software AutoCAD untuk proyek desain.\nJawaban: Kami telah mengunduh versi terbaru dari situs resmi AutoDesk dan melakukan instalasi di laptop Anda. Lisensi telah diaktivasi menggunakan akun universitas.",
    metadata={"source": "Request"},
)

document_6 = Document(
    page_content="Incident: Sistem ERP tidak bisa mengakses modul keuangan sejak pagi.\nJawaban: Kami temukan bahwa service database MySQL berhenti secara tiba-tiba. Service telah kami nyalakan kembali dan modul keuangan kini dapat diakses kembali.",
    metadata={"source": "Incident"},
)

document_7 = Document(
    page_content="Aduan: Aplikasi mobile sering crash saat dibuka.\nJawaban: Kami analisis log error dan menemukan bug pada fitur notifikasi. Kami telah melakukan patch pada versi 1.2.3 dan memperbarui aplikasi Anda melalui MDM.",
    metadata={"source": "Aduan"},
)

document_8 = Document(
    page_content="Request: Mohon dibuatkan email dinas baru untuk staf baru di departemen HR.\nJawaban: Email telah dibuat dengan format [email protected] dan password default. Informasi login telah kami kirimkan melalui email pribadi yang terdaftar.",
    metadata={"source": "Request"},
)

document_9 = Document(
    page_content="Incident: Koneksi internet putus-putus di gedung B.\nJawaban: Kami lakukan pengecekan router dan mengganti kabel jaringan yang rusak di lantai 2. Koneksi kini stabil dan normal.",
    metadata={"source": "Incident"},
)

document_10 = Document(
    page_content="Aduan: Layar laptop saya berkedip-kedip.\nJawaban: Masalah disebabkan oleh driver grafis yang tidak kompatibel. Kami telah menginstal versi driver yang sesuai dengan perangkat Anda dan masalah layar sudah tidak muncul lagi.",
    metadata={"source": "Aduan"},
)

documents = [
    Document(
        page_content="Aduan: Tidak bisa login ke sistem akademik.\nJawaban: Kami periksa bahwa akun Anda belum terverifikasi oleh admin fakultas. Setelah verifikasi dilakukan, Anda dapat login kembali.",
        metadata={"source": "Aduan"},
    ),
    Document(
        page_content="Aduan: Tidak bisa login ke sistem akademik.\nJawaban: Kami menemukan bahwa browser Anda menyimpan cache lama. Setelah Anda membersihkan cache dan cookies, akses sistem berhasil dilakukan.",
        metadata={"source": "Aduan"},
    ),
    Document(
        page_content="Request: Permintaan instalasi Adobe Photoshop.\nJawaban: Kami sudah menginstal Adobe Photoshop versi 2024 dengan lisensi institusi dan memastikan kompatibilitas dengan perangkat Anda.",
        metadata={"source": "Request"},
    ),
    Document(
        page_content="Request: Permintaan instalasi Adobe Photoshop.\nJawaban: Software tidak tersedia dalam lisensi institusi. Kami menyarankan penggunaan alternatif GIMP, yang telah kami instal dan konfigurasi sesuai kebutuhan Anda.",
        metadata={"source": "Request"},
    ),
    Document(
        page_content="Incident: Email tidak terkirim ke eksternal.\nJawaban: Kami periksa log email server dan menemukan bahwa IP server masuk daftar hitam. Kami sudah lakukan delisting dan konfigurasi ulang DNS.",
        metadata={"source": "Incident"},
    ),
    Document(
        page_content="Incident: Email tidak terkirim ke eksternal.\nJawaban: SMTP relay yang digunakan mengalami gangguan. Kami sudah ubah sementara ke relay backup agar email tetap dapat dikirim.",
        metadata={"source": "Incident"},
    ),
    Document(
        page_content="Aduan: Sistem presensi tidak mencatat kehadiran saya.\nJawaban: Ditemukan bahwa fingerprint scanner tidak tersambung ke jaringan. Kami restart koneksi dan sistem kembali berfungsi.",
        metadata={"source": "Aduan"},
    ),
    Document(
        page_content="Aduan: Sistem presensi tidak mencatat kehadiran saya.\nJawaban: Waktu di sistem berbeda 5 menit dari waktu server. Sinkronisasi waktu berhasil menyelesaikan masalah.",
        metadata={"source": "Aduan"},
    ),
    Document(
        page_content="Request: Tambah user baru ke sistem absensi.\nJawaban: Akun telah ditambahkan atas nama Sdr. Andi dan sudah diberikan akses pada shift pagi dan siang.",
        metadata={"source": "Request"},
    ),
    Document(
        page_content="Request: Tambah user baru ke sistem absensi.\nJawaban: Permintaan ditolak karena tidak ada surat permohonan resmi dari manajer. Mohon untuk melengkapi dokumen pendukung.",
        metadata={"source": "Request"},
    ),
    Document(
        page_content="Incident: Komputer tidak bisa menyala.\nJawaban: PSU mengalami kerusakan. Kami ganti dengan unit cadangan dan komputer dapat dinyalakan kembali.",
        metadata={"source": "Incident"},
    ),
    Document(
        page_content="Incident: Komputer tidak bisa menyala.\nJawaban: Kabel power longgar. Setelah diperbaiki, perangkat langsung menyala normal.",
        metadata={"source": "Incident"},
    ),
    Document(
        page_content="Aduan: Projector tidak bisa digunakan di ruang rapat.\nJawaban: Remote projector rusak. Kami gunakan tombol manual di perangkat untuk menghidupkannya sementara remote pengganti disiapkan.",
        metadata={"source": "Aduan"},
    ),
    Document(
        page_content="Aduan: Projector tidak bisa digunakan di ruang rapat.\nJawaban: Port HDMI longgar. Setelah mengganti kabel HDMI dan port, projector berfungsi kembali.",
        metadata={"source": "Aduan"},
    ),
    Document(
        page_content="Request: Ganti password akun email dinas.\nJawaban: Password telah kami reset dan dikirimkan ke nomor WhatsApp terdaftar. Silakan ubah setelah login.",
        metadata={"source": "Request"},
    ),
    Document(
        page_content="Request: Ganti password akun email dinas.\nJawaban: Reset password gagal karena email belum diverifikasi. Kami telah kirim ulang email verifikasi untuk proses selanjutnya.",
        metadata={"source": "Request"},
    ),
    Document(
        page_content="Incident: Aplikasi HRIS tidak bisa diakses.\nJawaban: Server aplikasi overload. Kami telah scale up resource di cloud dan restart service.",
        metadata={"source": "Incident"},
    ),
    Document(
        page_content="Incident: Aplikasi HRIS tidak bisa diakses.\nJawaban: Sertifikat SSL expired. Sertifikat telah diperbarui dan sistem kembali online.",
        metadata={"source": "Incident"},
    ),
    Document(
        page_content="Request: Instalasi software Zoom untuk keperluan rapat daring.\nJawaban: Zoom telah diinstal dan shortcut disiapkan di desktop Anda. Kami juga sinkronkan dengan kalender Outlook.",
        metadata={"source": "Request"},
    ),
    Document(
        page_content="Request: Instalasi software Zoom untuk keperluan rapat daring.\nJawaban: Permintaan ditunda karena perangkat belum memenuhi spesifikasi minimal. Kami akan bantu upgrade RAM terlebih dahulu.",
        metadata={"source": "Request"},
    ),
    Document(
        page_content="Incident: Suara speaker di ruang auditorium tidak keluar.\nJawaban: Output audio salah pilih di panel mixer. Kami atur kembali dan suara normal.",
        metadata={"source": "Incident"},
    ),
    Document(
        page_content="Incident: Suara speaker di ruang auditorium tidak keluar.\nJawaban: Kabel XLR mengalami short. Kami ganti kabel dan suara kembali terdengar jernih.",
        metadata={"source": "Incident"},
    ),
    Document(
        page_content="Aduan: Tidak bisa mengakses aplikasi mobile learning.\nJawaban: Kami temukan aplikasi belum diperbarui. Setelah update via Play Store, aplikasi berjalan normal.",
        metadata={"source": "Aduan"},
    ),
    Document(
        page_content="Aduan: Tidak bisa mengakses aplikasi mobile learning.\nJawaban: Login Anda diblokir karena ada aktivitas mencurigakan. Akses sudah kami pulihkan setelah validasi identitas.",
        metadata={"source": "Aduan"},
    ),
    Document(
        page_content="Request: Tambahan storage di Google Drive institusi.\nJawaban: Kami ajukan ke Google Admin dan menambah kapasitas sebesar 50GB sesuai permintaan.",
        metadata={"source": "Request"},
    ),
    Document(
        page_content="Request: Tambahan storage di Google Drive institusi.\nJawaban: Kuota maksimal telah tercapai. Kami arahkan untuk menyimpan file besar di server lokal.",
        metadata={"source": "Request"},
    ),
]

documents += [
    document_1,
    document_2,
    document_3,
    document_4,
    document_5,
    document_6,
    document_7,
    document_8,
    document_9,
    document_10,
]

uuids = [str(uuid4()) for _ in range(len(documents))]
docs = documents


sparse_embeddings = FastEmbedSparse(model_name="Qdrant/bm25")
embeddings = FastEmbedEmbeddings(model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")

client = QdrantClient(path="tmp/langchain_qdrant")

# Create a collection with sparse vectors
client.create_collection(
    collection_name="my_documents",
    # vectors_config={"dense": VectorParams(size=3072, distance=Distance.COSINE)},
    vectors_config={"dense": VectorParams(size=384, distance=Distance.COSINE)},
    sparse_vectors_config={
        "sparse": SparseVectorParams(index=models.SparseIndexParams(on_disk=False))
    },
)

qdrant = QdrantVectorStore(
    client=client,
    collection_name="my_documents",
    embedding=embeddings,
    sparse_embedding=sparse_embeddings,
    # retrieval_mode=RetrievalMode.SPARSE,
    # retrieval_mode=RetrievalMode.HYBRID,
    retrieval_mode=RetrievalMode.DENSE,
    vector_name="dense",
    sparse_vector_name="sparse",
    
)

qdrant.add_documents(documents=documents, ids=uuids)

app = FastAPI()

@app.get("/get_data")
def get_data(query: str):
    # query = "How much money did the robbers steal?"
    # found_docs = [x.model_dump() for x in qdrant.similarity_search(query)]
    found_docs = [x[0].model_dump() for x in qdrant.similarity_search_with_score(query, k=10, score_threshold=0.25)]

    for doc in found_docs:
        doc.pop("id", None)
        # key = 
        for k in list(doc["metadata"].keys()):
            if k[0] == "_":
                doc["metadata"].pop(k)

    return {
        "data": found_docs
    }


@app.post("/add_data")
def add_data(data: Data):
    global qdrant
    if isinstance(data.items, dict):
        qdrant.add_documents(documents=[Document(**data.items)])
    else:
        qdrant.add_documents(documents=[Document(**x.items) for x in data])

    return {"message":"Create data successfully!", "status_code":201}



@app.get("/")
def greet_json():
    return {"Hello": "World!"}