DEV Community

Cover image for Criando um Chatbot com JavaScript e Gemini AI
Neilton Seguins
Neilton Seguins

Posted on

Criando um Chatbot com JavaScript e Gemini AI

E aí, tudo bom?

Eu estava olhando alguns projetos no meu github e me deparei com um chatbot que criei recentemente usando o Google Gemini. A ideia era criar um assistente de idiomas, onde você conseguisse conversar com a IA para aprimorar suas habilidades no idioma que quisesse.

Então pensei: " Porque não compartilhar como eu fiz este projeto com todo mundo? ". E é por isso que estou escrevendo aqui, para te mostrar como fiz cada parte. Então vamos começar pelo front-end da aplicação.

Iniciando um novo projeto

Bom, para justificar algumas ações que vou tomar no projeto vou logo adiantando que iremos criar um "servidor" com express.js, onde forneceremos uma rota de api '/chat' que servirá para a comunicação entre o front-end e a API do Gemini.

Então, precisaremos iniciar nosso projeto com o comando npm init -y. O resultado é um arquivo package.json mais ou menos com essa cara:

{
  "name": "chatbot-ia",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}
Enter fullscreen mode Exit fullscreen mode

E também, vamos precisar organizar nossos arquivos da seguinte forma:

public
  |__ index.html
  |__ style.css
  |__ script.js
package.json 
Enter fullscreen mode Exit fullscreen mode

Feito isso, vamos criar a parte visual do nosso chatbot. Vamos lá!

Criando o visual do Chat

Como a ideia era fazer um projeto para um live coding de 1h, resolvi criar uma interface bem simples usando HTML, CSS e JavaScript para o Chatbot. Sou bem ruim com design, então a fonte e as cores eu escolhi as que mais gosto. Então vamos lá, começando pelo HTML.

<!DOCTYPE html>
<html lang="pt-br">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Chatbot Assistente de Idiomas</title>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Roboto&display=swap"
      rel="stylesheet"
    />
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div class="chat-container">
      <div id="chat-window" class="chat-box">
        <!-- As mensagens vão aparecer aqui -->
      </div>
      <div class="input-container">
        <form id="chat-form" class="chat-form">
          <input
            type="text"
            id="user-input"
            placeholder="Digite sua mensagem..."
            autocomplete="off"
            required
          />
          <button id="send-button" type="submit">Enviar</button>
        </form>
      </div>
    </div>

    <script src="script.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

E agora o CSS da página

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: "Roboto", sans-serif;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  background-color: #f2f2f2;
}

.chat-container {
  width: 100%;
  max-width: 400px;
  background-color: #fff;
  border-radius: 10px;
  box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.chat-box {
  height: 300px;
  max-height: 500px;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
}

.chat-form {
  width: 100%;
  display: flex;
  justify-content: space-between;
}

.message {
  padding: 10px;
  margin-bottom: 8px;
  border-radius: 20px;
  width: auto;
  display: inline-flex;
  max-width: 50%;
  word-wrap: break-word;
}

.model {
  background-color: #e0e0e0;
  color: #333;
  align-self: flex-start;
  justify-content: flex-start;
}

.user {
  background-color: #4caf50;
  color: white;
  align-self: flex-end;
  justify-content: flex-end;
  margin-left: auto;
}

.input-container {
  display: flex;
  padding: 10px;
  border-top: 1px solid #ddd;
}

#user-input {
  flex: 1;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 20px;
  outline: none;
}

#send-button {
  margin-left: 10px;
  padding: 10px 15px;
  background-color: #4caf50;
  color: white;
  border: none;
  border-radius: 20px;
  cursor: pointer;
}

#send-button:hover {
  background-color: #45a049;
}
Enter fullscreen mode Exit fullscreen mode

O resultado disso deve ser uma tela parecida com a mostrada abaixo:

alt: Interface de chat com uma área em branco para mensagens, campo de texto com o placeholder

Criando a lógica do cliente

Nossa aplicação é um chatbot que irá se comunicar com a API do Gemini. Então, precisamos criar a lógica que irá fazer essa comunicação. Para ficar claro o que devemos fazer, vou listar abaixo:

  • Pegar o que for digitado pelo usuário
  • Fazer uma requisição POST para a rota '/chat' que iremos criar
  • Exibir a mensagem do usuário e do modelo (a IA) na tela do chat

Então vamos lá, primeiro vamos adicionar um ouvinte de eventos para executar nossa lógica apenas depois que o conteúdo do DOM for totalmente carregado:

