Retrieval-Augmented Generation (RAG) dengan Milvus dan LlamaIndex

Open In Colab GitHub Repository

Panduan ini mendemonstrasikan cara membangun sistem Retrieval-Augmented Generation (RAG) dengan menggunakan LlamaIndex dan Milvus.

Sistem RAG menggabungkan sistem pencarian dengan model generatif untuk menghasilkan teks baru berdasarkan perintah yang diberikan. Sistem ini pertama-tama mengambil dokumen yang relevan dari sebuah korpus menggunakan Milvus, dan kemudian menggunakan model generatif untuk menghasilkan teks baru berdasarkan dokumen yang diambil.

LlamaIndex adalah kerangka kerja data yang sederhana dan fleksibel untuk menghubungkan sumber data khusus ke model bahasa besar (LLM). Milvus adalah basis data vektor sumber terbuka yang paling canggih di dunia, yang dibuat untuk mendukung pencarian kemiripan dan aplikasi AI.

Dalam buku catatan ini, kami akan menunjukkan demo singkat penggunaan MilvusVectorStore.

Sebelum Anda memulai

Menginstal ketergantungan

Potongan kode pada halaman ini membutuhkan dependensi pymilvus dan llamaindex. Anda dapat menginstalnya dengan menggunakan perintah berikut:

$ pip install pymilvus>=2.4.2 milvus-lite
$ pip install llama-index-vector-stores-milvus
$ pip install llama-index

Jika Anda menggunakan Google Colab, untuk mengaktifkan dependensi yang baru saja diinstal, Anda mungkin perlu memulai ulang runtime. (Klik menu "Runtime" di bagian atas layar, dan pilih "Restart session" dari menu tarik-turun).

Menyiapkan OpenAI

Pertama-tama, mari kita mulai dengan menambahkan kunci api openai. Ini akan memungkinkan kita untuk mengakses chatgpt.

import openai

openai.api_key = "sk-***********"

Menyiapkan data

Anda dapat mengunduh data sampel dengan perintah berikut:

! mkdir -p 'data/'
! wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/paul_graham/paul_graham_essay.txt' -O 'data/paul_graham_essay.txt'
! wget 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/docs/examples/data/10k/uber_2021.pdf' -O 'data/uber_2021.pdf'

Memulai

Menghasilkan data kita

Sebagai contoh pertama, mari kita buat sebuah dokumen dari file paul_graham_essay.txt. Dokumen tersebut adalah sebuah esai dari Paul Graham yang berjudul What I Worked On. Untuk menghasilkan dokumen, kita akan menggunakan SimpleDirectoryReader.

from llama_index.core import SimpleDirectoryReader

# load documents
documents = SimpleDirectoryReader(
    input_files=["./data/paul_graham_essay.txt"]
).load_data()

print("Document ID:", documents[0].doc_id)
Document ID: 95f25e4d-f270-4650-87ce-006d69d82033

Membuat indeks di seluruh data

Sekarang setelah kita memiliki sebuah dokumen, kita dapat membuat sebuah indeks dan menyisipkan dokumen tersebut. Untuk indeks kita akan menggunakan MilvusVectorStore. MilvusVectorStore membutuhkan beberapa argumen:

argumen dasar

  • uri (str, optional): URI yang akan disambungkan, berupa "https://address:port" untuk layanan Milvus atau Zilliz Cloud, atau "path/to/local/milvus.db" untuk Milvus lokal lite. Defaultnya adalah "./milvus_llamaindex.db".
  • token (str, optional): Token untuk masuk. Kosongkan jika tidak menggunakan rbac, jika menggunakan rbac kemungkinan besar akan menjadi "username:password".
  • collection_name (str, optional): Nama koleksi di mana data akan disimpan. Defaultnya adalah "llamalection".
  • overwrite (bool, optional): Apakah akan menimpa koleksi yang sudah ada dengan nama yang sama. Nilai defaultnya adalah "False".

bidang skalar termasuk id dokumen & teks

  • doc_id_field (str, optional): Nama bidang doc_id untuk koleksi. Defaultnya adalah DEFAULT_DOC_ID_KEY.
  • text_key (str, optional): Teks kunci apa yang disimpan dalam koleksi yang dilewatkan. Digunakan saat membawa koleksi Anda sendiri. Defaultnya adalah DEFAULT_TEXT_KEY.
  • scalar_field_names (list, optional): Nama-nama bidang skalar tambahan yang akan disertakan dalam skema koleksi.
  • scalar_field_types (list, optional): Jenis-jenis bidang skalar ekstra.

