08. SelfQueryRetriever

Self-querying

SelfQueryRetriever adalah alat pencarian dengan kemampuan untuk menghasilkan dan menyelesaikan pertanyaan dengan sendirinya. Alat ini mengambil pertanyaan bahasa alami yang diberikan oleh pengguna dan membuat pertanyaan terstruktur menggunakan rantai LLM yang membangun pertanyaan, lalu menerapkan pertanyaan terstruktur ini ke penyimpanan data vektor yang mendasarinya (VectorStore) untuk melakukan pencarian.

Proses ini memungkinkan SelfQueryRetriever untuk melakukan lebih dari sekadar membandingkan kueri input pengguna secara semantik dengan konten dokumen yang disimpan; SelfQueryRetriever dapat mengekstrak filter pada metadata dokumen dari kueri pengguna dan menjalankan filter ini untuk menemukan dokumen yang relevan. Hal ini memungkinkannya memberikan hasil yang lebih akurat dan relevan untuk kueri pengguna.

Catatan

Daftar pengambil kueri mandiri yang didukung oleh LangChain https://python.langchain.com/docs/integrations/retrievers/self_query

Memulai

Kita akan menggunakan penyimpanan vektor Chroma untuk demonstrasi kita. Untuk tutorial ini, kami telah membuat satu set kecil dokumen demo dengan ringkasan film.

Catatan: Anda perlu menginstal paket lark untuk menggunakan SelfQueryRetriever.

%pip install -qU lark chromadb

Buatlah penyimpanan vektor yang memungkinkan pencarian kemiripan berdasarkan deskripsi film dan metadata.

Gunakan kelas Document untuk membuat dokumen, daftar objek dokumen yang berisi deskripsi singkat tentang film dan metadatanya. Buat penyematan dokumen menggunakan OpenAIEmbeddings. Gunakan metode Chroma.from_documents untuk membuat penyimpanan vektor Chroma, vectorstore, dari docs dan OpenAIEmbeddings.

from langchain_community.vectorstores import Chroma
from langchain_core.documents import Document
from langchain_openai import OpenAIEmbeddings


docs = [
    Document(
        page_content="A bunch of scientists bring back dinosaurs and mayhem breaks loose",
        metadata={"year": 1993, "rating": 7.7, "genre": "science fiction"},
    ),
    Document(
        page_content="Leo DiCaprio gets lost in a dream within a dream within a dream within a ...",
        metadata={"year": 2010, "director": "Christopher Nolan", "rating": 8.2},
    ),
    Document(
        page_content="A psychologist / detective gets lost in a series of dreams within dreams within dreams and Inception reused the idea",
        metadata={"year": 2006, "director": "Satoshi Kon", "rating": 8.6},
    ),
    Document(
        page_content="A bunch of normal-sized women are supremely wholesome and some men pine after them",
        metadata={"year": 2019, "director": "Greta Gerwig", "rating": 8.3},
    ),
    Document(
        page_content="Toys come alive and have a blast doing so",
        metadata={"year": 1995, "genre": "animated"},
    ),
    Document(
        page_content="Three men walk into the Zone, three men walk out of the Zone",
        metadata={
            "year": 1979,
            "director": "Andrei Tarkovsky",
            "genre": "thriller",
            "rating": 9.9,
        },
    ),
]
vectorstore = Chroma.from_documents(docs, OpenAIEmbeddings())

Membuat SelfQueryRetriever

Sekarang Anda dapat menginstansiasi retriever. Untuk melakukannya, kita perlu menyediakan terlebih dahulu bidang metadata yang didukung oleh dokumen dan deskripsi singkat tentang konten dokumen.

