1. Retriever
Un retriever est une interface encapsulée par LangChain, qui peut retourner des documents pertinents en fonction de requêtes non structurées. Le but de la conception du retriever est de faciliter la consultation des données locales. Le stockage vectoriel peut être utilisé comme implémentation sous-jacente du retriever, et LangChain prend en charge plusieurs implémentations sous-jacentes de l'interface retriever.
2. Démarrage avec le Retriever
2.1. Installation
Pour démontrer comment obtenir un retriever, nous utiliserons la base de données vectorielle Qdrant comme exemple.
%pip install --upgrade --quiet qdrant-client
2.2. Obtention de la clé d'API OpenAI
Avant d'utiliser OpenAIEmbeddings
, nous devons obtenir la clé d'API OpenAI.
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass("Clé d'API OpenAI :")
2.3. Importation des données de document et obtention du client Qdrant
Le code suivant démontre comment importer les données de document et obtenir le client Qdrant pour créer un retriever :
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. Obtention du Retriever
Le code suivant démontre comment obtenir un retriever à partir de Qdrant :
retriever = qdrant.as_retriever()
retriever
Vous pouvez interroger des documents liés à une question de cette manière :
docs = retriever.get_relevant_documents("qu'a-t-il dit à propos de ketanji brown jackson")
Vous pouvez également définir le seuil de similarité pour le retriever de cette manière :
retriever = db.as_retriever(
search_type="similarity_score_threshold", search_kwargs={"score_threshold": 0.5}
)
De plus, vous pouvez configurer le retriever pour renvoyer les 'K' enregistrements les plus similaires, par exemple, pour renvoyer les 2 enregistrements les plus similaires:
retriever = db.as_retriever(search_kwargs={"k": 2})
2.5. Utilisation du Retriever dans LCEL
Puisque les retrievers sont des objets Runnable
, nous pouvons facilement les combiner avec d'autres objets Runnable
pour orchestrer des flux de travail :
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 = """Répondez aux questions uniquement sur la base du contexte suivant :
{context}
Question : {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("Qu'a dit le président à propos de la technologie ?")
Explication du processus :
- Étape 1 : Le but est de générer un dictionnaire contenant deux propriétés,
contexte
etquestion
, pour préparer les paramètres du modèle de prompt. Le paramètrecontexte
est généré par le retriever en fonction du paramètre passé à la méthodeinvoke
, qui est "Qu'a dit le président à propos de la technologie ?". Cela permet de récupérer des documents similaires à la question, puis de formater le tableau de documents à l'aide de la fonctionformat_docs
et de l'assigner à la propriétécontexte
. La fonctionRunnablePassthrough
copie le paramètre (question de l'utilisateur) de la chaîne dans la propriétéquestion
. - Étape 2 : Passer le dictionnaire généré dans la première étape au modèle de prompt pour le formater.
- Étape 3 : Passer le prompt formaté du modèle au modèle.
- Étape 4 : Passer le résultat de l'appel du modèle au parseur de sortie
StrOutputParser
.
3. Retriever Personnalisé
4.1. Introduction à l'Interface du Retriever
L'interface du retriever est très simple, et nous pouvons facilement écrire des retrieveurs personnalisés.
4.2. Exemple de récupérateur personnalisé
Voici un exemple de récupérateur personnalisé, démontrant comment écrire un récupérateur personnalisé et l'utiliser pour récupérer des documents pertinents :
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")
À travers l'étude des sections ci-dessus, vous gagnerez une compréhension approfondie du concept, des méthodes de récupération et de la personnalisation des récupérateurs.