bidang padat

  • enable_dense (bool): Bendera boolean untuk mengaktifkan atau menonaktifkan penyematan padat. Nilai defaultnya adalah True (Benar).
  • dim (int, optional): Dimensi vektor penyematan untuk koleksi. Diperlukan saat membuat koleksi baru dengan enable_sparse bernilai False.
  • embedding_field (str, optional): Nama bidang penyematan padat untuk koleksi, defaultnya adalah DEFAULT_EMBEDDING_KEY.
  • index_config (dict, optional): Konfigurasi yang digunakan untuk membangun indeks sematan padat. Defaultnya adalah None.
  • search_config (dict, optional): Konfigurasi yang digunakan untuk mencari indeks padat Milvus. Perhatikan bahwa ini harus kompatibel dengan jenis indeks yang ditentukan oleh index_config. Setelan default untuk Tidak Ada.
  • similarity_metric (str, optional): Metrik kemiripan yang digunakan untuk penyematan padat, saat ini mendukung IP, COSINE, dan L2.

sparse field

  • enable_sparse (bool): Bendera boolean untuk mengaktifkan atau menonaktifkan penyematan jarang. Defaultnya adalah False.
  • sparse_embedding_field (str): Nama bidang penyematan jarang, defaultnya adalah DEFAULT_SPARSE_EMBEDDING_KEY.
  • sparse_embedding_function (Union[BaseSparseEmbeddingFunction, BaseMilvusBuiltInFunction], optional): Jika enable_sparse bernilai True, objek ini harus disediakan untuk mengonversi teks ke sematan jarang. Jika Tidak Ada, fungsi penyematan jarang default (BGEM3SparseEmbeddingFunction) akan digunakan.
  • sparse_index_config (dict, optional): Konfigurasi yang digunakan untuk membangun indeks sematan jarang. Defaultnya adalah Tidak Ada.

pemeringkat hibrida

  • hybrid_ranker (str): Menentukan jenis pemeringkat yang digunakan dalam kueri penelusuran hibrida. Saat ini hanya mendukung ["RRFRanker", "WeightedRanker"]. Nilai default untuk "RRFRanker".

  • hybrid_ranker_params (dict, optional): Parameter konfigurasi untuk pemeringkat hibrida. Struktur kamus ini tergantung pada pemeringkat spesifik yang digunakan:

    • Untuk "RRFRanker", harus menyertakan:
      • "k" (int): Parameter yang digunakan dalam Reciprocal Rank Fusion (RRF). Nilai ini digunakan untuk menghitung skor peringkat sebagai bagian dari algoritme RRF, yang menggabungkan beberapa strategi peringkat menjadi satu skor untuk meningkatkan relevansi penelusuran.
    • Untuk "WeightedRanker", ini mengharapkan:
      • "bobot" (daftar float): Daftar yang terdiri dari dua bobot:
        1. Bobot untuk komponen sematan padat.
        2. Bobot untuk komponen sematan jarang. Bobot ini digunakan untuk menyesuaikan pentingnya komponen sematan padat dan jarang dalam proses pengambilan hibrida. Default ke kamus kosong, menyiratkan bahwa pemeringkat akan beroperasi dengan pengaturan default yang telah ditetapkan sebelumnya.

lainnya

  • collection_properties (dict, optional): Properti koleksi seperti TTL (Time-To-Live) dan MMAP (pemetaan memori). Defaultnya adalah Tidak Ada. Ini bisa termasuk:
    • "collection.ttl.seconds" (int): Setelah properti ini ditetapkan, data dalam koleksi saat ini akan kedaluwarsa dalam waktu yang ditentukan. Data yang kedaluwarsa dalam koleksi akan dibersihkan dan tidak akan dilibatkan dalam pencarian atau kueri.
    • "mmap.enabled" (bool): Apakah akan mengaktifkan penyimpanan yang dipetakan memori di tingkat koleksi.
  • index_management (IndexManagement): Menentukan strategi manajemen indeks yang akan digunakan. Nilai defaultnya adalah "buat_jika_tidak_ada".
  • batch_size (int): Mengonfigurasi jumlah dokumen yang diproses dalam satu batch saat memasukkan data ke dalam Milvus. Nilai defaultnya adalah DEFAULT_BATCH_SIZE.
  • consistency_level (str, optional): Tingkat konsistensi yang digunakan untuk koleksi yang baru dibuat. Defaultnya adalah "Session".
