Blog MNunes

Conectando sua Aplicação Node.js ao Gemini

Introdução

E aí, devs! 👋 Neste tutorial, vamos criar uma aplicação Node.js super simples que pega uma mensagem do usuário em uma página web e mandar essa mensagem para a API do Gemini do Google AI para obter uma resposta. Vamos juntos nessa jornada e aprender como configurar tudo, criar a interface web, implementar a lógica no Node.js para conversar com a API do Gemini e explorar alguns parâmetros importantes para controlar as respostas (texto e JSON).

Pré-requisitos:

  • Node.js e npm (ou yarn) instalados na sua máquina.
  • Uma conta no Google Cloud Platform com a API do Gemini ativada e uma chave de API gerada.
  • Se você ainda não tem uma chave:
    • Acesse https://ai.google.dev/gemini-api/docs/api-key e clique em “Get a Gemini API key in Google AI Studio“.
    • Na próxima tela clique em Criar chave de API.
    • Selecione um projeto do GCP ou crie um novo.
    • Gere sua chave e a copie.

Passo 1: Configurando o Projeto Node.js

Crie uma nova pasta para o seu projeto:

mkdir gemini-node-app
cd gemini-node-app

Inicialize um novo projeto Node.js:

npm init -y
# ou
yarn init -y

Instale as dependências necessárias:

npm install express dotenv @google/generative-ai body-parser
# ou
yarn add express dotenv @google/generative-ai body-parser

* express: Para criar o servidor web.
* dotenv: Para carregar variáveis de ambiente (como a chave da API).
* @google/generative-ai: A biblioteca oficial do Google AI para interagir com os modelos Gemini.
* body-parser: Para analisar o corpo das requisições HTTP.

Crie um arquivo .env na raiz do seu projeto e adicione sua chave de API do Gemini:

GEMINI_API_KEY=SUA_CHAVE_DE_API

Importante: Mantenha este arquivo seguro e não o compartilhe publicamente!

Passo 2: Criando a Interface Web (Frontend)

Crie uma pasta chamada public na raiz do seu projeto.

Dentro da pasta public, crie um arquivo index.html com o seguinte conteúdo:

<!DOCTYPE html>
<html>
<head>
    <title>Chat com Gemini</title>
</head>
<body>
    <h1>Pergunte ao Gemini</h1>
    <input type="text" id="userMessage" placeholder="Digite sua mensagem...">
    <button onclick="sendMessage()">Enviar</button>
    <div id="response"></div>

    <script>
        async function sendMessage() {
            const message = document.getElementById('userMessage').value;
            const responseDiv = document.getElementById('response');
            responseDiv.innerText = 'Carregando...';

            const response = await fetch('/ask', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ message }),
            });

            const data = await response.json();
            responseDiv.innerText = data.reply;
        }
    </script>
</body>
</html>

Este HTML cria um campo de texto para o usuário digitar sua mensagem, um botão para enviar e uma div para exibir a resposta do Gemini. A função sendMessage envia a mensagem para o servidor Node.js através de uma requisição POST para a rota /ask.

Passo 3: Implementando o Servidor Node.js (Backend)

Crie um arquivo chamado server.js na raiz do seu projeto com o seguinte código:

require('dotenv').config();
const express = require('express');
const { GenerativeModel, GoogleGenerativeAI } = require('@google/generative-ai');
const bodyParser = require('body-parser');
const path = require('path');

const app = express();
const port = 3000;

app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());

const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);

app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'public', 'index.html'));
});

app.post('/ask', async (req, res) => {
    const userMessage = req.body.message;
    const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flesh' });
    try {
        const result = await model.generateContent(userMessage);
        const responseText = result.response.candidates[0].content.parts[0].text;
        res.json({ reply: responseText });
    } catch (error) {
        console.error('Erro ao chamar a API do Gemini:', error);
        res.status(500).json({ error: 'Erro ao obter resposta do Gemini.' });
    }
});

app.listen(port, () => {
    console.log(`Servidor rodando em http://localhost:${port}`);
});

