07. Pencari Beberapa VectorStore (MultiVectorRetriever)

MultiVectorRetriever

LangChain menyediakan fitur khusus, MultiVectorRetriever, yang memungkinkan Anda untuk melakukan kueri dokumen secara efisien dalam berbagai situasi. Fitur ini memungkinkan Anda untuk menyimpan dan mengelola dokumen sebagai beberapa vektor, yang dapat sangat meningkatkan akurasi dan efisiensi pencarian informasi. Hari ini kita akan melihat beberapa cara untuk memanfaatkan MultiVectorRetriever ini untuk membuat beberapa vektor per dokumen.

Metode untuk menghasilkan beberapa vektor per dokumen:

  1. Membuat potongan yang lebih kecil: Pisahkan dokumen Anda menjadi unit yang lebih kecil dan buat penyematan terpisah untuk setiap potongan. Pendekatan ini memungkinkan Anda untuk memberikan perhatian lebih pada bagian tertentu dari dokumen. Proses ini dapat diimplementasikan melalui ParentDocumentRetriever, yang membuatnya lebih mudah untuk menavigasi ke detail.

  2. Penyematan ringkasan: Buat ringkasan setiap dokumen, dan buat penyematan dari ringkasan ini. Penyematan ringkasan ini adalah cara yang bagus untuk mendapatkan inti dari dokumen dengan cepat. Daripada menganalisis seluruh dokumen, Anda dapat memanfaatkan poin-poin penting untuk efisiensi maksimum.

  3. Memanfaatkan pertanyaan hipotetis: Buat pertanyaan hipotetis yang sesuai untuk setiap artikel dan buat sematan berdasarkan pertanyaan tersebut. Hal ini berguna saat Anda ingin menjelajahi topik atau konten tertentu secara mendalam. Pertanyaan hipotetis memungkinkan Anda untuk mendekati konten artikel dari perspektif yang berbeda dan memberikan pemahaman yang lebih luas.

  4. Ditambahkan secara manual: Pengguna dapat menambahkan secara manual pertanyaan atau kueri spesifik yang ingin mereka pertimbangkan saat mencari dokumen. Metode ini memberi pengguna kontrol lebih besar atas proses pencarian dan memungkinkan mereka untuk menyesuaikan pencarian dengan kebutuhan mereka sendiri.

Dengan memiliki fleksibilitas untuk memanfaatkan pendekatan yang berbeda ini dengan MultiVectorRetriever, pengguna dapat menemukan informasi yang mereka butuhkan dengan lebih akurat dan cepat. Fitur LangChain ini merupakan alat yang hebat untuk membuat tugas pencarian informasi menjadi lebih efektif.

Cara kerja

Memuat data dari file teks dan melakukan prapemrosesan untuk membagi dokumen yang dimuat ke dalam ukuran tertentu.

Dokumen yang tersegmentasi nantinya dapat digunakan untuk operasi seperti vektorisasi dan pencarian.

loaders = [
    # Memuat data pertama.
    TextLoader("./data/ai-story.txt"),
    # Memuat data kedua.
    TextLoader("./data/appendix-keywords.txt"),
]
docs = []  # Menginisialisasi daftar dokumen kosong.
for loader in loaders:
    docs.extend(loader.load())  # Memuat dokumen dari setiap loader dan menambahkannya ke dalam daftar docs.

Dokumen asli yang dimuat dari data disimpan dalam variabel docs.

Membuat potongan-potongan kecil

Ketika mencari informasi dalam jumlah besar, akan sangat berguna untuk menyematkan informasi dalam potongan-potongan yang lebih kecil.

Hal ini memungkinkan penyematan untuk menangkap makna semantik sedekat mungkin, sambil meneruskan konteks sebanyak mungkin ke hilir.

Inilah yang dilakukan oleh ParentDocumentRetriever

di mana kita mendefinisikan parent_text_splitter untuk membagi menjadi potongan-potongan yang lebih besar

