Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Saiba por que o MongoDB foi selecionado como um líder no 2024 Gartner_Magic Quadrupnt()
Desenvolvedor do MongoDB
Centro de desenvolvedores do MongoDB
chevron-right
Produtos
chevron-right
Atlas
chevron-right

Além do básico: aprimorando a API Kotlin Ktor com pesquisa vetorial

Ricardo Mello8 min read • Published Sep 18, 2024 • Updated Sep 18, 2024
IAPesquisa vetorialKotlinAtlas
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Neste artigo, abordaremos técnicas avançadas do MongoDB em conjunto com a API Kotlin Ktor, desenvolvendo sobre a base estabelecida em nosso artigo anterior, Mestre emKotlin: Criando uma API com Ktor e MongoDB Atlas. Nosso foco será a integração de funcionalidades robustas, como o Abraçar o Face, o Vector Search e as Atlas Triggers para aumentar a funcionalidade e o desempenho da nossa API.
Começaremos fornecendo uma visão geral dessas técnicas avançadas do MongoDB e seu papel crítico no desenvolvimento de API atual. Posteriormente, abordaremos implementações práticas, mostrando como você pode integrar perfeitamente o Hugging Face para o processamento de linguagem natural, aproveitar o Vector Atlas Search para recuperação rápida de dados e automatizar processos de banco de dados usando as funções e os gatilhos do Atlas.

Pré-requisitos

Demonstração

Começaremos importando um conjunto de dados de exercícios de preparação física para o MongoDB Atlas como documentos. Em seguida, criaremos um trigger que será ativado após a inserção. Para cada documento no conjunto de dados, uma função será invocada para solicitar a API do Hugging Face. Esta função enviará a descrição do exercício para conversão em uma matriz incorporada, que será salva na coleção de exercícios como descEmbedding :
Arquitetura de aplicativo Atlas
Na segunda parte, modificaremos o aplicativo Kotlin Ktor para incorporar chamadas de clientes HTTP, permitindo a interação com a API Hugging Face. Além disso, criaremos um endpoint /exercises/processRequest. Esse endpoint aceitará uma entrada de texto, que será processada usando a API Hugging Face para gerar uma matriz incorporada. Posteriormente, compararemos essa array com o descEmbedding gerado na primeira parte. Utilizando a pesquisa vetorial, retornaremos os três resultados mais próximos (neste caso, os exercícios de condicionamento físico mais relevantes para minha pesquisa):
Arquitetura do aplicativo Kotlin

Configuração do MongoDB e integração do face do Abraço

1. Criando a coleção de exercícios

A primeira etapa para atingir nosso objetivo é criar uma coleção vazia chamada "exercícios" que posteriormente armazenará nosso conjunto de dados. Comece fazendo login em sua conta MongoDB Atlas . No dashboard do Atlas , navegue até seu cluster e selecione o banco de dados de dados onde você deseja criar a coleção. Clique na aba "Coleções" para gerenciar suas coleções dentro desse banco de dados de dados e criar uma coleção de exercícios vazia:
Criando a coleção de exercícios

2. Criação de um gatilho e função

