inteligencia_artificial:langchain:documentos
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
| inteligencia_artificial:langchain:documentos [2025/01/21 16:46] – [Troceado de documentos] alberto | inteligencia_artificial:langchain:documentos [2025/01/31 00:44] (actual) – [Base de datos vectorial] alberto | ||
|---|---|---|---|
| Línea 60: | Línea 60: | ||
| ===== Troceado de documentos ===== | ===== Troceado de documentos ===== | ||
| - | La información almacenada debe "trocearse" para poder trabajar con ella sin problemas de tener ventanas de contexto demasiado grandes, que reduzcan el desempeño del LLM. \\ | + | Los modelos de lenguaje, o LLM, sólo pueden examinar unos pocos miles de palabras de una vez, por lo que tenemos que necesitamos una solución para documentos que sean largos. |
| + | {{ : | ||
| + | |||
| + | Podemos | ||
| Puede resultar sencillo conceptualmente, | Puede resultar sencillo conceptualmente, | ||
| Línea 70: | Línea 73: | ||
| A continuación algunos tipos de //text splitters// proporcionados por Langchain en **langchain.text_splitter.**: | A continuación algunos tipos de //text splitters// proporcionados por Langchain en **langchain.text_splitter.**: | ||
| - | * **CharacterTextSplitter()** | + | * **CharacterTextSplitter()** |
| - | * **MarkdownHeaderTextSplitter** | + | * **MarkdownHeaderTextSplitter** |
| - | * **TokenTextSplitter()** | + | * **TokenTextSplitter()** |
| - | * **SentenceTransformersTokenTextSplitter()** | + | * **SentenceTransformersTokenTextSplitter()** |
| - | * **RecursiveCharacterTextSplitter()** | + | * **RecursiveCharacterTextSplitter()** |
| - | * **Language()** | + | * **Language()** |
| - | * **NLTKTextSplitter()** | + | * **NLTKTextSplitter()** |
| - | * **SpacyTextSplitter()** | + | * **SpacyTextSplitter()** |
| En el siguiente ejemplo vamos a usar 2 //text splitters// comunes, //recursive character text splitter// y //character text splitter//. | En el siguiente ejemplo vamos a usar 2 //text splitters// comunes, //recursive character text splitter// y //character text splitter//. | ||
| - | La principal diferencia entre ellos, es que en el caso de //character text splitter// sólo divide el texto si encuentra el carácter especificado, | + | Para usar expresiones regulares con //recursive character text splitter// expresiones regulares, con el parámetro // |
| Lo vemos con unos ejemplos: | Lo vemos con unos ejemplos: | ||
| Línea 172: | Línea 175: | ||
| print(r_splitter.split_text(some_text)) | print(r_splitter.split_text(some_text)) | ||
| </ | </ | ||
| + | ===== Guardado de información ===== | ||
| - | text splitter con tokens. | + | ===== Retrieval ===== |
| - | Ejemplo de splitting con contexto con Markdown: | + | |
| - | "La fragmentación tiene como objetivo mantener unido el texto con un contexto común. | + | |
| + | ===== Salida ===== | ||
| + | ===== Embeddings ===== | ||
| + | Una vez " | ||
| + | Los embeddings generan representaciones numéricas de las partes de texto. Estas representaciones son vectores cuyo valor depende del significado de estas partes de texto, de forma que textos semánticamente similares, tendrán vectores similares. | ||
| - | Una división de texto a menudo usa oraciones u otros delimitadores para mantener unido el texto relacionado, | + | {{ : |
| + | {{ : | ||
| + | En el ejemplo de la imagen, los dos primeros casos hablan de mascotas, mientras que el tercero habla de un coche, por lo que los vectores entre los dos primeros son similares (cerca espacialmente, | ||
| + | Los embeddings dependen de un modelo de IA. OpenAI tiene sus embeddings, Llama los suyos, etc. De modo que podemos usar sus APIs para generar estos vectores, aunque no se usen sus LLM. \\ | ||
| + | ===== Base de datos vectorial ===== | ||
| + | Los vectores generados a través de embeddings los guardamos en una base de datos vectorial, desde la que trabajaremos para hacer búsquedas semánticas y recuperar información. \\ | ||
| - | Podemos usar MarkdownHeaderTextSplitter para preservar los metadatos del encabezado en nuestros fragmentos, como se muestra a continuación." | + | {{ : |
| + | Para pasar al modelo las partes más importantes del texto que requiera la consulta, necesitaremos crear un índice **index** que busque entre los vectores de las diferentes porciones de información. | ||
| - | ===== Guardado de información ===== | + | {{ : |
| - | ===== Retrieval ===== | + | Para realizar una búsqueda semántica en la base de datos, se pasa la consulta a vector a través de embeddings, y se compara con los diferentes vectores de cada porción de información. Se devuelven al modelo los más parecidos para poder devolver la respuesta definitiva. |
| - | ===== Salida ===== | + | {{ :ia:langchain_08_vector_database.png?400 |}} |
| - | ===== Embeddings ===== | + | |
| - | Los modelos de lenguaje, o LLM, sólo pueden examinar unos pocos miles de palabras de una vez, por lo que tenemos que buscar una solución para documentos que sean largos. | + | |
| - | {{ :ia:langchain_01_llm_inspeccionar.png?400 |}} | + | |
| + | En langchain existen más de 30 tipos de base de datos vectoriales diferentes que pueden [[https:// | ||
| - | Para almacenar | + | En el siguiente ejemplo cargamos el texto de varios PDFs, dividimos |
| + | <code python> | ||
| + | from langchain_community.document_loaders import PyPDFLoader | ||
| - | {{ : | + | # Cargamos los documentos |
| - | {{ : | + | loaders = [ |
| + | PyPDFLoader(" | ||
| + | | ||
| + | PyPDFLoader(" | ||
| + | PyPDFLoader(" | ||
| + | PyPDFLoader(" | ||
| + | ] | ||
| - | En el ejemplo de la imagen, los dos primeros casos hablan de mascotas, mientras que el tercero habla de un coche, por lo que los vectores entre los dos primeros son similares | + | docs = [] |
| + | for loader in loaders: | ||
| + | docs.extend(loader.load()) | ||
| + | # Troceamos los documentos | ||
| + | from langchain.text_splitter import RecursiveCharacterTextSplitter | ||
| + | text_splitter = RecursiveCharacterTextSplitter( | ||
| + | chunk_size = 500, | ||
| + | chunk_overlap = 50 | ||
| + | ) | ||
| - | ===== Base de datos de vectores ===== | + | splits |
| - | A la base de datos de vectores le pasamos los vectores resultantes de aplicar los embeddings al texto de nuestros documentos. \\ | + | |
| - | Si los documentos son muy grandes, hay que " | + | # Definimos el modelo de embeddings |
| + | from langchain_ollama import OllamaEmbeddings | ||
| - | {{ : | + | embedding = OllamaEmbeddings(model=" |
| - | Para pasar al modelo las partes más importantes del texto que requiera la consulta, necesitaremos crear un índice **index** que busque entre los vectores | + | # Guardamos |
| + | from langchain_community.vectorstores import Chroma | ||
| - | {{ : | + | # Definimos el directorio donde se guardará la base de datos vectorial |
| + | persist_directory = ' | ||
| - | La consulta se pasa a un vector a través de un embedding, y se compara con los diferentes vectores | + | # Eliminamos el directorio si ya existe, es decir, borramos la base de datos anterior antes de volver a lanzar el sript |
| + | import shutil | ||
| - | {{ :ia:langchain_08_vector_database.png?400 |}} | + | path = " |
| + | |||
| + | try: | ||
| + | shutil.rmtree(path) | ||
| + | print(f" | ||
| + | |||
| + | except FileNotFoundError: | ||
| + | print(f" | ||
| + | |||
| + | except Exception as e: | ||
| + | print(f" | ||
| + | |||
| + | # Creamos la base de datos vectorial | ||
| + | vectordb = Chroma.from_documents( | ||
| + | documents = splits, | ||
| + | embedding = embedding, | ||
| + | persist_directory = persist_directory | ||
| + | ) | ||
| + | |||
| + | # Vamos a realizar una consulta | ||
| + | question = "¿En qué parte de la península hay seres fantásticos como hadas y gnomos?" | ||
| + | docus = vectordb.similarity_search(question, | ||
| + | print(f" | ||
| + | |||
| + | print(f" | ||
| + | print(f" | ||
| + | print(f" | ||
| + | </ | ||
| + | Al final del ejemplo anterior realizamos una búsqueda en la base de datos. | ||
| + | Al haber documentos duplicados, podemos obtener diferentes respuestas prácticamente iguales. | ||
| + | También puede ocurrir que se obtenga la información de algunos documentos (vectores), cuando hay otros más idóneos para la consulta realizada. | ||
| + | Veremos en el siguiente apartado // | ||
| ===== Métodos de extracción de información ===== | ===== Métodos de extracción de información ===== | ||
| Hay varios métodos a partir de los cuales se puede extraer la información más importante (la más similar vectorialmente) de las diferentes partes en que se dividió la información. | Hay varios métodos a partir de los cuales se puede extraer la información más importante (la más similar vectorialmente) de las diferentes partes en que se dividió la información. | ||
inteligencia_artificial/langchain/documentos.1737474407.txt.gz · Última modificación: por alberto