child_text_splitter untuk membagi menjadi potongan-potongan yang lebih kecil.

  • Pisahkan dokumen menjadi beberapa bagian menggunakan parent_text_splitter.

  • Dalam metadata untuk setiap dokumen, masukkan uuid yang Anda buat dengan “doc_id” sebagai kuncinya.

  • Pada akhirnya, daftar parent_docs akan berisi dokumen asli yang dipecah menjadi beberapa bagian yang lebih besar, dengan setiap dokumen berisi ID dokumen asli sebagai metadata.

  • Gunakan child_text_splitter untuk membagi dokumen menjadi bagian yang lebih kecil.

  • Pada metadata untuk setiap dokumen, masukkan uuid yang Anda buat dengan “doc_id” sebagai kuncinya. Ini untuk memberikan ID pada bagian yang lebih kecil sebagai ID dokumen.

  • Pada akhirnya, daftar child_docs akan berisi dokumen asli yang dipecah menjadi potongan-potongan yang lebih kecil, masing-masing dengan ID dokumen asli sebagai metadata.

Periksa jumlah potongan yang dibagi ke dalam masing-masing bagian.

Tambahkan kumpulan subdokumen yang lebih kecil yang baru dibuat ke penyimpanan vektor.

Selanjutnya, kita tambahkan dokumen induk ke docstore dengan memetakannya ke UUID yang telah dibuat.

  • Gunakan metode mset() untuk menyimpan ID dokumen dan konten dokumen sebagai pasangan kunci-nilai di dalam penyimpanan dokumen.

(Contoh) list(zip(doc_ids, docs))[0]

Melakukan pencarian kemiripan untuk kata kunci yang diberikan. Mengeluarkan fragmen dokumen pertama dengan kemiripan tertinggi.

Anda dapat menambahkan ambang batas skor untuk melakukan pencarian kemiripan seperti ini

Hasil pencarian kemiripan hanya akan mengembalikan hasil dengan nilai kemiripan 0,5 atau lebih tinggi.

Anda juga dapat menentukan faktor k, di mana k adalah jumlah dokumen yang dicari.

Mengambil dokumen yang relevan dengan memanggil metode get_relevant_documents dari objek retriever.

Mengambil dokumen yang relevan dengan kueri yang diberikan.

Dalam kasus ini, kedua dokumen muncul sebagai hasil pencarian karena mengandung definisi “Word2Vec”.

Jika Anda memeriksa panjang string isi dokumen pertama yang ditemukan, Anda akan melihat bahwa seluruh dokumen adalah output.

Jenis pencarian yang dilakukan retriever secara default pada basis data vektor adalah pencarian kemiripan.

LangChain Vector Store juga mendukung pencarian melalui Max Marginal Relevance, jadi jika Anda ingin menggunakannya, Anda dapat mengatur properti search_type sebagai berikut

  • Tetapkan properti search_type pada objek retriever ke SearchType.mmr.

  • Ini menetapkan bahwa pencarian harus menggunakan algoritma Maximal Marginal Relevance (MMR).

Menyimpan ringkasan ke penyimpanan vektor

Ringkasan sering kali dapat memberikan ekstraksi yang lebih akurat dari konten sebuah potongan, yang dapat menghasilkan hasil pencarian yang lebih baik.

Bagian ini menjelaskan cara membuat ringkasan dan cara menyematkannya.

  • Gunakan metode chain.batch untuk memproses docs dalam daftar dokumen secara bersamaan.

  • Di sini, kami menetapkan parameter max_concurrency ke 5 untuk mengizinkan hingga lima dokumen diproses secara bersamaan.

Cetak ringkasan untuk melihat hasilnya.

Inisialisasi penyimpanan vektor Chroma untuk mengindeks potongan anak. Kami menggunakan OpenAIEmbeddings sebagai fungsi penyematan.

  • Gunakan “doc_id” sebagai kunci yang mewakili ID dokumen.

Simpan dokumen yang diringkas dan metadata (dalam hal ini, Document ID untuk ringkasan yang Anda buat).

Jumlah dokumen dalam intisari sesuai dengan jumlah dokumen asli.

  • Tambahkan summary_docs ke penyimpanan vektor dengan retriever.vectorstore.add_documents(summary_documents).

  • Memetakan doc_ids dan docs dengan retriever.docstore.mset(list(zip(doc_ids, docs))) untuk menyimpannya di penyimpanan dokumen.