Em seguida, precisamos criar um trigger que será ativado sempre que um novo documento for inserido na coleção de exercícios. Navegue até a aba Triggers e crie um trigger chamado "Trigger_Exercises" como mostrado nas imagens abaixo:
Criando exercícios de gatilho
Lembre-se de escolher a coleção " exercises ", selecionar " Inserir documento " para o tipo de operação e ativar " Documento completo.”
Criando exercícios de gatilho
Por fim, cole o seguinte código de função no campo "Função" e clique em "Salvar":
1exports = async function(changeEvent) {
2 const doc = changeEvent.fullDocument;
3
4 const url = 'https://api-inference.huggingface.co/pipeline/feature-extraction/sentence-transformers/all-MiniLM-L6-v2';
5 const hf_key = context.values.get("HF_value");
6 try {
7 console.log(`Processing document with id: ${doc._id}`);
8
9 let response = await context.http.post({
10 url: url,
11 headers: {
12 'Authorization': [`Bearer ${hf_key}`],
13 'Content-Type': ['application/json']
14 },
15
16 body: JSON.stringify({
17 inputs: [doc.description]
18 })
19 });
20
21 let responseData = EJSON.parse(response.body.text());
22
23 if(response.statusCode === 200) {
24 console.log("Successfully received embedding.");
25
26 const embedding = responseData[0];
27
28 const collection = context.services.get("Cluster0").db("my_database").collection("exercises");
29
30 const result = await collection.updateOne(
31 { _id: doc._id },
32 { $set: { descEmbedding: embedding }}
33 );
34
35 if(result.modifiedCount === 1) {
36 console.log("Successfully updated the document.");
37 } else {
38 console.log("Failed to update the document.");
39 }
40 } else {
41 console.log(`Failed to receive embedding. Status code: ${response.statusCode} plus ${response}`);
42 }
43
44 } catch(err) {
45 console.error(err);
46 }
47};
Criando a função exercises
Essa função serve como uma ponte entre o MongoDB e a API Hugging Face, aprimorando documentos armazenados em uma coleção do MongoDB com incorporações geradas pela API. A função é acionada por um evento de alteração na coleção MongoDB, especificamente quando um novo documento é inserido ou um documento existente é atualizado.
Agora, vamos explorar a funcionalidade desta função:
  1. Tratamento de eventos: a função extrai o documento completo do evento de alteração do MongoDB para ser processado.
  2. Interação com a APIAbraçando Face : ela interage com a API Abraçando Face para obter uma incorporação para a descrição do documento. Isso envolve o envio de uma solicitação HTTP POST para o endpoint de extração de recursos da API, com a descrição do documento como entrada.
  3. Atualização do MongoDB : ao receber uma resposta bem-sucedida da API Abraçando Faces, a função atualiza o documento na coleção MongoDB com a incorporação extraída. Isso Enriquece o documento com informações adicionais úteis para várias tarefas de processamento de linguagem natural.

3. Renomear a função

Para alinhar nosso ambiente com a imagem de demonstração, vamos mudar o nome da nossa função para Function_Exercises. Para fazer isso, acesse o menu "Funções" e edite a função:
Selecionando trigger de serviço de aplicativo
Criando um gatilho para novos exercícios
Em seguida, digite o novo nome e clique em “Save:
Renomear função

4. Obtendo o token de acesso Hugging Face

A função que criamos anteriormente requer um token para acessar o Hugging Face. Precisamos obtê-lo e configurá-lo no Atlas. Para fazer isso, faça login na sua conta Hugging Face e acesse as configurações para criar sua chave:
Obter token de face de Abraço
Depois de copiar sua chave, vamos retornar ao MongoDB Atlas e configurar nossa chave para acesso. Clique no botão "Valores" no menu lateral e selecione "Create New Value":
Criando novos valores de aplicativo
Agora, precisamos criar um segredo e um valor que será associado a este segredo.
Primeiro, crie o segredo inserindo a chave a partir do Abraço do Face:
Criando segredo do aplicativo
Em seguida, crie um valor chamado HF_value (que será usado em nossa função) e associe-o ao segredo, como mostra a imagem:
Criando valor do aplicativo
Se tudo tiver corrido perfeitamente, nossos valores ficarão assim:
Lista de Valores do Aplicativo
Terminamos de configurar nosso ambiente. Para recapitular:
Criando a coleção vazia:
  • Criamos uma coleção vazia denominada "exercícios" no MongoDB Atlas. Esta coleção receberá dados de entrada, acionando um processo para converter a descrição dos exercícios em valores incorporados.
Configurar triggers e funções:
  • Um trigger chamado "Trigger_Exercises" foi criado para ser ativado após a inserção do documento.
  • O trigger chama uma função chamada "Function_Exercises" para cada documento inserido.
  • A função processa a descrição usando a API Hugging Face para gerar valores incorporados, que são então adicionados à collection " exercises ".
Configuração final:
  • Para concluir a configuração, associamos um segredo e um valor à chave Abraçando a face no MongoDB Atlas.