// script.js
document.addEventListener("DOMContentLoaded", () => {
  const chatForm = document.getElementById("chat-form");
  const chatWindow = document.getElementById("chat-window");
  const userInput = document.getElementById("user-input");

  // ...
});
Enter fullscreen mode Exit fullscreen mode

Criamos constantes para pegar os elementos que nos interessam, como o input onde o usuário digita, a janela onde irão aparecer as mensagens e o campo do formulário, pois vamos escutar quando ele for submetido e aí sim executar nossa lógica.

Continuando, vamos para o segundo passo que é fazer a requisição para a rota que criaremos enviando a mensagem do usuário.

chatForm.addEventListener("submit", async (e) => {
    e.preventDefault();

    const userMessage = userInput.value.trim();
    if (!userMessage) return;

    addMessage("user", userMessage);

    try {
      const modelResponse = await fetch("/chat", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ message: userMessage }),
      });

      const data = await modelResponse.json();
      if (data && data.response) {
        addMessage("model", data.response);
      } else {
        addMessage("model", "Erro: Resposta inválida do modelo.");
      }
    } catch (err) {
      console.error(err);
      addMessage("model", "Erro: Não foi possível processar sua mensagem.");
    }

    userInput.value = "";
});
Enter fullscreen mode Exit fullscreen mode

Neste código, estamos escutando o evento de submit no elemento de formulário. Então, de início usamos o preventDefault para evitar que a página faça reload sempre que enviarmos uma mensagem. Depois pegamos o que o usuário digitou, removendo os espaços em branco da mensagem, do início e fim com o trim() e verificamos se a mensagem não é vazia, em branco. Se a mensagem for vazia a gente para nosso processo aí mesmo.

Agora, se tivermos a mensagem do usuário, exibimos ela na tela usando a função addMessage(). Esta função é definida da seguinte forma:

  function addMessage(role, text) {
    const messageDiv = document.createElement("div");
    messageDiv.className = `message ${role}`;
    messageDiv.textContent = text;
    chatWindow.appendChild(messageDiv);
    chatWindow.scrollTop = chatWindow.scrollHeight; 
  }
Enter fullscreen mode Exit fullscreen mode

Basicamente ela recebe quem enviou a mensagem e o texto da mensagem e exibe essa informação no chat, adicionando os estilos corretos do usuário e do model, o modelo de IA.

Beleza, agora voltando para a lógica da nossa requisição se tivermos uma mensagem do usuário precisamos fazer uma requisição POST usando o fetch API, e o corpo dessa requisição é a mensagem do usuário.

Por fim, se tivermos uma resposta dessa requisição iremos exibir a mensagem do modelo no chat. Caso contrário, pegamos o erro e exibimos no console, com o console.error() ou exibimos uma mensagem no próprio chat de forma customizada. E para melhorar a usabilidade do chat, limpamos o input de mensagem do usuário com o userInput.value = "";.

O arquivo script.js fica com essa cara:

// script.js
document.addEventListener("DOMContentLoaded", () => {
  const chatForm = document.getElementById("chat-form");
  const chatWindow = document.getElementById("chat-window");
  const userInput = document.getElementById("user-input");

  chatForm.addEventListener("submit", async (e) => {
    e.preventDefault();

    const userMessage = userInput.value.trim();
    if (!userMessage) return;

    addMessage("user", userMessage);

    try {
      const modelResponse = await fetch("/chat", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ message: userMessage }),
      });

      const data = await modelResponse.json();
      if (data && data.response) {
        addMessage("model", data.response);
      } else {
        addMessage("model", "Erro: Resposta inválida do modelo.");
      }
    } catch (err) {
      console.error(err);
      addMessage("model", "Erro: Não foi possível processar sua mensagem.");
    }

    userInput.value = "";
  });

  function addMessage(role, text) {
    const messageDiv = document.createElement("div");
    messageDiv.className = `message ${role}`;
    messageDiv.textContent = text;
    chatWindow.appendChild(messageDiv);
    chatWindow.scrollTop = chatWindow.scrollHeight;
  }
});
Enter fullscreen mode Exit fullscreen mode

E com isso a gente finaliza a parte do front-end do chatbot. O próximo passo será criar o nosso "servidor", realizar a comunicação com a API do Gemini e conversar com ele sobre a vida, o universo e tudo mais!

Até uma próxima!

Top comments (1)

Collapse
 
sucodelarangela profile image
Angela Caldas

Boa! No aguardo da parte 2!