1. Pencari

Pencari adalah sebuah antarmuka yang dienkapsulasi oleh LangChain, yang dapat mengembalikan dokumen-dokumen relevan berdasarkan kueri-kueri yang tidak terstruktur. Tujuan dari desain pencari adalah untuk memudahkan pengaksesan data lokal. Penyimpanan vektor dapat digunakan sebagai implementasi dasar dari pencari, dan LangChain mendukung beberapa implementasi dasar dari antarmuka pencari.

2. Memulai dengan Pencari

2.1. Instalasi

Untuk menunjukkan bagaimana cara mendapatkan pencari, kita akan menggunakan basis data vektor Qdrant sebagai contoh.

%pip install --upgrade --quiet qdrant-client

2.2. Mendapatkan Kunci API OpenAI

Sebelum menggunakan OpenAIEmbeddings, kita perlu mendapatkan kunci API OpenAI.

import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass("Kunci API OpenAI:")

2.3. Mengimpor Data Dokumen dan Mendapatkan Klien Qdrant

Kode berikut menunjukkan bagaimana cara mengimpor data dokumen dan mendapatkan klien Qdrant untuk membuat pencari:

from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import Qdrant
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitter

loader = TextLoader("../../modules/state_of_the_union.txt")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)

embeddings = OpenAIEmbeddings()

qdrant = Qdrant.from_documents(
    docs,
    embeddings,
    path="/tmp/local_qdrant",
    collection_name="my_documents",
)

2.4. Mendapatkan Pencari

Kode berikut menunjukkan bagaimana cara mendapatkan pencari dari Qdrant:

retriever = qdrant.as_retriever()
retriever

Anda dapat menanyakan dokumen-dokumen yang terkait dengan sebuah pertanyaan seperti ini:

docs = retriever.get_relevant_documents("apa yang dikatakan tentang ketanji brown jackson")

Anda juga dapat mengatur ambang kesamaan untuk pencari seperti ini:

retriever = db.as_retriever(
    search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.5}
)

Selain itu, Anda dapat mengatur pencari untuk mengembalikan 'K' rekaman yang paling mirip, misalnya, untuk mengembalikan 2 rekaman yang paling mirip:

retriever = db.as_retriever(search_kwargs={"k": 2})

2.5. Menggunakan Pencari dalam LCEL

Karena pencari adalah objek Runnable, kita dapat dengan mudah menggabungkannya dengan objek Runnable lain untuk mengatur alur kerja:

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

template = """Jawab pertanyaan berdasarkan konteks berikut:

{context}

Pertanyaan: {question}
"""
prompt = ChatPromptTemplate.from_template(template)
model = ChatOpenAI()

def format_docs(docs):
    return "\n\n".join([d.page_content for d in docs])

chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()}
    | prompt
    | model
    | StrOutputParser()
)

chain.invoke("Apa yang dikatakan presiden tentang teknologi?")

Penjelasan dari proses ini:

  • Langkah 1: Tujuannya adalah untuk menghasilkan sebuah kamus yang berisi dua properti, context dan question, untuk menyiapkan parameter untuk template prompt. Parameter context dihasilkan oleh pencari berdasarkan parameter yang dilewatkan ke metode invoke, yaitu "Apa yang dikatakan presiden tentang teknologi?". Hal ini mengambil dokumen-dokumen yang mirip dengan pertanyaan, kemudian memformat array dokumen menggunakan fungsi format_docs dan menetapkannya ke properti context. Fungsi RunnablePassthrough menyalin parameter (pertanyaan pengguna) rantai ke properti question.
  • Langkah 2: Meneruskan kamus yang dihasilkan pada langkah pertama ke template prompt untuk diformat.
  • Langkah 3: Meneruskan prompt yang diformat dari template prompt ke model.
  • Langkah 4: Meneruskan hasil dari panggilan model ke parser output StrOutputParser.

3. Pencari Kustom

4.1. Pengantar ke Antarmuka Pencari

Antarmuka pencari sangat sederhana, dan kita dapat dengan mudah menulis pencari kustom.

4.2. Contoh Pencari Kustom

Berikut adalah contoh pencari kustom, yang menunjukkan bagaimana menulis pencari kustom dan menggunakannya untuk mendapatkan dokumen yang relevan:

from langchain_core.retrievers import BaseRetriever
from langchain_core.callbacks import CallbackManagerForRetrieverRun
from langchain_core.documents import Document
from typing import List

class CustomRetriever(BaseRetriever):
  
    def _get_relevant_documents(
        self, query: str, *, run_manager: CallbackManagerForRetrieverRun
    ) -> List[Document]:
        return [Document(page_content=query]

retriever = CustomRetriever()

retriever.get_relevant_documents("bar")

Dengan mempelajari bagian di atas, Anda akan mendapatkan pemahaman yang lebih mendalam tentang konsep, metode pencarian, dan penyesuaian pencari.