5. Importando um conjunto de dados

Nesta etapa, importaremos um conjunto de dados de documentos 50 contendo informações sobre exercícios:
Amostra de documento de exercícios
Para atingir esse objetivo, usarei asferramentas do MongoDB para importar o arquivoconcerns.json por meio da linha de comando. Após instalar o MongoDB Tools, basta colar o arquivo "exercises.json" na pasta "bin" e executar o comando, conforme mostrado na imagem abaixo:
Importação de ferramentas do Mongo
1 .\mongoimport mongodb+srv://<user>:<password>@cluster0.xpto.mongodb.net/my_database --collection exercises --jsonArray .\exercises.json
Aviso: lembre-se de alterar seu usuário, senha e cluster.
Se tudo correr bem, veremos que importamos os exercícios 50.
Conjunto de dados importado com sucesso
Agora, vamos verificar os registros de nossa função para garantir que tudo correu bem. Para fazer isso, navegue até a aba "App Services" e clique em "Logs":
Verificando logs de App Services
E agora, vamos ver nossa coleção:
Collection de exercícios com dados incorporados
Como podemos ver, transformamos as descrições dos exercícios 50 em valores vetoriais e os atribuímos ao campo "descEmbedding".
Vamos prosseguir com as alterações em nosso aplicação Kotlin . Se ainda não fez isso, você pode baixar o aplicação. Nosso objetivo é criar um endpoint /processRequest para enviar uma entrada para o HuggingFace, como:
"Precisode um exercício para os meus quadris e para perder a gordu ras da abdome."
Expressão final do Postman
Converteremos essas informações em dadosincorporados e utilizaremos o Vector Search para retornar os três exercícios que mais se aproximam dessa entrada. Para começar, vamos incluir duas dependências no arquivo build.gradle.kts que nos permitirão fazer chamadas HTTP para Abraçar o Face:
build.gradle.kts
1//Client
2implementation("io.ktor:ktor-client-core:$ktor_version")
3implementation("io.ktor:ktor-client-cio:$ktor_version")
No pacoteports, criaremos um repositório que recuperará exercícios do banco de dados:
domain/ports/ExercisesRepository
1package com.mongodb.domain.ports
2
3import com.mongodb.domain.entity.Exercises
4
5interface ExercisesRepository {
6 suspend fun findSimilarExercises(embedding: List<Double>): List<Exercises>
7}
Criaremos uma resposta para exibir algumas informações ao usuário:
application/response/ExercisesResponse
1package com.mongodb.application.response
2data class ExercisesResponse(
3 val exerciseNumber: Int,
4 val bodyPart: String,
5 val type: String,
6 val description: String,
7 val title: String
8)
Agora, crie a classeExercícios:
domínio/entidade/Exercícios
1package com.mongodb.domain.entity
2
3
4import com.mongodb.application.response.ExercisesResponse
5import org.bson.codecs.pojo.annotations.BsonId
6import org.bson.types.ObjectId
7
8
9data class Exercises(
10 @BsonId
11 val id: ObjectId,
12 val exerciseNumber: Int,
13 val title: String,
14 val description: String,
15 val type: String,
16 val bodyPart: String,
17 val equipment: String,
18 val level: String,
19 val rating: Double,
20 val ratingDesc: String,
21 val descEmbedding: List<Double>
22){
23 fun toResponse() = ExercisesResponse(
24 exerciseNumber = exerciseNumber,
25 title = title,
26 description = description,
27 bodyPart = bodyPart,
28 type = type
29 )
30}
Em seguida, implementaremos nossa interface que se comunicará com o banco de dados de dados executando uma query agregada usando a pesquisa vetorial que criaremos posteriormente.
infrastructure/ExercisesRepositoryImpl
1package com.mongodb.infrastructure
2
3import com.mongodb.domain.entity.Exercises
4import com.mongodb.domain.ports.ExercisesRepository
5import com.mongodb.kotlin.client.coroutine.MongoDatabase
6import kotlinx.coroutines.flow.toList
7import org.bson.Document
8
9class ExercisesRepositoryImpl(
10 private val mongoDatabase: MongoDatabase
11) : ExercisesRepository {
12
13 companion object {
14 const val EXERCISES_COLLECTION = "exercises"
15 }
16
17 override suspend fun findSimilarExercises(embedding: List<Double>): List<Exercises> {
18 val result =
19 mongoDatabase.getCollection<Exercises>(EXERCISES_COLLECTION).withDocumentClass<Exercises>().aggregate(
20 listOf(
21 Document(
22 "\$vectorSearch",
23 Document("queryVector", embedding)
24 .append("path", "descEmbedding")
25 .append("numCandidates", 3L)
26 .append("index", "vector_index")
27 .append("limit", 3L)
28 )
29 )
30 )
31
32 return result.toList()
33 }
34}
Agora, vamos criar nosso endpoint para acessar o Hugging Face e chamar o método criado anteriormente:
application/routes/ExercisesRoutes (aplicativos/rotas/ExercíciosRotas)
1package com.mongodb.application.routes
2
3import com.mongodb.application.request.SentenceRequest
4import com.mongodb.domain.ports.ExercisesRepository
5import com.mongodb.huggingFaceApiUrl
6import io.ktor.client.*
7import io.ktor.client.call.*
8import io.ktor.client.engine.cio.*
9import io.ktor.client.request.*
10import io.ktor.client.statement.*
11import io.ktor.http.*
12import io.ktor.http.content.*
13import io.ktor.server.application.*
14import io.ktor.server.request.*
15import io.ktor.server.response.*
16import io.ktor.server.routing.*
17import org.koin.ktor.ext.inject
18
19fun Route.exercisesRoutes() {
20 val repository by inject<ExercisesRepository>()
21
22 route("/exercises/processRequest") {
23 post {
24 val sentence = call.receive<SentenceRequest>()
25
26 val response = requestSentenceTransform(sentence.input, call.huggingFaceApiUrl())
27
28 if (response.status.isSuccess()) {
29 val embedding = sentence.convertResponse(response.body())
30 val similarDocuments = repository.findSimilarExercises(embedding)
31
32 call.respond(HttpStatusCode.Accepted, similarDocuments.map { it.toResponse() })
33 }
34 }
35 }
36}
37
38suspend fun requestSentenceTransform(input: String, huggingFaceURL: String): HttpResponse {
39
40 println(huggingFaceURL)
41
42 return HttpClient(CIO).use { client ->
43
44 val response = client.post(huggingFaceURL) {
45 val content = TextContent(input, ContentType.Text.Plain)
46 setBody(content)
47 }
48
49 response
50 }
51}
Em seguida, vamos criar a solicitação que enviaremos para Abraçando a face. Nesta classe, além da entrada, temos um conversor para converter o retorno de String para Double:
application/request/SentenceRequest
1package com.mongodb.application.request
2
3data class SentenceRequest(
4 val input: String
5)
6{
7 fun convertResponse(body: String) =
8 body
9 .replace("[", "")
10 .replace("]", "")
11 .split(",")
12 .map { it.trim().toDouble() }
13}
Vamos incluir a rota criada anteriormente e um métodohuggingFaceApiUrl em nossa classe Aplicativo. Aqui está o código completo:
Application.kt
1package com.mongodb
2
3import com.mongodb.application.routes.exercisesRoutes
4import com.mongodb.application.routes.fitnessRoutes
5import com.mongodb.domain.ports.ExercisesRepository
6import com.mongodb.domain.ports.FitnessRepository
7import com.mongodb.infrastructure.ExercisesRepositoryImpl
8import com.mongodb.infrastructure.FitnessRepositoryImpl
9import com.mongodb.kotlin.client.coroutine.MongoClient
10import io.ktor.serialization.gson.*
11import io.ktor.server.application.*
12import io.ktor.server.plugins.contentnegotiation.*
13import io.ktor.server.plugins.swagger.*
14import io.ktor.server.routing.*
15import io.ktor.server.tomcat.*
16import org.koin.dsl.module
17import org.koin.ktor.plugin.Koin
18import org.koin.logger.slf4jLogger
19
20fun main(args: Array<String>): Unit = EngineMain.main(args)
21fun Application.module() {
22
23 install(ContentNegotiation) {
24 gson {
25 }
26 }
27
28 // Other code..
29
30 routing {
31 // Other code..
32
33 exercisesRoutes()
34 }
35}
36
37fun ApplicationCall.huggingFaceApiUrl(): String {
38 return application.environment.config.propertyOrNull("ktor.huggingface.api.url")?.getString()
39 ?: throw RuntimeException("Failed to access Hugging Face API base URL.")
40
41}
Por fim, vamos incluir o ponto de extremidade do Hugging Face no arquivo application.conf.
application.conf
1ktor {
2
3 // Other code ..
4
5 huggingface {
6 api {
7 url = "https://api-inference.huggingface.co/pipeline/feature-extraction/sentence-transformers/all-MiniLM-L6-v2"
8 }
9 }
10}
Agora, precisamos Go ao Atlas e criar nosso índice de pesquisa vetorial. Acompanhe as imagens abaixo:
Criando um novo índice do Atlas Search.
Selecione o Atlas Vector Search:
Criando novo índice do Atlas Vector Search
Criando novo índice do Atlas Vector Search
Se estiver tudo bem, você verá uma mensagem de sucesso como a abaixo, indicando que o índice foi criado com sucesso no MongoDB Atlas:
Criando novo índice do Atlas Vector Search
Este trecho de código define um índice vetorial no campo descEmbedding em nossa collection de exercícios. O campo de tipo especifica que este é um índice de vetor. O campo de caminho indica o caminho para o campo que contém os dados do vetor. Neste caso, estamos usando o campo descEmbedding. O campo numDimensions especifica o número de dimensões
dos vetores, que é 384 neste caso. Por fim, o campo de similaridade especifica a métrica de similaridade a ser usada para comparar vetores, que é a distância euclidiana.
1{
2 "fields": [
3 {
4 "type": "vector",
5 "path": "descEmbedding",
6 "numDimensions": 384,
7 "similarity": "euclidean"
8 }
9 ]
10}
Depois de implementar as atualizações e configurações mais recentes, é hora de testar o aplicativo. Vamos começar executando o aplicativo. Abra o Application.kt e clique no botão Executar:
Executando o aplicativo
Quando o aplicativo estiver instalado e funcionando, você poderá prosseguir com o teste usando o seguinte comando curl:
1curl --location 'http://localhost:8081/exercises/processRequest' \
2--header 'Content-Type: application/json' \
3--data '{
4 "input": "I need an exercise for my shoulders and to lose my belly fat"
5}'
Solicitando processRequest em