Gunakan kelas AttributeInfo untuk mendefinisikan informasi tentang bidang metadata film

  • Genre (genre): Jenis string, menunjukkan genre film dan dapat mengambil ['fiksi ilmiah', 'komedi', 'drama', 'thriller', 'romansa', 'aksi', 'animasi'] dan memiliki salah satu nilai berikut

  • tahun (year): Tipe integer, menunjukkan tahun rilis film.

  • stradara (director): Tipe string, menunjukkan nama sutradara film.

  • rating (rating): Tipe bilangan real, menunjukkan peringkat film dalam rentang 1-10.

Tetapkan deskripsi ringkasan singkat tentang film ke variabel document_content_description.

Gunakan metode SelfQueryRetriever.from_llm() untuk membuat objek retriever.

  • llm: model bahasa

  • vectorstore: Penyimpanan vektor

  • document_content_description: Deskripsi konten dokumen

  • metadata_field_info: Informasi bidang metadata

Pengujian

Sekarang kita dapat mencoba retriever yang telah kita buat!

Panggil metode invoke objek retriever untuk melakukan pencarian yang difilter.

  • Kami mengoper “Saya ingin menonton film dengan rating lebih tinggi dari 8,5” sebagai permintaan pencarian kami, menentukan bahwa kami ingin mencari film dengan rating 8,5 atau lebih tinggi.

Dalam kueri ini, Anda dapat melihat bahwa kami telah menggunakan filter komposit untuk menentukan kriteria pencarian kami.

Filter komposit: peringkat di atas 8,5, fiksi ilmiah

Kueri ini juga menggunakan filter gabungan untuk menyaring hasil pencarian.

Filter gabungan: 1990 hingga 2005, pilih film tentang gedung pertunjukan, pilih film animasi

Catatan: Solusi untuk error ini ada di-akhir bagian ini

Memfilter berdasarkan faktor K

k adalah jumlah dokumen yang akan diambil.

Anda juga dapat menggunakan SelfQueryRetriever untuk menentukan k. Hal ini dapat dilakukan dengan mengoper enable_limit = True ke konstruktor.

Buat objek retriever menggunakan kelas SelfQueryRetriever.

  • document_content_description: Deskripsi konten dokumen

  • metadata_field_info: Informasi bidang metadata

  • enable_limit: Apakah akan membatasi hasil pencarian

(Metode 1) Dalam kasus berikut, search_kwargs = {“k”: 2} untuk secara eksplisit menentukan bahwa 2 hasil pencarian harus dikembalikan.

Namun, Anda dapat menggunakan angka seperti dua, tiga, dst. dalam kueri Anda untuk membatasi hasil pencarian tanpa secara eksplisit menentukan search_kwargs dalam kode Anda.

Mari kita modifikasi sedikit kueri untuk mengembalikan hanya satu.

Mengkonfigurasi chain menggunakan LCEL

Untuk melihat apa yang terjadi di balik layar dan memiliki lebih banyak kontrol khusus, kita dapat mengkonfigurasi ulang retriever dari awal.

Pertama, kita perlu membuat query-construction chain.

Chain ini akan mengambil kueri pengguna dan membuat objek StructuredQuery yang menangkap filter yang Anda tentukan.

Membuat pembuat kueri terstruktur (query_constructor)

Gunakan fungsi get_query_constructor_prompt untuk mendapatkan prompt konstruktor kueri.

  • Fungsi ini menerima document_content_description dan metadata_field_info sebagai argumen.

Gunakan metode StructuredQueryOutputParser.from_components() untuk menginisialisasi pemilah keluaran kueri terstruktur.

  • Buatlah query_constructor dengan menghubungkan prompt generator(prompt), model bahasa (LLM), dan output parser dalam sebuah pipeline.

  • Pipeline ini akan membuat query berdasarkan prompt, memprosesnya melalui model bahasa, dan kemudian mengubahnya menjadi format terstruktur menggunakan output parser.

Mari gunakan metode prompt.format() untuk mengoper string “pertanyaan tiruan” ke parameter kueri dan mencetak hasilnya untuk melihat apa yang dikatakan oleh prompt.

