1. Retriever
Retriever to interfejs zkapitalizowany przez LangChain, który może zwrócić odpowiednie dokumenty na podstawie nieustrukturyzowanych zapytań. Celem projektu retrievera jest ułatwienie zapytania do lokalnych danych. Przechowywanie wektorowe może być użyte jako zaimplementowanie retrievera, a LangChain obsługuje wielokrotne zaimplementowania interfejsu retrievera.
2. Rozpoczęcie pracy z Retriever
2.1. Instalacja
Aby zademonstrować, jak uzyskać retriever, użyjemy bazy danych wektorów Qdrant jako przykładu.
%pip install --upgrade --quiet qdrant-client
2.2. Uzyskanie klucza OpenAI API
Przed użyciem OpenAIEmbeddings
, musimy uzyskać klucz OpenAI API.
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass("Klucz OpenAI API:")
2.3. Importowanie danych dokumentów i uzyskiwanie klienta Qdrant
Poniższy kod demonstruje, jak zaimportować dane dokumentów i uzyskać klienta Qdrant do utworzenia retrievera:
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. Uzyskanie Retrievera
Poniższy kod demonstruje, jak uzyskać retrievera z Qdrant:
retriever = qdrant.as_retriever()
retriever
Możesz zapytać dokumenty związane z pytaniem w ten sposób:
docs = retriever.get_relevant_documents("co powiedział o Ketanji Brown Jackson")
Możesz także ustawić próg podobieństwa dla retrievera w ten sposób:
retriever = db.as_retriever(
search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.5}
)
Dodatkowo, możesz ustawić retriever, aby zwrócił najlepsze 'K' najbardziej podobne rekordy, na przykład, aby zwrócić najlepsze 2 najbardziej podobne rekordy:
retriever = db.as_retriever(search_kwargs={"k": 2})
2.5. Używanie Retrievera w LCEL
Ponieważ retrievery są obiektami „Runnable”, możemy łatwo połączyć je z innymi obiektami „Runnable” w celu skomponowania workflowów:
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 = """Odpowiadać na pytania na podstawie następującego kontekstu:
{context}
Pytanie: {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("Co prezydent powiedział o technologii?")
Wyjaśnienie procesu:
- Krok 1: Celem jest wygenerowanie słownika zawierającego dwie właściwości,
context
iquestion
, do przygotowania parametrów dla szablonu promptu. Parametrcontext
jest generowany przez retrievera na podstawie parametru przekazanego do metodyinvoke
, czyli "Co prezydent powiedział o technologii?". To odnajduje dokumenty podobne do pytania, a następnie formatuje tablicę dokumentów za pomocą funkcjiformat_docs
i przypisuje ją do właściwościcontext
. FunkcjaRunnablePassthrough
kopiująca parametr (pytanie użytkownika) łańcucha do właściwościquestion
. - Krok 2: Przekaż wygenerowany w pierwszym kroku słownik do szablonu promptu w celu sformatowania.
- Krok 3: Przekaż sformatowany prompt z szablonu do modelu.
- Krok 4: Przekaż wynik wywołania modelu do analizatora wyników
StrOutputParser
.
3. Niestandardowy Retriever
4.1. Wprowadzenie do Interfejsu Retrievera
Interfejs retrievera jest bardzo prosty i możemy łatwo pisać niestandardowe retrievery.
4.2. Przykład niestandardowego Wyszukiwacza
Oto przykład niestandardowego wyszukiwacza, który demonstruje, jak napisać niestandardowego wyszukiwacza i jak go użyć do wyszukiwania odpowiednich dokumentów:
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")
Poprzez przeanalizowanie powyższych sekcji zdobędziesz głębsze zrozumienie koncepcji, metod wyszukiwania oraz dostosowywania wyszukiwaczy.