Conclusão

Este artigo mostrou como enriquecer documentos do MongoDB com incorporações da API Hugging Face, aproveitando seus poderosos recursos de processamento de linguagem natural. A função fornecida demonstra o tratamento de eventos de mudança em uma coleção do MongoDB e a interação com uma API externa. Essa integração oferece aos desenvolvedores oportunidades de aprimorar seus aplicativos com recursos de NLP, destacando o potencial de combinar tecnologias para aplicativos mais inteligentes.
O código-fonte de exemplo está disponível no GitHub.
Se você tiver alguma dúvida ou quiser discutir outras implementações, fique à vontade para entrar em contato com o fórum dacomunidade de desenvolvedores do MongoDB para obter suporte e orientação.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Iniciar a conversa

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Tutorial

RAG interativo com MongoDB Atlas + API de chamada de função


Sep 18, 2024 | 16 min read
Artigo

AI Shop: o poder da LangChain, OpenAI e MongoDB Atlas trabalhando juntos


Sep 18, 2024 | 7 min read
Artigo

Crie um site de boletim informativo com a plataforma de dados MongoDB


Sep 09, 2024 | 9 min read
Tutorial

Como automatizar a cópia contínua de dados do MongoDB para o S3


Jan 23, 2024 | 8 min read
Sumário