Berikutnya adalah kode untuk menambahkan data potongan asli ke penyimpanan vektor.

Mengeluarkan jumlah dokumen yang dipisah.

Terakhir, tambahkan dokumen yang telah dipisah ke tempat penyimpanan vektor.

Lakukan pencarian kemiripan dengan menggunakan metode similarity_search pada objek vectorstore.

Gunakan metode get_relevant_documents pada objek retriever untuk mengambil dokumen yang terkait dengan pertanyaan.

Pertanyaan Hipotesis

LLM juga dapat digunakan untuk menghasilkan daftar pertanyaan yang dapat dijadikan hipotesis tentang dokumen tertentu.

Pertanyaan-pertanyaan yang dihasilkan ini kemudian dapat disematkan untuk mengeksplorasi dan memahami lebih lanjut isi dokumen.

Menghasilkan pertanyaan hipotetis membantu mengidentifikasi topik dan konsep utama dalam dokumentasi Anda, dan dapat mendorong pembaca untuk mengajukan lebih banyak pertanyaan tentang konten dokumentasi Anda.

  • functions adalah sebuah list berisi satu elemen dictionary.

  • dictionary ini memiliki kunci name, descriptions, dan parameters.

  • name adalah sebuah string yang merepresentasikan nama fungsi.

  • descriptions adalah string yang merepresentasikan deskripsi fungsi.

  • parameters adalah kamus yang mendefinisikan parameter fungsi.

  • type menunjukkan jenis parameter, yang diatur ke “objek” di sini.

  • properties adalah kamus yang mendefinisikan properti dari objek.

    • questions adalah properti bertipe “array”, di mana setiap elemennya bertipe “string”.

  • required adalah daftar properti yang diperlukan, di mana pertanyaan ditentukan sesuai kebutuhan.

Gunakan ChatPromptTemplate untuk mendefinisikan template prompt yang menghasilkan tiga pertanyaan virtual berdasarkan dokumen yang diberikan.

  • Inisialisasi model GPT menggunakan ChatOpenAI, dan panggil fungsi menghasilkan pertanyaan virtual dengan mengatur functions dan function_call.

  • Gunakan JsonKeyOutputFunctionsParser untuk mem-parsing pertanyaan virtual yang dihasilkan dan mengekstrak nilai yang sesuai dengan kunci questions.

panggil chain.invoke(docs[0]) untuk mengeluarkan jawaban untuk dokumen pertama.

  • Keluarannya berisi tiga Pertanyaan Hipotetis yang telah kita buat.

Gunakan metode chain.batch untuk memproses beberapa permintaan data docs secara bersamaan.

  • Parameter docs mewakili data dokumen yang akan diproses.

  • Parameter max_concurrency menentukan jumlah maksimum permintaan yang dapat diproses secara bersamaan. Dalam contoh ini, parameter tersebut diatur ke 5.

  • Metode ini melakukan operasi pada objek chain untuk setiap item dalam data docs, dan memproses hingga lima permintaan secara bersamaan.

  • Hasil pemrosesan disimpan dalam variabel hypothetical_questions.

Di bawah ini adalah proses penyimpanan Kueri Hipotetis yang Anda buat di VectorStore dengan cara yang sama seperti sebelumnya.

Menambahkan metadata (ID dokumen) ke daftar question_docs.

Tambahkan kueri hipotesis ke dokumen, dan tambahkan dokumen asli ke docstore.

Lakukan pencarian kemiripan dengan menggunakan metode similarity_search pada objek vectorstore.

Di bawah ini adalah hasil dari pencarian kemiripan.

Di sini, kita hanya menambahkan kueri hipotesis yang kita buat, sehingga mengembalikan dokumen dengan kemiripan tertinggi di antara kueri hipotesis yang kita buat.

Tambahkan dokumen yang Anda pisahkan pada langkah sebelumnya ke penyimpanan vektor juga.

Gunakan metode get_relevant_documents pada objek retriever untuk mengambil dokumen yang relevan dengan kueri.

Periksa panjang hasil pencarian, retrieved_docs[0].page_content.

Last updated