Este código faz o seguinte:

  • Carrega as variáveis de ambiente do arquivo .env.
  • Inicializa o Express e configura middlewares para servir arquivos estáticos da pasta public e analisar o corpo das requisições JSON.
  • Cria uma instância da API do Gemini usando a chave de API.
  • Define uma rota POST /ask que recebe a mensagem do usuário no corpo da requisição.
  • Utiliza o modelo gemini-2.0-flesh para gerar conteúdo com base na mensagem do usuário.
  • Envia a resposta do Gemini de volta para o cliente como um JSON.
  • Inicia o servidor na porta 3000.

Passo 4: Executando a Aplicação

  1. Abra o terminal na raiz do seu projeto.
  2. Execute o servidor Node.js:
node server.js
  1. Abra seu navegador e acesse http://localhost:3000. Você deverá ver a interface web simples.
  2. Digite uma mensagem no campo de texto e clique em “Enviar”. A resposta do Gemini será exibida abaixo do botão.

Explorando Parâmetros e Formatos de Resposta

A API do Gemini oferece diversos parâmetros que você pode ajustar para controlar a geração de respostas. Vamos explorar alguns deles e como você pode solicitar respostas em diferentes formatos. 🤓

Parâmetros Comuns

Ao utilizar o método getGenerativeModel, você pode passar um objeto de configuração no parâmetro generationConfig com opções como:

  • generationConfig: Define parâmetros para a geração de texto, como:
    • temperature: Controla a aleatoriedade da resposta. Valores mais baixos (e.g., 0.2) tornam a resposta mais determinística e focada, enquanto valores mais altos (e.g., 0.8) a tornam mais criativa e surpreendente. 🔥
    • topK: Considera apenas os k tokens mais prováveis para a próxima palavra. Isso ajuda a reduzir respostas fora do contexto. 🧐
    • topP: Considera o menor conjunto de tokens cuja probabilidade cumulativa seja pelo menos p. Isso também influencia a aleatoriedade da resposta. 🤔
    • maxOutputTokens: Define o número máximo de tokens na resposta gerada. 📏
  • safetySettings: Permite configurar filtros de segurança para diferentes categorias de conteúdo (e.g., conteúdo prejudicial, sexualmente explícito, etc.). ⚠️

Solicitando Respostas em Texto

No exemplo acima, já estamos recebendo a resposta em texto através de:

const responseText = result.response.candidates[0].content.parts[0].text;

Solicitando Respostas em JSON (Estruturadas)

Para solicitar respostas em formato JSON, você pode instruir o modelo Gemini a gerar a resposta seguindo uma estrutura JSON específica em sua pergunta.

Além disso, no parâmtro de generationConfig, passe reponse_mine_type como "application/json".

Exemplo de Prompt para Resposta em JSON:

Modifique a rota /ask no server.js para incluir um prompt que instrua o Gemini a responder em JSON:

app.post('/ask', async (req, res) => {
    const userMessage = req.body.message;
    const temperature = parseFloat(req.body.temperature);
    const structuredPrompt = `${userMessage}\n\nPor favor, responda formatando sua resposta como um objeto JSON com as chaves "resposta" (responsta completa), "resumo" (resposta curta) e "palavras_chave".`;
    const generationConfig = {
        temperature: temperature,
        response_mime_type: "application/json"
    };
    const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash', generationConfig: generationConfig});
    
    try {
        const result = await model.generateContent(structuredPrompt);
        
        const responseText = result.response.text();
        try {
            const jsonResponse = JSON.parse(responseText);
            res.json({ reply: jsonResponse });
        } catch (error) {
            console.warn('A resposta não pôde ser retornada como JSON:', responseText);
            res.json({ reply: responseText });
        }
    } catch (error) {
        console.error('Erro ao chamar a API do Gemini:', error);
        res.status(500).json({ error: 'Erro ao obter resposta do Gemini.' });
    }
});

No frontend (public/index.html), você precisará ajustar a forma como a resposta é exibida, pois agora ela pode ser um objeto JSON:

