1. Recuperadores
Retriever es una interfaz encapsulada por LangChain, que puede devolver documentos relevantes basados en consultas no estructuradas. El propósito del diseño del recuperador es facilitar la consulta de datos locales. El almacenamiento vectorial puede ser utilizado como la implementación subyacente del recuperador, y LangChain soporta múltiples implementaciones subyacentes de la interfaz del recuperador.
2. Comenzando con el Recuperador
2.1. Instalación
Para demostrar cómo obtener un recuperador, utilizaremos la base de datos de vectores Qdrant como ejemplo.
%pip install --upgrade --quiet qdrant-client
2.2. Obteniendo la Clave de API de OpenAI
Antes de utilizar OpenAIEmbeddings
, necesitamos obtener la clave de API de OpenAI.
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass("Clave de API de OpenAI:")
2.3. Importar Datos del Documento y Obtener el Cliente de Qdrant
El siguiente código demuestra cómo importar datos del documento y obtener el cliente de Qdrant para crear un recuperador:
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="mis_documentos",
)
2.4. Obtención del Recuperador
El siguiente código demuestra cómo obtener un recuperador de Qdrant:
recuperador = qdrant.como_recuperador()
recuperador
Puedes consultar documentos relacionados con una pregunta de esta manera:
docs = recuperador.obtener_documentos_relevantes("¿Qué dijo sobre Ketanji Brown Jackson?")
También puedes establecer el umbral de similitud para el recuperador de esta manera:
recuperador = db.como_recuperador(
tipo_de_busqueda="umbral_de_puntuacion_de_similitud", argumentos_de_busqueda={"umbral_de_puntuacion": 0.5}
)
Además, puedes configurar el recuperador para que devuelva los 'K' registros más similares, por ejemplo, para devolver los 2 registros más similares:
recuperador = db.como_recuperador(argumentos_de_busqueda={"k": 2})
2.5. Uso del Recuperador en LCEL
Dado que los recuperadores son objetos Ejecutables
, podemos combinarlos fácilmente con otros objetos Ejecutables
para orquestar flujos de trabajo:
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
plantilla = """Responder preguntas basadas únicamente en el siguiente contexto:
{contexto}
Pregunta: {pregunta}
"""
prompt = ChatPromptTemplate.from_template(plantilla)
modelo = ChatOpenAI()
def formatear_docs(docs):
return "\n\n".join([d.contenido_pagina for d in docs])
cadena = (
{"contexto": recuperador | formatear_docs, "pregunta": RunnablePassthrough()}
| prompt
| modelo
| StrOutputParser()
)
cadena.invocar("¿Qué dijo el presidente sobre la tecnología?")
Explicación del proceso:
- Paso 1: El objetivo es generar un diccionario que contenga dos propiedades,
contexto
ypregunta
, para preparar parámetros para la plantilla de la sugerencia. El parámetrocontexto
es generado por el recuperador basado en el parámetro pasado al métodoinvocar
, que es "¿Qué dijo el presidente sobre la tecnología?". Esto recupera documentos similares a la pregunta, luego formatea el array de documentos usando la funciónformatear_docs
y lo asigna a la propiedadcontexto
. La funciónRunnablePassthrough
copia el parámetro (pregunta del usuario) de la cadena a la propiedadpregunta
. - Paso 2: Pasa el diccionario generado en el primer paso a la plantilla de la sugerencia para formatearlo.
- Paso 3: Pasa la sugerencia formateada desde la plantilla de la sugerencia al modelo.
- Paso 4: Pasa el resultado de la llamada al modelo al analizador de salida
StrOutputParser
.
3. Recuperador Personalizado
4.1. Introducción a la Interfaz del Recuperador
La interfaz del recuperador es muy sencilla, y podemos escribir recuperadores personalizados fácilmente.
4.2. Ejemplo de recuperador personalizado
Aquí tienes un ejemplo de un recuperador personalizado, que demuestra cómo escribir un recuperador personalizado y usarlo para recuperar documentos relevantes:
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")
A través del estudio de las secciones anteriores, obtendrás una comprensión más profunda del concepto, los métodos de recuperación y la personalización de los recuperadores.