Los índices en Langchain son vitales para organizar y estructurar grandes volúmenes de información, facilitando así su fácil consulta y recuperación. Imagina que tienes un libro de 300 páginas lleno de texto; buscar información específica sin un índice sería caótico. Los índices segmentan el contenido en capítulos y subcapítulos, señalando en qué página se encuentra cada tema.
En el contexto de Langchain, cuando ingresas múltiples documentos en una base de datos vectorial, esta se parte y el índice te permite identificar rápidamente qué fragmentos son relevantes para tus consultas. Es una herramienta fundamental para acceder a la información de manera rápida y efectiva.
¿Qué es la clase Document en Langchain?
La clase Document es uno de los componentes nucleares de Langchain. Forma parte de la librería de esquemas, que son los ladrillos fundamentales de esta tecnología. Para crear un documento en Langchain, necesitas proporcionar dos elementos cruciales:
Page Content: El contenido del texto en sí, el cual puede ser extenso y aportar el cuerpo del documento.
Metadata: Variables adicionales que describen al documento, como la fuente, la clase o temática del texto.
Ejemplo práctico de la clase Document
Para ilustrar esto, vamos a ver un ejemplo:
from langchain.schema import Document
# Creando el contenido del documentopage_content ="Texto largo, ejemplo"# Creando la metadata correspondientemetadata ={"fuente":"Platzi","clase":"Langchain"}# Instanciando la clase Documentdoc = Document(page_content=page_content, metadata=metadata)
Este Document contiene el texto principal y la metadata asociada.
¿Por qué es importante la metadata en los documentos?
La metadata es un concepto quizás menos explorado, pero extremadamente útil al crear un índice. Permite categorizar y etiquetar la información de múltiples maneras, lo cual es esencial cuando queremos buscar datos precisos en grandes colecciones de documentos.
Utilidades de la metadata
Identificación de la fuente: Proporciona el origen del documento; en nuestro ejemplo, es "Platzi".
Clasificación temática: Ayuda a identificar el tema o curso al que pertenece; en el caso ilustrado, la clase de "Langchain".
La metadata, aunque acompaña al texto primario, juega un papel clave en la segmentación y búsqueda de información relevante dentro de las gigantescas bases de datos.
¿Cómo se gestiona una gran cantidad de documentos?
En Langchain, manejar una gran cantidad de documentos implica cortar estos textos en fragmentos más pequeños, cada uno encapsulado en un Document separado con su propio page_content y metadata. Esta técnica asegure instalación óptima y eficiencia durante el proceso de indexación y búsqueda:
División del texto: Cada documento se divide según sea necesario para mantenerlo manejable y fácil de buscar.
Acompañado de metadata: Cada fragmento incluye metadata que puede proporcionar contexto adicional al texto.
Así, al manejar centenares de textos, es crucial segmentarlos correctamente para su posterior integración en la base de datos y facilitar su recuperación eficiente. En resumen, este método estructural es la base de un manejo efectivo de información con Langchain.
-Son la forma de estructurar documentos para que los LLM puedan interactuar con ellos de la mejor forma
-Con lo cual permite optimizar eficiencia y velocidad de las operaciones búsqueda y recuperación de información
-Son un análogo a los índices de libros que permiten localizar rápidamente un contenido específico.De manera similar los indices en langchain permiten a los LLM encontrar rápidamente información relevante sin tener que procesar todos los documentos disponibles.
Recuperación de información y los índices:
El uso más común de índices es la recuperación de información en el procesamiento de datos
Toma la consulta del usuario y devuelve los documentos más relevantes, considerando la siguiente distinción:
Un índice puede utilizarse para aplicaciones diferentes a la recuperación
La recuperación puede utilizar otras lógicas además de un índice para encontrar los documentos más relevantes
La indexación y recuperación de datos no estructurados es la referencia común cuanto se habla de índices y recuperación de información.
Retriver en LangChain
-Es un componente fundamental, su responsabilidad es localizar y devolver documentos relevantes según una consulta específica(como un bibliotecario que sabe exactamente la ubicación de los libros necesario)-Retriver implementa el método `get_relevant_documents`, la estrategia más eficiente planteado por LangChain se basa en el concepto de Vectorstore, centrándonos en Retriver tipo vectorstore
Vectorstore y los Vectorestore Retriver
- Un vectorstore :
-Es un tipo de base de datos especialmente diseñada para gestionar y manipular vectores de alta dimensionalidad
-Comúnmente utilizado para presentar datos en apredizaje automático y otras aplicaciones de IA-Si el retriver es el bibliotecario, el vectorstore sería el sistema de clasificación y organización de la biblioteca
-LangChain utiliza como sistema Vectorstore predeterminada a Chroma, el cual es utilizado para indexar y buscar embeddings(vectores que representan documentos en el espacio multidimencional)-Los embedding son una forma de condensar y representar la información de un documento para que pueda ser fácilmente comparada con otros
-ElRetriver tipo Vectorstore primero transforma la consulta en un vector(por medio del embedding), luego busca en la base de datos Vectorstore los documentos cuyos vectores son más cercanos(en términos de distancia coseno u otras métricas) a la consulta vectorizada
Un LLM puede recordar información de 2 maneras:
Los datos con los que se entrenó, lo cual es limitado
Podemos hacer que un LLM recuerde información a partir del contenido que le ingresemos al prompt.
Para ingresar información al LLM por medio del prompt:
La clave está en cómo ingresarle al información al modelo para que este genere la mejor respuesta a las preguntas del usuario o de la usuaria
Los índices permiten abordar este tema:
Permitirán encontrar la información clave que necesitamos.
Permite cargar la información al LLM desde cualquier tipo de fuente
Luego de la carga debemos pasar por todo un proceso:
Document loaders → cargar información
Text splitters → embedding que conviertan de texto a número
Vectorstore → permite crear el índice
Los queries también ingresan a la vectorstore para buscar el fragmento de texto que tiene la mayor probabilidad de responder adecuadamente dicha query. Dichos fragmentos son pasados al modelo como insumo para que de la respuesta la usuario
Excelente aporte, y la forma de verlo como una biblioteca se me hizo una gran forma de visualizarlo, gracias!
muchas gracias por la aportacion.
Me surge una duda acerca de como se manejan los indices en openAI, si estoy creando una aplicación en la cual yo pueda hacer una query de mis datos, mi contexto será un documento de 800 páginas, por ende en cada momento de hacer una query o un prompt cual será la cantidad de tokens usadas?
Cuando trabajas con OpenAI y particularmente con modelos como GPT-3 o GPT-4, hay un límite en la cantidad de tokens que el modelo puede manejar en una sola pasada. Por ejemplo, GPT-3 tiene un límite de 4096 tokens.
.
Contando tokens en tu documento: Primero, debes tener en cuenta que el documento de 800 páginas que quieres utilizar como contexto será convertido en tokens. Un token puede ser tan corto como un carácter o tan largo como una palabra. Por lo tanto, el número de tokens en tu documento podría ser bastante grande. Si el documento excede el límite de tokens del modelo, tendrás que encontrar una manera de reducirlo o dividirlo.
.
Tokens en tu consulta: Además, la consulta o el prompt que planeas enviar al modelo también consumirá tokens. Por ejemplo, si tu consulta es de 10 tokens, estos se sumarán a los tokens utilizados de tu documento.
.
Resumen del documento: Si tu documento es muy largo, podrías considerar crear un resumen o extraer las partes más relevantes para reducir el número de tokens. Esto puede ser un desafío, especialmente si necesitas mantener un alto grado de precisión y contexto.
.
División del documento: Otra estrategia podría ser dividir el documento en partes más pequeñas y hacer consultas separadas sobre estas partes. Esto podría ser manejable, pero podrías perder contexto entre las diferentes partes del documento.
.
Uso eficiente del espacio de tokens: Puedes también considerar técnicas para hacer un uso más eficiente del espacio de tokens, como la eliminación de información redundante, la reducción de la verbosidad, etc.
.
Modelos con mayor capacidad de tokens: En el futuro, podrían existir modelos con mayores límites de tokens que podrían manejar documentos más grandes en una sola pasada.
.
Indexación y Búsqueda: En algunos casos, podrías considerar usar técnicas de indexación y búsqueda para identificar y recuperar solo las partes más relevantes del documento para cada consulta. Esto podría ser combinado con el uso de un modelo de lenguaje para proporcionar respuestas más precisas y contextualizadas.
📝 Creando Documentos
.
ℹ️ Summary
Esta guía proporciona un caso de uso sobre "Document Loaders", cuando es necesario crear documentos para un repositorio de información.
.
🗂️ Background
Un Documento es un fragmento de texto y metadatos asociados. El fragmento de texto es con el que interactuamos con el modelo lingüístico, mientras que los metadatos opcionales son útiles para realizar un seguimiento de los metadatos sobre el documento (como la fuente).
.
Enlaces auxiliares:
Document Loaders
.
🎯 Problem
Implementar un "Document Loader" utilizando TypeScript para generar un repositorio de información, vinculando los documentos mediante los metadatos de category y owner.
.
🚧 Solution
LangChain provee de una abstracción, para cargar documentos según sea el formato del mismo mediante Document.
import { Document } from "langchain/document"
Posteriormente, según sea la definición del documento (texto, PDF, etc.), tendríamos que variar su implementación. Por ejemplo, para cargar documentos en "Plain Text":
import { TextLoader } from 'langchain/document_loaders/fs/text'
const loader = new TextLoader('tmp/meeting.txt')
const docsLoaded = await loader.load()
Para proveer de una información adicional como metadatos, modificamos la solución de nuestros loaders:
Según sea la propuesta de desarrollo, como lo son los vector stores, podemos implementar una abstracción más completa para poder embeber más documentos.
.
Cabe mencionar, es posible anexar diferentes tipos de documentos entre sí para generar una basta colección de información a procesar.
Para fragmentar un texto usando page_content en LangChain, debes dividir el texto en partes más pequeñas antes de crear instancias de la clase Document. Generalmente, esto se realiza utilizando TextSplitter que permite fragmentar el contenido en trozos manejables.
Por ejemplo, puedes tomar un texto largo y dividirlo en párrafos o frases, asignando cada fragmento a su propio Document con su page_content correspondiente. Este proceso facilita la búsqueda y recuperación de información relevante en tus índices.
en langchain.schema, están los atributos más relevantes de langchain, hay que entrar a revisar un poco de está parte,