Terraformando AI fluxos de trabalho de IA: RAG RAG com MongoDB Atlas e Spring AI AI
Avalie esse Tutorial
Qual é a maneira mais fácil de lidar com o gerenciamento de infraestrutura sem clicar manualmente na interface do usuário de um fornecedor de nuvem? Melhor ainda, como você pode automatizar todo o processo – bancos de dados, clusters, índices – para que você possa se concentrar apenas na criação do seu aplicativo? Bem, é exatamente aqui que entra oHashiCorp Terraform, e hoje vamos vê-lo em ação com o MongoDB Atlas.
Eu posso saber o que você pode estar achando. Infraestrutura? Não é a coisa mais legal do mundo. Mas me ouça. O Terraform, em toda a sua gloria declarativa, pode fazer o gerenciamento de recursos da nuvem parecer menos uma tarefa árdua e mais como estabelecer um projeto para algo demais. Ao escrever algumas linhas de código (porque nenhuma quantidade de UX nunca me fará aproveitar a UI para DevOps), você terá sua infraestrutura instalada e funcionando sem suar.
Neste tutorial, estamos configurando um cluster MongoDB Atlas, configurando a pesquisa vetorial e criando um aplicativo degeração aumentada de recuperação (RAG)com incorporaçõesSpring Boot e OpenAI. E a melhor parte? Usaremos o Terraform para automatizar tudo. Clusters do MongoDB Atlas , listas de controle de acesso IP, backups — tudo é tratado por nós.
Veremos como implantar programaticamente tudo o que você precisa para uma configuração escalável e com prioridade para a nuvem. Nenhum salto entre provedor de nuvem . Sem erros manuais. Apenas uma infraestrutura limpa e automatizada pronta para dar suporte à sua aplicação RAG. E se você estiver usando o Amazon Web Services, oAzure ou o Google Cloud Platform, o Terraform ajuda você.
Então, até o final deste tutorial, você não terá apenas um RAG aplicativo RAG habilidoso. Você também terá uma compreensão sólida de como o Terraform e o MongoDB Atlas podem trabalhar juntos para facilitar sua vida. O projeto inteiro está disponível Github no Github. Vamos pular para o código.
Para acompanhar este tutorial, precisamos garantir que temos:
- Java 21 ou superior.
- Maven ou Gradle (para gerenciar dependências): Usamos o Maven para este tutorial.
- Uma conta do MongoDB Atlas, com um método de cobrança adicionado (para nossos clusters de nível pago).
- Terraform instalado em seu sistema, de preferência usando a versão principal mais recente do Terraform Core, que no momento em que este artigo foi escrito é v1.9.
Primeiro, configuraremos o cluster do MongoDB Atlas, o usuário de banco de dados de dados e o índice de pesquisa vetorial usando Terraform.
Criamos um novo diretório para nosso projeto Terraform e criamos dois arquivos:
main.tf
e variables.tf
.Agora, vamos falar sobre as variáveis que vamos usar para o MongoDB Atlas. Em vez de codificar valores diretamente na configuração do Terraform (que é um antipadrão), definimos todas as coisas importantes como variáveis. Dessa forma, podemos trocar valores facilmente ao nos movermos entre ambientes como desenvolvimento, preparação e produção, sem tocar no código principal do Terraform.
1 variable "atlas_org_id" { 2 description = "MongoDB Atlas Organization ID" 3 type = string 4 } 5 6 variable "public_key" { 7 description = "Public API key for MongoDB Atlas" 8 type = string 9 } 10 11 variable "private_key" { 12 description = "Private API key for MongoDB Atlas" 13 type = string 14 } 15 16 variable "cluster_name" { 17 description = "Name of the MongoDB Atlas cluster" 18 type = string 19 default = "RagCluster" 20 } 21 22 variable "project_name" { 23 description = "Name of the MongoDB Atlas project" 24 type = string 25 default = "RAGProject" 26 } 27 28 variable "db_username" { 29 description = "MongoDB database username" 30 type = string 31 } 32 33 variable "db_password" { 34 description = "MongoDB database password" 35 type = string 36 } 37 38 variable "ip_address" { 39 description = "IP address to whitelist" 40 type = string 41 }
Tudo bem, então o que temos aqui é uma configuração Terraform que está essencialmente fazendo todo o trabalho pesado para configurar nossa infraestrutura MongoDB Atlas . Em vez de clicar manualmente no MongoDB Atlas ou lidar com a interface do usuário (porque quem realmente curte fazer isso pelo DevOps?), Esse código automatiza todo o processo. Vamos analisar.
Primeiro, declaramos o blocoTerraform:
1 terraform { 2 required_providers { 3 mongodbatlas = { 4 source = "mongodb/mongodbatlas" 5 } 6 } 7 required_version = ">= 0.13" 8 }
É como dizer ao Terraform: "Ei, preciso do MongoDB Atlas Provider para esse tarefa", que é um plug-in oficial compatível com o plugin que permite que o Terraform gerencie o MongoDB Atlas. Também estamos verificando se o Terraform está na versão 0.13 ou superior.
Em seguida, configuramos o próprio provedor MongoDB Atlas :
1 provider "mongodbatlas" { 2 public_key = var.public_key 3 private_key = var.private_key 4 }
É aqui que fornecemos ao Terraform as chaves da API programática (que configuraremos mais tarde), ele precisa para se comunicar com o MongoDB Atlas em nosso nome. Estamos usando variáveis aqui (
var.public_key
e var.private_key
), o que significa que as chaves reais são armazenadas com segurança em variáveis de ambiente ou em outro método seguro. Sem credenciais de código rígidas aqui - segurança em primeiro lugar, certo?Agora, criamos um projeto no MongoDB Atlas:
1 resource "mongodbatlas_project" "rag_project" { 2 name = var.project_name 3 org_id = var.atlas_org_id 4 }
Este bloco ativa um projeto MongoDB Atlas com um nome e ID da organização que já definimos em variáveis. Pense nisso como a pasta onde residem todos os nossos bancos de dados, clusters e usuários.
Agora, para as coisas boas: construir o cluster real:
1 resource "mongodbatlas_advanced_cluster" "rag_cluster" { 2 project_id = mongodbatlas_project.rag_project.id 3 name = var.cluster_name 4 cluster_type = "REPLICASET" 5 6 replication_specs { 7 region_configs { 8 electable_specs { 9 instance_size = "M10" 10 node_count = 3 11 } 12 provider_name = "AWS" 13 region_name = "EU_WEST_1" 14 priority = 7 15 } 16 } 17 }
É aqui que configuramos um cluster de conjunto de réplicas no MongoDB Atlas (basicamente, alta disponibilidade para nossos dados). Especificamos o tamanho da instância (
M10
, que é uma instância razoável) e ativamos três nós na 7regiãoeu_WEST_ no Amazon Web Services. Também atribuímos a ele uma prioridade de, o que afeta o processo de eleição se um nó falhar. Resumindo: essa configuração está configurando um cluster resiliente e pronto para produção.1Em seguida, precisamos garantir que apenas IPs confiáveis possam acessar nosso cluster MongoDB :
1 resource "mongodbatlas_project_ip_access_list" "ip_list" { 2 project_id = mongodbatlas_project.rag_project.id 3 ip_address = var.ip_address 4 }
Esse bloqueio adiciona um endereço IP à lista de permissões para que somente os dispositivos desse endereço possam se comunicar com nosso cluster. Super importante para a segurança - deixe entrar apenas os moços.
Finalmente, criamos um usuário de banco de dados de dados:
1 resource "mongodbatlas_database_user" "db_user" { 2 username = var.db_username 3 password = var.db_password 4 project_id = mongodbatlas_project.rag_project.id 5 auth_database_name = "admin" 6 7 roles { 8 role_name = "readWrite" 9 database_name = "rag" 10 } 11 }
Este bloco cria um novo usuário de banco de dados de dados MongoDB com acesso de leitura e gravação ao
rag
banco de banco de dados. Estamos usando variáveis para o nome de usuário e senha, para que sejam mantidos em segurança e fora da configuração principal. Esse usuário é criado no admin
banco de banco de dados, mas tem permissões para o rag
banco de banco de dados, que é com o qual estamos trabalhando.Então, resumindo: esta configuração do Terraform está configurando um projeto MongoDB Atlas totalmente automatizado com um cluster, controles de acesso e um usuário, enquanto mantém tudo seguro e pronto para a ação.
Para configurar nosso aplicação Terraform, precisamos adicionar algumas variáveis de ambiente.
1 export TF_VAR_atlas_org_id="$MONGODB_ORG_ID" 2 export TF_VAR_public_key="$MONGODB_PUBLIC_KEY" 3 export TF_VAR_private_key="$MONGODB_PRIVATE_KEY" 4 export TF_VAR_db_username="$MONGODB_USER" 5 export TF_VAR_db_password="$MONGODB_PASSWORD" 6 export TF_VAR_ip_address="$IP_ADDRESS"
Nota: o Terraform assumirá as variáveis que começam com
TF_VAR_
Para obter o ID da organização Atlas ID, precisamos Go acessar a página inicial da organização na interface do usuário do Atlas e selecionar configurações. Aqui, podemos pegar nosso ID da organização.
Em seguida, precisamos criar um
public key
e um private key
. Precisamos Go ir até o Gerenciador de acesso na parte superior da interface do usuário do Atlas e selecionar o acesso da organização . Selecione API chaves de API e criaremos uma chave com as permissões do Organization Owner
e copiaremos essas chaves para usar como variáveis de ambiente.Agora podemos adicionar um nome de usuário e senha que serão criados com permissões de leitura/escrita no cluster que nosso projeto criará.
Depois de adicionados, é hora de inicializar e aplicar nossa configuração Terraform, criando assim nosso projeto.
- Inicialize o projeto Terraform :
1 terraform init - Aplique a configuração:
1 terraform apply
Isso provisionará um projeto, cluster e índice de pesquisa doMongoDB Atlas para o aplicativo RAG, bem como criará um usuário de banco de dados de dados e uma lista de acesso IP.
Em seguida, criaremos um aplicação Spring Boot que se conecta ao MongoDB Atlas, gera incorporações usando OpenAI e executa geração aumentada de recuperação(RAG) .
Você pode clonar esse aplicação a partir do Github repositório do Github Spring-AI-Rag ou seguir as etapas abaixo.
Esta será uma rápida revisão de como criar nosso RAG aplicação RAG. Tudo de que você precisa estará neste tutorial! Mas, se quiser mais informações sobre o que estamos construindo aqui, como o RAG RAG e a IA do AI Spring, recomendamos ler meus outros tutoriais Geração de recuperação-aumento com MongoDB e IA do Spring AI: levando IA AI para seus Java aplicativos Java e construindo um semântica Serviço de pesquisa com Spring AI AI e MongoDB Atlas. Repita, todo o código e configuração estarão neste tutorial!
Baixe o projeto e abra-o no IDE de sua preferência.
Em nosso
pom.xml
arquivo, verifique se temos as seguintes dependências:1 <dependencies> 2 <dependency> 3 <groupId>org.springframework.boot</groupId> 4 <artifactId>spring-boot-starter-web</artifactId> 5 </dependency> 6 7 <dependency> 8 <groupId>org.springframework.data</groupId> 9 <artifactId>spring-data-mongodb</artifactId> 10 </dependency> 11 12 <dependency> 13 <groupId>org.springframework.ai</groupId> 14 <artifactId>spring-ai-openai</artifactId> 15 <version>1.0.0-SNAPSHOT</version> 16 </dependency> 17 </dependencies>
Abra o
application.properties
arquivo na pasta de recursos e configure as seguintes propriedades para MongoDB e OpenAI:1 spring.application.name=RagApp 2 3 # OpenAI API key 4 spring.ai.openai.api-key=${OPENAI_API_KEY} 5 spring.ai.openai.chat.options.model=gpt-4 6 7 # MongoDB Atlas URI and Database 8 spring.data.mongodb.uri=${MONGO_URI} 9 spring.data.mongodb.database=rag 10 11 spring.ai.vectorstore.mongodb.initialize-schema=false
Podemos recuperar seu URI de conexão do MongoDB a partir da UI do Atlas para o cluster que acabamos de criar.
Estas propriedades conectarão nosso aplicação ao MongoDB Atlas e OpenAI utilizando as variáveis de ambiente.
Crie um
Config.java
arquivo para configurar a integração do OpenAI e do MongoDB Atlas para incorporações e pesquisa vetorial.1 import org.springframework.ai.embedding.EmbeddingModel; 2 import org.springframework.ai.openai.OpenAiEmbeddingModel; 3 import org.springframework.ai.openai.api.OpenAiApi; 4 import org.springframework.ai.vectorstore.MongoDBAtlasVectorStore; 5 import org.springframework.ai.vectorstore.VectorStore; 6 import org.springframework.beans.factory.annotation.Value; 7 import org.springframework.context.annotation.Bean; 8 import org.springframework.context.annotation.Configuration; 9 import org.springframework.data.mongodb.core.MongoTemplate; 10 11 12 public class Config { 13 14 15 private String openAiKey; 16 17 18 public EmbeddingModel embeddingModel() { 19 return new OpenAiEmbeddingModel(new OpenAiApi(openAiKey)); 20 } 21 22 23 public VectorStore mongodbVectorStore(MongoTemplate mongoTemplate, EmbeddingModel embeddingModel) { 24 return new MongoDBAtlasVectorStore(mongoTemplate, embeddingModel, 25 MongoDBAtlasVectorStore.MongoDBVectorStoreConfig.builder().build(), true); 26 } 27 }
Este arquivo configura nosso modelo de incorporação OpenAI para gerar nossas incorporações e nosso armazenamento de vetores MongoDB Atlas para armazenar e pesquisar nossos documentos.
Agora, é hora de implementarmos um serviço de carregamento de documento e trazer o Atlas Vector Search para nosso aplicação.
Crie um
DocsLoaderService.java
serviço em um Service
pacote para carregar documentos de um conjunto de dados e armazená-los no armazenamento vetorial do MongoDB Atlas .1 package com.mongodb.RagApp.service; 2 3 import com.fasterxml.jackson.databind 4 5 .ObjectMapper; 6 import org.springframework.ai.document.Document; 7 import org.springframework.ai.vectorstore.VectorStore; 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.core.io.ClassPathResource; 10 import org.springframework.stereotype.Service; 11 12 import java.io.BufferedReader; 13 import java.io.InputStream; 14 import java.io.InputStreamReader; 15 import java.util.ArrayList; 16 import java.util.List; 17 import java.util.Map; 18 19 20 public class DocsLoaderService { 21 private static final int MAX_TOKENS_PER_CHUNK = 2000; 22 private final VectorStore vectorStore; 23 private final ObjectMapper objectMapper; 24 25 26 public DocsLoaderService(VectorStore vectorStore, ObjectMapper objectMapper) { 27 this.vectorStore = vectorStore; 28 this.objectMapper = objectMapper; 29 } 30 31 public String loadDocs() { 32 try (InputStream inputStream = new ClassPathResource("docs/devcenter-content-snapshot.json").getInputStream(); 33 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { 34 35 List<Document> documents = new ArrayList<>(); 36 String line; 37 while ((line = reader.readLine()) != null) { 38 Map<String, Object> jsonDoc = objectMapper.readValue(line, Map.class); 39 String content = (String) jsonDoc.get("body"); 40 41 List<String> chunks = splitIntoChunks(content, MAX_TOKENS_PER_CHUNK); 42 for (String chunk : chunks) { 43 Document document = createDocument(jsonDoc, chunk); 44 documents.add(document); 45 } 46 47 if (documents.size() >= 100) { 48 vectorStore.add(documents); 49 documents.clear(); 50 } 51 } 52 53 if (!documents.isEmpty()) { 54 vectorStore.add(documents); 55 } 56 57 return "All documents added successfully!"; 58 } catch (Exception e) { 59 return "Error while adding documents: " + e.getMessage(); 60 } 61 } 62 63 private Document createDocument(Map<String, Object> jsonMap, String content) { 64 Map<String, Object> metadata = (Map<String, Object>) jsonMap.get("metadata"); 65 metadata.putIfAbsent("sourceName", jsonMap.get("sourceName")); 66 metadata.putIfAbsent("url", jsonMap.get("url")); 67 68 return new Document(content, metadata); 69 } 70 71 private List<String> splitIntoChunks(String content, int maxTokens) { 72 List<String> chunks = new ArrayList<>(); 73 String[] words = content.split("\\s+"); 74 StringBuilder chunk = new StringBuilder(); 75 int tokenCount = 0; 76 77 for (String word : words) { 78 int wordTokens = word.length() / 4; 79 if (tokenCount + wordTokens > maxTokens) { 80 chunks.add(chunk.toString()); 81 chunk.setLength(0); 82 tokenCount = 0; 83 } 84 chunk.append(word).append(" "); 85 tokenCount += wordTokens; 86 } 87 88 if (chunk.length() > 0) { 89 chunks.add(chunk.toString()); 90 } 91 92 return chunks; 93 } 94 }
Esse serviço carregará nossos documentos de um arquivo JSON armazenado em um diretório chamado
docs
, em nossa pasta de recursos. Estamos usando o conjunto de dados MongoDB/devcenter- Articles sobre Abraçando a Face. Ele consiste em artigos e tutoriais do MongoDB Developer Center.Em seguida, ele dividirá nossos documentos maiores em pedaços menores (para acomodar os limites de token OpenAI) e armazenará esses documentos, com suas incorporações, no MongoDB Atlas.
Por fim, criaremos nosso controlador para lidar com nossas queries para carregar o conjunto de dados no banco de banco de dados (e gerar as incorporações) e para consultar os dados. Liberte todo o poder do nosso aplicação RAG interpretando nossas perguntas e gerando respostas, todas fornecidas por nosso próprio repositório de conhecimento personalizado. Isso soa dramático, mas é bem legal!
Crie um
RagController.java
arquivo para aceitar queries de usuários, recuperar documentos relevantes usando pesquisa vetorial e passá-los ao OpenAI para aprimoramento.1 import org.springframework.ai.chat.client.ChatClient; 2 import org.springframework.ai.chat.client.advisor.QuestionAnswerAdvisor; 3 import org.springframework.ai.vectorstore.SearchRequest; 4 import org.springframework.ai.vectorstore.VectorStore; 5 import org.springframework.web.bind.annotation.CrossOrigin; 6 import org.springframework.web.bind.annotation.GetMapping; 7 import org.springframework.web.bind.annotation.RequestParam; 8 import org.springframework.web.bind.annotation.RestController; 9 10 11 public class RagController { 12 private final ChatClient chatClient; 13 14 public RagController(ChatClient.Builder builder, VectorStore vectorStore) { 15 this.chatClient = builder 16 .defaultAdvisors(new QuestionAnswerAdvisor(vectorStore, SearchRequest.defaults())) 17 .build(); 18 } 19 20 21 public String question( String message) { 22 return chatClient.prompt() 23 .user(message) 24 .call() 25 .content(); 26 } 27 }
Aceitamos nossas queries de usuário por meio de um
/question
endpoint . Em seguida, nosso aplicativo usa a pesquisa vetorial para encontrar documentos relevantes do MongoDB e envia os referidos documentos para o OpenAI, para fornecer contexto adicional para as respostas, para gerar uma resposta aumentada.Use o
/api/docs/load
endpoint para carregar documentos no armazenamento de vetores MongoDB .1 curl http://localhost:8080/api/docs/load
Aqui temos uma opção ao configurar o índice de pesquisa vetorial para nosso aplicação. Podemos construí-lo programaticamente por meio
application.properties
de nosso arquivo ou defini-lo como parte de nossa infraestrutura como código (IaC) Terraform.Se quisermos que o índice seja inicializado como parte do processo de inicialização de nosso aplicativo, simplesmente definimos
initialize.schema
como true
em nosso application.properties
arquivo:1 spring.ai.vectorstore.mongodb.initialize-schema=true
Essa abordagem é útil quando queremos uma configuração rápida sem gerenciar ferramentas externas. É apropriado para desenvolvimento local ou aplicativos menores onde a infraestrutura não é tão complexa. Como tudo está contido no aplicativo, é simples e rápido modificar.
No entanto, se quisermos que nossa configuração de índice faça parte de nosso gerenciamento de infraestrutura, podemos usar o Terraform. Na parte inferior do nosso
main.tf
arquivo, adicionaremos o código para configurar e criar o índice como:1 resource "mongodbatlas_search_index" "vector_search" { 2 name = "search-index" 3 project_id = mongodbatlas_project.rag_project.id 4 cluster_name = mongodbatlas_advanced_cluster.rag_cluster.name 5 type = "vectorSearch" 6 database = "rag" 7 collection_name = "vector_store" 8 fields = <<-EOF 9 [{ 10 "type": "vector", 11 "path": "embedding", 12 "numDimensions": 1536, 13 "similarity": "cosine" 14 }] 15 EOF 16 }
Ao usar o Terraform, estamos aproveitando uma abordagem declarativa. Nossas alterações de infraestrutura são codificadas, versionadas e facilmente rastreáveis! Isso proporciona forte consistência entre ambientes, tornando-o ideal para casos de uso de produção ou sistemas maiores em que a infraestrutura é complexa, e a implantação automatizada e reproduzível é crucial.
Vamos aplicar nossas alterações agora:
1 terraform init 2 terraform apply
Então, qual é a nossa conclusão aqui?
- abordagem da API: muitas vezes mais rápida de configurar e modificar, mas não tem os benefícios de consistência e controle de versão que vêm com a automação da infraestrutura
- Terraform: Adiciona uma camada de confiabilidade, especialmente para produção, onde consistência e automação são essenciais
A abordagem correta depende do nosso caso de uso. Para projetos pequenos ou iterações rápidas, a infraestrutura de implantação diretamente por meio de APIs pode se ajustar como uma luva. Para aplicativos maiores de nível de produção, o Terraform geralmente é o caminho preferido.
Agora que temos documentos carregados, campos incorporados e índices criados, o que resta? Bem, vamos aprender um pouco sobre MongoDB.
Use o
/question
endpoint para recuperar documentos e gerar respostas aumentadas. Aqui, perguntaremos:1 curl http://localhost:8080/question?message=How%20to%20analyze%20time-series%20data%20with%20Python%20and%20MongoDB?
Este tutorial orienta você na criação de um aplicação Spring Boot RAG usando MongoDB Atlas, OpenAI e Terraform para gerenciar a infraestrutura. O aplicativo permite que os usuários façam perguntas, recuperem documentos relevantes usando pesquisa vetorial e gere respostas sensíveis ao contexto usando OpenAI, tudo isso usando o Terraform para obter os benefícios da infraestrutura como código.
Se este tutorial foi útil para você, confira nosso Centro de desenvolvedores do MongoDB , onde você pode saber mais sobre o que pode fazer com o Terraform e o MongoDB e aprender a fazer coisas como começar a usar o processamento de fluxo do MongoDB Atlas e o HashiCorp Terraform MongoDB Atlas Provider. Ou acesse os fóruns da comunidade MongoDB para fazer perguntas e ver o que outras pessoas estão construindo com o MongoDB.
O HashiCorp Terraform Atlas Provider é de código aberto sob a Licença Pública Mozilla v2.0 e agradecemos as contribuições da comunidade. Para saber mais, consulte nossas diretrizes de contribuição.
A maneira mais rápida de começar é criar uma conta do MongoDB Atlas no Amazon Web Amazon Web Services Services Marketplace, no GoogleGoogle Cloud Platform Cloud Platform Marketplace ou Azure no Azure Marketplace. Para saber mais sobre o fornecedor Terraform, consulte a documentação, o resumo da solução e os tutoriais, ou comece hoje mesmo.
Go Vá construir com o MongoDB Atlas e o Terraform HashiCorp hoje mesmo!
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.