Tujuan Anda adalah menyusun kueri pengguna agar sesuai dengan skema permintaan yang disediakan di bawah ini.

<< Skema Permintaan Terstruktur >> Saat merespons, gunakan cuplikan kode penurunan harga dengan objek JSON yang diformat dalam skema berikut ini:

String query harus hanya berisi teks yang diharapkan sesuai dengan isi dokumen. Kondisi apa pun dalam filter tidak boleh disebutkan dalam kueri.

Pernyataan kondisi logis terdiri dari satu atau lebih pernyataan perbandingan dan operasi logis.

Sebuah pernyataan perbandingan mengambil bentuk: comp(attr, val):

  • comp (eq | ne | gt | gte | lt | lte | contain | like | in | nin): pembanding

  • attr (string): nama atribut yang akan digunakan sebagai pembanding

  • val (string): adalah nilai perbandingan

Pernyataan operasi logika berbentuk op(pernyataan1, pernyataan2, ...):

  • op (dan | atau | tidak): operator logika

  • pernyataan1, pernyataan2, ... (pernyataan perbandingan atau pernyataan operasi logika): satu atau lebih pernyataan untuk menerapkan operasi

Perlu dipastikan:

  • Pastikan Anda hanya menggunakan pembanding dan operator logika yang tercantum di atas dan tidak menggunakan yang lainnya.

  • Pastikan bahwa filter hanya mengacu pada atribut yang ada di sumber data.

  • Pastikan bahwa filter hanya menggunakan nama atribut dengan nama fungsinya jika ada fungsi yang diterapkan pada atribut tersebut.

  • Pastikan filter hanya menggunakan format YYYY-MM-DD ketika menangani nilai tipe data tanggal.

  • Pastikan bahwa filter memperhitungkan deskripsi atribut dan hanya membuat perbandingan yang layak berdasarkan jenis data yang disimpan.

  • Pastikan bahwa filter hanya digunakan sesuai kebutuhan. Jika tidak ada filter yang harus diterapkan, kembalikan “NO_FILTER” untuk nilai filter.

Contoh 1:

Data:

User query:

Structured Request:

Contoh 2:

Data:

User query:

Structured Request:

Contoh 3:

Data:

User query:

Structured question:

Panggil metode query_constructor.invoke() untuk melakukan pemrosesan untuk kueri yang diberikan.

Elemen kunci dari pengambil kueri mandiri adalah konstruktor kueri. Untuk membuat sistem pencarian yang hebat, Anda harus memastikan konstruktor kueri berfungsi dengan baik.

Hal ini memerlukan penyesuaian pada petunjuk, contoh di dalam petunjuk, deskripsi properti, dll.

[Catatan].

Untuk contoh yang menunjukkan proses penyempurnaan konstruktor kueri untuk data inventaris hotel, lihat https://github.com/langchain-ai/langchain/blob/master/cookbook/self_query_hotel_search.ipynb.

Mengubah structured query menggunakan Structured Query Translator

Elemen penting berikutnya adalah penerjemah kueri terstruktur, yang bertanggung jawab untuk mengonversi objek StructuredQuery umum menjadi filter metadata yang sesuai dengan sintaks penyimpanan vektor yang Anda gunakan.

Kami mengimplementasikan pencari yang menggunakan SelfQueryRetriever untuk menghasilkan jawaban atas pertanyaan.

  • Gunakan query_constructor untuk membuat pertanyaan.

  • Gunakan vectorstore untuk mengakses penyimpanan vektor.

  • Gunakan ChromaTranslator untuk menerjemahkan kueri terstruktur agar sesuai dengan penyimpanan vektor Chroma.

Hasilkan jawaban untuk pertanyaan yang diberikan menggunakan metode retriever.invoke().

Anda dapat menggunakan generator kueri terstruktur + konverter kueri ini untuk memfilter dan mengambil data tanpa kesalahan.

Last updated