// ... dentro da função sendMessage ...
const data = await response.json();
if (typeof data.reply === 'object') {
   let keywords = data.reply.palavras_chave;
   let keywordsString = keywords.join ? keywords.join(', ') : keywords.toString();
   responseDiv.innerHTML = `
                    <p><strong>Responsta:</strong> ${data.reply.resposta}</p>
                    <p><strong>Resumo:</strong> ${data.reply.resumo}</p>
                    <p><strong>Palavras-chave:</strong> ${data.reply.palavras_chave}</p>
                `;
} else {
  responseDiv.innerText = data.reply 
}           }

Explorando generationConfig

Vamos adicionar a possibilidade de configurar a temperatura na requisição do frontend. 🔥

Modifique o index.html: Adicione um controle deslizante para a temperatura:

<!DOCTYPE html>
<html>

<head>
    <title>Chat com Gemini</title>
    <style>
        #controls {
            margin-top: 10px;
        }
    </style>
</head>

<body>
    <h1>Pergunte ao Gemini</h1>
    <input type="text" id="userMessage" placeholder="Digite sua mensagem...">
    <div id="controls">
        <label for="temperature">Temperatura:</label>
        <input type="range" id="temperature" min="0" max="1" step="0.1" value="0.5">
        <span id="temperatureValue">0.5</span>
    </div>
    <button onclick="sendMessage()">Enviar</button>
    <div id="response"></div>

    <script>
        const temperatureSlider = document.getElementById('temperature');
        const temperatureValueSpan = document.getElementById('temperatureValue');

        temperatureSlider.addEventListener('input', () => {
            temperatureValueSpan.innerText = temperatureSlider.value;
        });

        async function sendMessage() {
            const message = document.getElementById('userMessage').value;
            const temperature = parseFloat(document.getElementById('temperature').value);
            const responseDiv = document.getElementById('response');
            responseDiv.innerText = 'Carregando...';

            const response = await fetch('/ask', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({ message, temperature }),
            });

            const data = await response.json();
            if (typeof data.reply === 'object') {
                let keywords = data.reply.palavras_chave;
                let keywordsString = keywords.join ? keywords.join(', ') : keywords.toString();

                responseDiv.innerHTML = `
                    <p><strong>Responsta:</strong> ${data.reply.resposta}</p>
                    <p><strong>Resumo:</strong> ${data.reply.resumo}</p>
                    <p><strong>Palavras-chave:</strong> ${data.reply.palavras_chave}</p>
                `;
            } else {
                responseDiv.innerText = data.reply;
            }
        }
    </script>
</body>

</html>

Modifique o server.js: Receba o parâmetro de temperatura e passe-o para generationConfig:

app.post('/ask', async (req, res) => {
    const userMessage = req.body.message;
    const temperature = parseFloat(req.body.temperature);
    const structuredPrompt = `${userMessage}\n\nPor favor, responda formatando sua resposta como um objeto JSON com as chaves "resposta" (responsta completa), "resumo" (resposta curta) e "palavras_chave".`;
    const generationConfig = {
        temperature: temperature,
        response_mime_type: "application/json"
    };
    const model = genAI.getGenerativeModel({ model: 'gemini-2.0-flash', generationConfig: generationConfig});
    
    try {
        const result = await model.generateContent(structuredPrompt);
        
        const responseText = result.response.text();
        try {
            const jsonResponse = JSON.parse(responseText);
            res.json({ reply: jsonResponse });
        } catch (error) {
            console.warn('A resposta não pôde ser retornada como JSON:', responseText);
            res.json({ reply: responseText });
        }
    } catch (error) {
        console.error('Erro ao chamar a API do Gemini:', error);
        res.status(500).json({ error: 'Erro ao obter resposta do Gemini.' });
    }
});

Agora, você pode ajustar o controle deslizante de temperatura na página web para observar como ele influencia a aleatoriedade e a criatividade das respostas do Gemini.

Conclusão

Este tutorial demonstrou como criar uma aplicação Node.js simples para se comunicar com a API do Gemini, receber mensagens do usuário através de uma interface web e exibir as respostas. Exploramos como instruir o modelo a fornecer respostas em formato JSON através do prompt e como utilizar o parâmetro temperature para controlar a geração de texto.

Links úteis

Documentação Gemini API: https://ai.google.dev/api?lang=node

Repositório desse Projeto: https://github.com/marcosnunesmbs/gemini-node-tutorial