Puedes integrar MongoDB Vector Search con LangChain4j para compilar aplicaciones LLM. Este tutorial demuestra cómo empezar a utilizar MongoDB Vector Search con LangChain4j para realizar búsquedas semánticas en tus datos y compilar una sencilla RAG implementation. Específicamente, realizas las siguientes acciones:
Configura el entorno.
Instancia el modelo de embedding.
Utilice MongoDB como almacén de inserciones.
Almacena datos personalizados en tu clúster de MongoDB.
Ejecuta las siguientes consultas de búsqueda vectorial:
búsqueda semántica.
Búsqueda semántica con prefiltrado de metadatos.
Implementa RAG usando la búsqueda vectorial de MongoDB para responder preguntas sobre tus datos.
Segundo plano
LangChain4j es un framework que simplifica la creación de aplicaciones LLM en Java. LangChain4j combina conceptos y funcionalidades de LangChain, Haystack, LlamaIndex y otras fuentes. Puede utilizar este framework para diversos casos de uso, como la búsqueda semántica y RAG.
Al integrar MongoDB Vector Search con LangChain4j, puedes utilizar MongoDB como una base de datos vectorial y MongoDB Vector Search para implementar RAG (Respuesta Generada por Recuperación) utilizando documentos semánticamente similares para responder a consultas. Para obtener más información sobre RAG, consulta Recuperación-Generación Aumentada (RAG) con MongoDB.
Requisitos previos
Para completar este tutorial, debes tener lo siguiente:
Uno de los siguientes tipos de clúster de MongoDB:
Un clúster de Atlas que ejecuta la versión 6.0.11, 7.0.2 o posterior de MongoDB. Asegúrese de que su dirección IP esté incluida en la lista de acceso de su proyecto Atlas.
Una implementación local de Atlas creada usando Atlas CLI. Para obtener más información, consulta Crear una Implementación local de Atlas.
Un clúster de MongoDB Community o Enterprise con Search y Vector Search instalados.
Una Clave API de Voyage IA. Debes tener una cuenta con tokens disponibles para solicitudes a la API. Para obtener más información sobre cómo registrar una cuenta Voyage IA, consulta Claves API del modelo.
Una llave de API de OpenAI. Debes tener una cuenta de OpenAI con créditos disponibles para las solicitudes de API. Para obtener más información sobre cómo registrar una cuenta de OpenAI, consulta el sitio web de la API de OpenAI.
Java Development Kit (JDK) versión 8 o posterior.
Un entorno para configurar y ejecutar una aplicación Java. Recomendamos utilizar un entorno de desarrollo integrado (IDE) como IntelliJ IDEA o Eclipse IDE para configurar Maven o Gradle para compilar y ejecutar el proyecto.
Configurar el entorno
Primero debes configurar el entorno para este tutorial, lo que incluye agregar las dependencias necesarias y configurar las variables de entorno.
Crea una nueva aplicación Java.
Abra su IDE y cree un nuevo proyecto Java y configure la siguiente configuración:
Nombre: LangChain4jSampleApp
Lenguaje: Java
Sistema de compilación: Maven
JDK: Cualquier versión superior a
8
Es posible que veas una opción para incluir un código de muestra. Seleccionar esta opción puede ayudarte a comprobar que tu entorno funciona y localizar el archivo de aplicación que editas en los siguientes pasos.
Agrega dependencias.
Agregue las siguientes dependencias al arreglo
dependenciesen su archivopom.xmldel proyecto. Estas dependencias agregan las librerías LangChain4j, Voyage IA API para LangChain4j y MongoDB Java Sync Driver a tu aplicación:pom.xml<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-mongodb-atlas</artifactId> <version>1.1.0</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-voyage-ai</artifactId> <version>1.1.0-beta7</version> </dependency> A continuación, añade una entrada
dependencyManagementdebajo de tu lista de dependencias para la Lista de Materiales (BOM) de LangChain4j:pom.xml<dependencyManagement> <dependencies> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-bom</artifactId> <version>1.1.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> Para obtener más información sobre la lista de materiales de LangChain4j, consulte la página Comenzar en la 4documentación de LangChain j.
Cuando termines de editar el archivo
pom.xml, vuelve a cargar tu proyecto para asegurarte de que tus dependencias estén instaladas.
Importar clases y métodos.
Localice el archivo de aplicación principal Main.java en su proyecto. Reemplace las importaciones existentes con la siguiente lista:
import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import dev.langchain4j.data.document.Metadata; import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.voyageai.VoyageAiEmbeddingModel; import dev.langchain4j.store.embedding.EmbeddingMatch; import dev.langchain4j.store.embedding.EmbeddingSearchRequest; import dev.langchain4j.store.embedding.EmbeddingSearchResult; import dev.langchain4j.store.embedding.filter.comparison.*; import dev.langchain4j.store.embedding.mongodb.IndexMapping; import dev.langchain4j.store.embedding.mongodb.MongoDbEmbeddingStore; import org.bson.Document; import java.io.*; import java.util.*;
Más adelante en este tutorial, utilizarás estas clases y métodos para crear embeddings vectoriales y query datos.
Establecer variables de entorno.
Dependiendo de su IDE, puede haber varias maneras de configurar variables de entorno que su aplicación pueda recuperar. Para configurar variables de entorno en IntelliJ, debe crear una configuración de ejecución para su aplicación. Para obtener más información, consulte la sección "Sistema operativo" de la página "Configuración de ejecución/depuración: Aplicación" en la documentación de IntelliJ.
Configure las siguientes variables de entorno:
MONGODB_URI: Establecido a su cadena de conexión de MongoDB.VOYAGE_AI_KEY: Establezca su clave de API de Voyage AI.
Nota
Su cadena de conexión debe usar el siguiente formato:
mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net/?<settings>
Para obtener más información sobre cómo recuperar tu cadena de conexión, consulta la guía de cadenas de conexión.
Instancie el modelo de Embedding
En este paso, se instancia un modelo de embedding que utiliza Voyage AI para convertir texto en datos de muestra en embeddings vectoriales.
Agrega el siguiente código a tu archivo Main.java para instanciar el modelo de embedding usando tu clave de API de Voyage AI y seleccionando voyage-3-large como el modelo:
EmbeddingModel embeddingModel = VoyageAiEmbeddingModel.builder() .apiKey(embeddingApiKey) .modelName("voyage-3-large") .build();
Para obtener más información sobre el modelo voyage-3-large, consulta la entrada de blog sobre voyage-3 & voyage-3-lite en el sitio web de Voyage AI.
Utilizar MongoDB como almacén de embeddings
En esta sección, se instancia MongoDB como una base de datos vectorial, también llamada almacenamiento de vectores o embeddings. Cuando se instancia la tienda de embeddings, LangChain4j crea automáticamente un índice de búsqueda vectorial de MongoDB en tus datos.
Nota
Acceso requerido
Para crear un índice de búsqueda vectorial Project Data Access Admin de MongoDB, debe tener o acceso superior al proyecto MongoDB.
Este código realiza las siguientes acciones:
Crea una instancia de
MongoClientque está conectada a tu implementación de Atlas.Establece el número de dimensiones en la definición del índice de búsqueda vectorial en la dimensión de embedding del modelo de IA. El índice de búsqueda vectorial resultante tiene la siguiente definición:
{ "fields": [ { "type": "vector", "path": "embedding", "numDimensions": 1024, "similarity": "cosine" } ] } Configura tu colección de MongoDB especificando los siguientes parámetros:
langchain4j_test.vector_storecomo la colección de MongoDB para almacenar los documentos.vector_indexcomo el índice a utilizar para consultar la tienda de embedding.
Debido a que el booleano createIndex está configurado en true, la creación de la instancia del almacén de embeddings crea automáticamente el índice de búsqueda vectorial. El código incluye un retraso para permitir la creación exitosa del índice.
Agrega el siguiente código en tu archivo Main.java:
MongoClient mongoClient = MongoClients.create(uri); System.out.println("Instantiating the embedding store..."); // Set to false if the vector index already exists Boolean createIndex = true; IndexMapping indexMapping = IndexMapping.builder() .dimension(embeddingModel.dimension()) .metadataFieldNames(new HashSet<>()) .build(); MongoDbEmbeddingStore embeddingStore = MongoDbEmbeddingStore.builder() .databaseName("search") .collectionName("langchaintest") .createIndex(createIndex) .indexName("vector_index") .indexMapping(indexMapping) .fromClient(mongoClient) .build(); if (createIndex) { // Creating a vector search index can take up to a minute, // so this delay allows the index to become queryable try { Thread.sleep(15000); } catch (InterruptedException e) { throw new RuntimeException(e); } }
Para obtener más información sobre las clases y métodos utilizados en el código anterior, consulta la documentación de la API del paquete dev.langchain4j.store.embedding.mongodb.
Almacenar datos personalizados
En esta sección, creará documentos de muestra, utilizará el modelo de incrustación para convertir el texto en incrustaciones y conservará los datos en MongoDB.
Este código realiza las siguientes acciones:
Crea una lista de documentos de muestra que incluye los campos
textymetadata.Convierte el contenido del campo
texten incrustaciones y conserva los datos en MongoDB. El código incluye un retardo para adaptar el tiempo necesario para la conversión vectorial.
Agrega el siguiente código en tu archivo Main.java:
ArrayList<Document> docs = new ArrayList<>(); docs.add(new Document() .append("text", "In Zadie Smith's new novel, the true story of a heated nineteenth-century criminal trial connects to the unrest of current times.") .append("metadata", new Metadata(Map.of("author", "A")))); docs.add(new Document() .append("text", "Emperor penguins are the tallest and heaviest of all penguin species, standing up to 4 feet.") .append("metadata", new Metadata(Map.of("author", "D")))); docs.add(new Document() .append("text", "Penguins are flightless seabirds that live almost exclusively below the equator. Some island-dwellers can be found in warmer climates.") .append("metadata", new Metadata(Map.of("author", "C")))); docs.add(new Document() .append("text", "Patagonia is home to five penguin species - Magellanic, Humboldt, Gentoo, Southern Rockhopper and King.") .append("metadata", new Metadata(Map.of("author", "B")))); System.out.println("Persisting document embeddings..."); for (Document doc : docs) { TextSegment segment = TextSegment.from( doc.getString("text"), doc.get("metadata", Metadata.class) ); Embedding embedding = embeddingModel.embed(segment).content(); embeddingStore.add(embedding, segment); } // Delay for persisting data try { Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); }
Ejecución de consultas de búsqueda vectorial
Esta sección demuestra cómo ejecutar consultas en sus datos vectorizados.
Realiza una búsqueda semántica.
Este código realiza una query de búsqueda semántica para la frase "Where do penguins live?" y devuelve los tres resultados más relevantes. También imprime un puntaje que muestra qué tan bien cada resultado coincide con la query.
Agrega el siguiente código a tu archivo Main.java:
String query = "Where do penguins live?"; Embedding queryEmbedding = embeddingModel.embed(query).content(); EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder() .queryEmbedding(queryEmbedding) .maxResults(3) .build(); System.out.println("Performing the query..."); EmbeddingSearchResult<TextSegment> searchResult = embeddingStore.search(searchRequest); List<EmbeddingMatch<TextSegment>> matches = searchResult.matches(); for (EmbeddingMatch<TextSegment> embeddingMatch : matches) { System.out.println("Response: " + embeddingMatch.embedded().text()); System.out.println("Author: " + embeddingMatch.embedded().metadata().getString("author")); System.out.println("Score: " + embeddingMatch.score()); }
Response: Penguins are flightless seabirds that live almost exclusively below the equator. Some island-dwellers can be found in warmer climates. Author: C Score: 0.829620897769928 Response: Patagonia is home to five penguin species - Magellanic, Humboldt, Gentoo, Southern Rockhopper and King. Author: B Score: 0.7459062337875366 Response: Emperor penguins are the tallest and heaviest of all penguin species, standing up to 4 feet. Author: D Score: 0.6908764839172363
(Opcional) Ejecuta una búsqueda semántica con filtrado por metadatos.
Para realizar una búsqueda con filtro de metadatos, puedes utilizar las clases del paquete dev.langchain4j.store.embedding.filter.comparison. Estas clases te permiten crear filtros que comparan los valores de metadatos con los valores especificados para reducir los resultados devueltos por la búsqueda.
Este ejemplo filtra los documentos en los que el valor del campo author es "B" o "C". Luego, realiza una query de búsqueda semántica para la frase "Where do penguins live?".
Reemplace el código que crea una instancia EmbeddingSearchRequest en el paso anterior con el siguiente código:
EmbeddingSearchRequest searchRequest = EmbeddingSearchRequest.builder() .queryEmbedding(queryEmbedding) .filter(new IsIn("author", List.of("B", "C"))) .maxResults(3) .build();
Response: Penguins are flightless seabirds that live almost exclusively below the equator. Some island-dwellers can be found in warmer climates. Author: C Score: 0.8520907163619995 Response: Patagonia is home to five penguin species - Magellanic, Humboldt, Gentoo, Southern Rockhopper and King. Author: B Score: 0.7666836977005005
Para obtener más información sobre el prefiltrado de metadatos, consulta MongoDB Vector Search.
Tip
Para obtener más información, consulte la referencia de API.
Utilice sus datos para responder preguntas
Esta sección demuestra una implementación de RAG que utiliza el framework LangChain4j y la Búsqueda Vectorial de MongoDB. Ahora que has usado la búsqueda vectorial de MongoDB para recuperar documentos semánticamente similares, utiliza los siguientes ejemplos de código para indicarle al LLM que responda preguntas usando información de los documentos almacenados en MongoDB.
Configura tu proyecto para RAG.
Agregue las siguientes dependencias a la
dependenciesmatriz en el archivo de supom.xmlproyecto, pero no elimine ninguna de las dependencias ya agregadas. Estas dependencias agregan los4servicios de IA de LangChain j y la API de OpenAI para las bibliotecas de LangChain4j a su aplicación:pom.xml<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId> <version>1.1.0</version> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j</artifactId> <version>1.1.0</version> </dependency> Cuando termines de editar el archivo
pom.xml, vuelve a cargar tu proyecto para asegurarte de que tus dependencias estén instaladas.Agregue las siguientes importaciones a su lista de importaciones en su archivo
Main.java:import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import dev.langchain4j.service.AiServices; import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.openai.OpenAiChatModel; import dev.langchain4j.rag.content.retriever.ContentRetriever; import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever; Configure la variable de entorno
OPENAI_KEYcon su clave API de OpenAI. Utilice esta clave para crear un modelo de chat que genere una respuesta a su query.
Cargue los datos de muestra.
En este paso se ingresan datos externos en Atlas. Descarga el archivo de datos de muestra rainforest-docs.json desde el docs-code-examples repositorio de GitHub. Los documentos de este archivo contienen información sobre las plantas, animales y clima de la selva tropical.
Sube este archivo al directorio resources de tu proyecto, que se encuentra al mismo nivel que el directorio java que contiene los archivos de tu aplicación.
Debe procesar los datos en un formato utilizable que permita crear incrustaciones y conservarlas en Atlas. Este código define el método loadJsonDocuments(), que realiza las siguientes acciones:
Recupera los datos de muestra de su directorio
resourcesutilizando la claseClassLoaderProcesa los documentos JSON a un
Listde instanciasDocumentde MongoDB usando la claseObjectMapper
Agrega el siguiente código a tu archivo Main.java fuera de tu método principal:
private static List<Document> loadJsonDocuments(String resourcePath) throws IOException { // Loads file from resources directory using the ClassLoader InputStream inputStream = Main.class.getClassLoader().getResourceAsStream(resourcePath); if (inputStream == null) { throw new FileNotFoundException("Resource not found: " + resourcePath); } // Parses JSON file to List of MongoDB Documents ObjectMapper objectMapper = new ObjectMapper(); List<Document> documents = objectMapper.readValue(inputStream, new TypeReference<>() {}); return documents; }
Luego, añade el siguiente código en el cuerpo del método principal para llamar al método loadJsonDocuments() y cargar tus documentos:
System.out.println("Loading documents from file..."); String resourcePath = "rainforest-docs.json"; List<Document> documents = loadJsonDocuments(resourcePath);
Almacena incrustaciones vectoriales en Atlas.
En este paso, creará incrustaciones vectoriales a partir de sus documentos de muestra y las conservará en Atlas.
Este código convierte el contenido de los campos text de los documentos de ejemplo en incrustaciones y conserva los datos en Atlas. El código incluye un retardo para adaptar el tiempo necesario para la conversión vectorial.
Agrega el siguiente código en tu archivo Main.java:
System.out.println("Persisting document embeddings..."); for (Document doc : documents) { TextSegment segment = TextSegment.from( doc.getString("text"), new Metadata(doc.get("metadata", Map.class))); Embedding embedding = embeddingModel.embed(segment).content(); embeddingStore.add(embedding, segment); } try { Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); }
Instanciar el modelo de chat y especificar el recuperador de contenido.
En este paso, se instancia un modelo de chat de OpenAI para poder responder preguntas basadas en los datos. También se especifica un recuperador de contenido que muestra los documentos relevantes para fundamentar la respuesta generada por el modelo de chat.
Este código realiza las siguientes acciones:
Instancia el modelo de chat usando tu clave API de OpenAI.
Crea el recuperador de contenido con las siguientes especificaciones:
Recupera como máximo
3documentos relevantesRecupera documentos que tienen una puntuación de relevancia de al menos
0.75
Agrega el siguiente código a tu archivo Main.java en el cuerpo del método principal:
String chatApiKey = System.getenv("OPENAI_KEY"); ChatLanguageModel chatModel = OpenAiChatModel.builder() .apiKey(chatApiKey) .modelName("gpt-4") .build(); ContentRetriever contentRetriever = EmbeddingStoreContentRetriever.builder() .embeddingStore(embeddingStore) .embeddingModel(embeddingModel) .maxResults(3) .minScore(0.75) .build();
Tip
Filtrado de metadatos
Puedes implementar el filtrado de metadatos en tu ContentRetriever usando el método builder filter() y pasando una instancia de un Filter. Consulta el ejemplo de filtro de metadatos en el paso anterior para aprender cómo construir un Filter.
Crear el asistente de chat.
Cree una interfaz Assistant simple que implemente la API de Servicios de IA en su aplicación. Cree un archivo de interfaz llamado Assistant.java al mismo nivel que su archivo Main.java.
Define la interfaz Assistant:
package org.example; public interface Assistant { String answer(String question); }
En tu archivo Main.java, instancia el Assistant:
Assistant assistant = AiServices.builder(Assistant.class) .chatLanguageModel(chatModel) .contentRetriever(contentRetriever) .build();
Realizar consultas sobre sus datos.
Finalmente, realice una consulta con los datos de muestra. Agregue el siguiente código al archivo Main.java para ejecutar una consulta e imprimir el resultado:
String ragQuery = "What types of insects live in the rainforest?"; String output = assistant.answer(ragQuery); System.out.println("Response:\n" + output);
Response: In the rainforest, there are numerous species of insects such as beetles, butterflies, moths, wasps, bees, flies, and ants. Of the many insects that live in the rainforest, ants are particularly important as they play a crucial role in nutrient recycling and aeration of the soil. Moreover, many of these insects are involved in the processes of pollination and decomposition. The adaptations these insects have developed enable their survival in the rainforest's specific conditions, characterized by heavy rainfall.
Próximos pasos
MongoDB también proporciona los siguientes recursos para desarrolladores:
Cómo crear una aplicación RAG con LangChain4j tutorial en el sitio web de la comunidad DEV