# Create an index over the documents
from llama_index.core import VectorStoreIndex, StorageContext
from llama_index.vector_stores.milvus import MilvusVectorStore


vector_store = MilvusVectorStore(uri="./milvus_demo.db", dim=1536, overwrite=True)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)

Untuk parameter MilvusVectorStore:

  • Mengatur uri sebagai file lokal, misalnya./milvus.db, adalah metode yang paling mudah, karena secara otomatis menggunakan Milvus Lite untuk menyimpan semua data dalam file ini.
  • Jika Anda memiliki data dalam skala besar, Anda dapat mengatur server Milvus yang lebih berkinerja pada docker atau kubernetes. Dalam pengaturan ini, silakan gunakan uri server, misalnyahttp://localhost:19530, sebagai uri.
  • Jika Anda ingin menggunakan Zilliz Cloud, layanan cloud yang dikelola sepenuhnya untuk Milvus, sesuaikan uri dan token, yang sesuai dengan kunci Public Endpoint dan Api di Zilliz Cloud.

Menanyakan data

Setelah dokumen kita tersimpan dalam indeks, kita dapat mengajukan pertanyaan terhadap indeks. Indeks akan menggunakan data yang tersimpan di dalamnya sebagai basis pengetahuan untuk chatgpt.

query_engine = index.as_query_engine()
res = query_engine.query("What did the author learn?")
print(res)
The author learned that philosophy courses in college were boring to him, leading him to switch his focus to studying AI.
res = query_engine.query("What challenges did the disease pose for the author?")
print(res)
The disease posed challenges for the author as it affected his mother's health, leading to a stroke caused by colon cancer. This resulted in her losing her balance and needing to be placed in a nursing home. The author and his sister were determined to help their mother get out of the nursing home and back to her house.

Pengujian berikutnya menunjukkan bahwa penimpaan akan menghapus data sebelumnya.

from llama_index.core import Document


vector_store = MilvusVectorStore(uri="./milvus_demo.db", dim=1536, overwrite=True)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(
    [Document(text="The number that is being searched for is ten.")],
    storage_context,
)
query_engine = index.as_query_engine()
res = query_engine.query("Who is the author?")
print(res)
The author is the individual who created the context information.

Pengujian berikutnya menunjukkan penambahan data tambahan ke indeks yang sudah ada.

del index, vector_store, storage_context, query_engine

vector_store = MilvusVectorStore(uri="./milvus_demo.db", overwrite=False)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
query_engine = index.as_query_engine()
res = query_engine.query("What is the number?")
print(res)
The number is ten.
res = query_engine.query("Who is the author?")
print(res)
Paul Graham

Penyaringan metadata

Kita dapat menghasilkan hasil dengan menyaring sumber-sumber tertentu. Contoh berikut mengilustrasikan pemuatan semua dokumen dari direktori dan kemudian menyaringnya berdasarkan metadata.

from llama_index.core.vector_stores import ExactMatchFilter, MetadataFilters

# Load all the two documents loaded before
documents_all = SimpleDirectoryReader("./data/").load_data()

vector_store = MilvusVectorStore(uri="./milvus_demo.db", dim=1536, overwrite=True)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents_all, storage_context)

Kita hanya ingin mengambil dokumen dari file uber_2021.pdf.

filters = MetadataFilters(
    filters=[ExactMatchFilter(key="file_name", value="uber_2021.pdf")]
)
query_engine = index.as_query_engine(filters=filters)
res = query_engine.query("What challenges did the disease pose for the author?")

print(res)
The disease posed challenges related to the adverse impact on the business and operations, including reduced demand for Mobility offerings globally, affecting travel behavior and demand. Additionally, the pandemic led to driver supply constraints, impacted by concerns regarding COVID-19, with uncertainties about when supply levels would return to normal. The rise of the Omicron variant further affected travel, resulting in advisories and restrictions that could adversely impact both driver supply and consumer demand for Mobility offerings.

Kita mendapatkan hasil yang berbeda ketika mengambil dari file paul_graham_essay.txt.

filters = MetadataFilters(
    filters=[ExactMatchFilter(key="file_name", value="paul_graham_essay.txt")]
)
query_engine = index.as_query_engine(filters=filters)
res = query_engine.query("What challenges did the disease pose for the author?")

print(res)
The disease posed challenges for the author as it affected his mother's health, leading to a stroke caused by colon cancer. This resulted in his mother losing her balance and needing to be placed in a nursing home. The author and his sister were determined to help their mother get out of the nursing home and back to her house.