Trata-se de um chat em tempo real com a Inteligência Artificial da OpenAI ChatGPT 3.5. Nele, é possível cadastrar um novo usuário, realizar o login, criar novas conversas, conversar com o ChatGPT, visualizar e remover conversas do histórico de conversas, também como acessá-las do ponto em que parou
Para a realização desse projeto, foi utilizada a ferramenta da OpenAI, que nos permite integrar seus produtos de Inteligência Artificial aos nossos projetos.
- Licença
- Tecnologias utilizadas
- Instruções para rodar o projeto
- Demonstração
- Rotas e autenticação
- Testes
- Banco de dados
- Infra
Este projeto está sob licença do MIT
- ReactJS: Uma biblioteca JavaScript de código aberto utilizada para construir interfaces de usuário (UI). Desenvolvida pelo Facebook, ela é baseada em componentes reutilizáveis, permitindo a construção de interfaces dinâmicas e interativas de forma eficiente.
- TypeScript: Um superconjunto de JavaScript que adiciona tipagem estática opcional ao código. Ele ajuda os desenvolvedores a detectar erros mais cedo durante o desenvolvimento e oferece ferramentas avançadas para trabalhar em projetos de grande escala, melhorando a manutenibilidade e escalabilidade do código.
- Styled Components: Uma biblioteca para React e React Native que permite escrever estilos CSS diretamente dentro de componentes JavaScript. Isso facilita a criação e o gerenciamento de estilos, além de fornecer recursos como props dinâmicas e escopo encapsulado para estilos.
- Axios: Uma biblioteca JavaScript para fazer requisições HTTP a partir do navegador ou Node.js. Ele fornece uma API simples e concisa para lidar com solicitações e respostas HTTP, suportando várias funcionalidades, como interceptadores, cancelamento de requisições e transformações de dados.
- Vite: Um construtor de aplicações web moderno e rápido, desenvolvido principalmente para projetos usando Vue.js, mas também é compatível com outras estruturas como React e Svelte. Ele oferece um ambiente de desenvolvimento extremamente rápido e eficiente, com recarga rápida (hot module replacement) e suporte a módulos ES.
- React Icons: Uma biblioteca que fornece um conjunto de ícones populares para serem usados em aplicações React. Ela simplifica a inclusão de ícones vetoriais em projetos React, oferecendo uma ampla variedade de ícones e estilos prontos para uso.
- React Spinners: Uma biblioteca React que fornece componentes para exibir indicadores de carregamento (spinners) em aplicações web. Ela oferece uma variedade de estilos e opções de personalização para spinners, facilitando a inclusão de feedback visual de carregamento em interfaces de usuário.
- React Query: Uma biblioteca para gerenciamento de dados em aplicações React. Ela simplifica o gerenciamento de dados assíncronos, como solicitações HTTP, cache de dados e atualizações em tempo real, fornecendo uma API simples e intuitiva para lidar com esses cenários comuns no desenvolvimento de aplicações web.
- Node.js: Plataforma de desenvolvimento para construção do ambiente de servidor.
- NestJS: Framework web para Node.js utilizado na construção da API.
- TypeORM: ORM (Object-Relational Mapping) para TypeScript e JavaScript que simplifica o acesso e manipulação de banco de dados relacionais.
- MySQL: Sistema de gerenciamento de banco de dados relacional utilizado para armazenar os dados da aplicação.
- Bcrypt: Biblioteca para hashing de senhas utilizada para armazenar senhas de forma segura.
- Jsonwebtoken: Implementação de JSON Web Tokens (JWT) para autenticação de usuários.
- Dotenv: Módulo que carrega variáveis de ambiente a partir de um arquivo .env para o processo do Node.js.
- Cors: Middleware para Express que habilita o controle de acesso HTTP (CORS).
- Http Status Codes: Status Codes: Pacote que fornece uma lista de constantes para códigos de status HTTP.
- Jest: Framework de teste em JavaScript com foco na simplicidade.
- Supertest: Biblioteca utilizada para testar APIs HTTP.
- Uuidv4: Pacote para geração de UUIDs (identificadores únicos universais) versão 4.
- Docker: Uma ferramenta para definir e executar aplicações multi-contêineres. É a chave para desbloquear uma experiência de desenvolvimento e implantação simplificada e eficiente.
- Swagger: Ferramente utilizada para criar documentações exemplificando a utilização das rotas, de uma forma prática.
- OpenAI: Biblioteca que nos permite integrar seus produtos de Inteligência Artificial aos nossos projetos.
- Terraform: Uma ferramenta de infraestrutura como código (IaC) para provisionar e gerenciar recursos de infraestrutura de forma declarativa. É utilizado para automatizar implantações, oferecendo consistência e confiabilidade.
- Google Cloud: Uma plataforma de computação em nuvem do Google, oferecendo uma ampla gama de serviços para desenvolvimento, armazenamento e implantação de aplicações. Com infraestrutura global e recursos avançados, é uma escolha popular para migrar cargas de trabalho para a nuvem.
Git
Docker
- Clone o repositório com o comando git clone:
git clone git@github.com:danielbped/ChatPRT.git
- Entre no diretório que acabou de ser criado:
cd ChatPRT
Para que a aplicação funcione corretamente, algumas variáveis de ambiente precisam ser configuradas, basta seguir os passos a seguir.
Na raiz do projeto, basta renomear o arquivo .env.example para .env, lá já se encontram todas as variáveis necessárias para iniciar o banco de dados.
Na pasta Backend, será necessário criar um arquivo .env, com as seguintes informações:
MYSQL_DB_USER=root
MYSQL_DB_NAME=chat-prt
MYSQL_DB_HOST=localhost
MYSQL_DB_PASSWORD=password
MYSQL_DB_ROOT_PASSWORD=password
MYSQL_DB_PORT=3306
SECRET_KEY_JWT=chat-prt
OPENAI_API_URL=https://api.openai.com/v1/chat/completions
OPENAI_PROJECT=
OPENAI_ORGANIZATION=
OPENAI_MODEL=
Um arquivo com estas definições já está presente no projeto, o .env.example, para que funcione corretamente, basta renomear para apenas .env, são responsáveis pela criação do banco de dados. Caso deseje utilizar um banco de dados local ao invés do banco fornecido na imagem do Docker, basta alterar os dados de acordo com os dados de usuário do banco de dados local. Em relação às outras variáveis. Em relação às variáveis relacionadas à plataforma da OpenAI, é necessário que você possua uma conta na OpenAI, com um projeto criado, então o código do projeto irá em OPENAI_PROJECT e o código da organização em OPENAI_ORGANIZATION. Já em relação ao modelo utilizado, foi o gpt-3.5-turbo, mas outros modelos podem ser utilizados, de acordo com as configurações da sua conta. Para mais informações sobre como obter estes dados, visite.
Com as variáveis de ambiente configuradas, basta executar o comando do Docker abaixo para buildar a aplicação:
docker-compose up -d --build
Caso tudo tenha dado certo, a seguinte mensagem aparecerá no terminal
[+] Running 5/5
Network chatprt_backend_network Created
Network chatprt_frontend_network Created
Container chatprt-chatprt-db-1 Started
Container chatprt-chatprt-backend-1 Started
Container chatprt-chatprt-frontend-1 Started
Agora basta acessar a URL http://localhost:8000 para acessar a aplicação, e a URL http://localhost:3000/docs para visualizar as rotas disponíveis da API.
Para derrubar a aplicação e encerrar os containers do Docker, basta rodar o comando abaixo:
docker-compose down
Prisma ícones criados por Freepik - Flaticon
- Status 200 (OK)
- Descrição: Aplicação está saudável e funcionando.
- Status 500 (Internal Server Error)
- Descrição: Aplicação não está funcionando corretamente.
As requisições que envolvem usuário (POST /user
e POST /login
) possuem um comportamento semelhante. Ambas irão retornar o usuário logado e um token. Este token será necessário para as demais rotas, sendo passado no parâmetro Authorization dos headers das requisições. No seguinte formato Bearer token
. Por exemplo, se o token for yJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ
, o parâmetro Authorization terá o seguinte valor Bearer yJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ
.
Parâmetro | Tipo | Descrição | Exemplo |
---|---|---|---|
firstName |
String | Nome do usuário | "Douglas" |
lastName |
String | Sobrenome do usuário | "Adams" |
email |
String | E-mail do usuário | "douglasadams@email.com" |
password |
String | Senha do usuário | "s3nh4_f0rt3" |
-
Status 201 (Created)
- Descrição: Criado com sucesso.
{ "token": "yJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ", "user": { "firstName": "Douglas", "lastName": "Adams", "email": "douglasadams@email.com", "id": "123456789", "createdAt": "2024-05-02T12:00:00Z", "updatedAt": "2024-05-02T12:00:00Z" } }
-
Status 400 (Bad Request)
- Descrição: Dados inválidos.
-
Status 500 (Internal Server Error) -Descrição: Erro interno do sistema.
Parâmetro | Tipo | Descrição | Exemplo |
---|---|---|---|
email |
String | E-mail do usuário | "douglasadams@email.com" |
password |
String | Senha do usuário | "s3nh4_f0rt3" |
-
Status 200 (OK)
- Descrição: Sucesso no login.
{ "token": "yJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ", "user": { "firstName": "Douglas", "lastName": "Adams", "email": "douglasadams@email.com", "id": "123456789", "createdAt": "2024-05-02T12:00:00Z", "updatedAt": "2024-05-02T12:00:00Z" } }
-
Status 401 (Unauthorized)
- Descrição: Credenciais inválidas.
-
Status 500 (Internal Server Error)
- Descrição: Erro interno do sistema.
Parâmetro | Tipo | Descrição | Exemplo |
---|---|---|---|
content |
String | Conteúdo da mensagem a ser enviada | "Qual é a resposta para a vida, o universo e tudo mais?" |
conversation |
Object | Conversation em que a mensagem está inserida | Consulte o exemplo abaixo |
Exemplo do objeto conversation
:
{
"id": "123456789",
"messages": [],
"createdAt": "2024-05-02T12:00:00Z",
"updatedAt": "2024-05-02T12:00:00Z",
"user": {
"id": "42",
"firstName": "Douglas",
"lastName": "Adams",
"email": "douglasadams@example.com",
"createdAt": "2024-05-02T12:00:00Z",
"updatedAt": "2024-05-02T12:00:00Z"
}
}
- Status 201 (Created)
- Descrição: Criado com sucesso.
{
"content": "Qual é a resposta para a vida, o universo e tudo mais?",
"response": "42",
"conversation": {
"id": "123456789",
"messages": [],
"createdAt": "2024-05-02T12:00:00Z",
"updatedAt": "2024-05-02T12:00:00Z",
"user": {
"id": "42",
"firstName": "Douglas",
"lastName": "Adams",
"email": "douglasadams@example.com",
"createdAt": "2024-05-02T12:00:00Z",
"updatedAt": "2024-05-02T12:00:00Z"
}
},
"id": "123456789",
"createdAt": "2024-05-02T12:00:00Z",
"updatedAt": "2024-05-02T12:00:00Z"
}
- Status 401 (Unauthorized)
- Descrição: Usuário não autorizado.
- Status 400 (Bad Request)
- Descrição: Dados inválidos.
- Status 500 (Internal Server Error)
- Descrição: Erro interno do sistema.
Parâmetro | Tipo | Descrição | Exemplo |
---|---|---|---|
id |
String | ID do usuário | "42" |
-
Status 200 (OK)
- Descrição: Sucesso.
[ { "id": "123456789", "user": { "id": "42", "firstName": "Douglas", "lastName": "Adams", "email": "douglasadams@example.com" }, "messages": [], "createdAt": "2024-05-02T12:00:00Z", "updatedAt": "2024-05-02T12:00:00Z" } ]
-
Status 401 (Unauthorized)
- Descrição: Usuário não autorizado.
-
Status 404 (Not Found)
- Descrição: Usuário não encontrado.
-
Status 400 (Bad Request)
- Descrição: Dados inválidos.
Parâmetro | Tipo | Descrição | Exemplo |
---|---|---|---|
user |
Object | Usuário participante da conversa | Consulte o exemplo abaixo |
Exemplo do objeto user
:
{
"id": "42",
"firstName": "Douglas",
"lastName": "Adams",
"email": "douglasadams@example.com",
"createdAt": "2024-05-02T12:00:00Z",
"updatedAt": "2024-05-02T12:00:00Z"
}
- Status 201 (Created)
- Descrição: Criado com sucesso.
{
"id": "123456789",
"user": {
"id": "42",
"firstName": "Douglas",
"lastName": "Adams",
"email": "douglasadams@example.com",
"createdAt": "2024-05-02T12:00:00Z",
"updatedAt": "2024-05-02T12:00:00Z"
},
"createdAt": "2024-05-02T12:00:00Z",
"updatedAt": "2024-05-02T12:00:00Z",
"messages": []
}
- Status 401 (Unauthorized)
- Descrição: Usuário não autorizado.
- Status 400 (Bad Request)
- Descrição: Dados inválidos.
Parâmetro | Tipo | Descrição | Exemplo |
---|---|---|---|
id |
String | ID da conversa | "123456789" |
-
Status 200 (OK)
- Descrição: Deletado com sucesso.
-
Status 401 (Unauthorized)
- Descrição: Usuário não autorizado.
-
Status 404 (Not Found)
- Descrição: Conversa não encontrada.
-
Status 400 (Bad Request)
- Descrição: Dados inválidos.
Ao rodar a aplicação, você poderá visualizar as rotas disponíveis, também como seus respectivos conteúdos de body e parametros, basta navegar para a rota http://localhost:3000/docs, onde está disponível uma documentação exclusiva das rotas, desenvolvida utilizando Swagger.
A aplicação possui testes unitários de todas as rotas e todos os middlewares, também como testes E2E (End to end) de todas as rotas. Para rodar os testes, basta executar o comando abaixo, no diretório /Backend
:
npm run test
O banco de dados foi desenvolvido utilizando MySQL com o auxílio da ORM TypeORM nas migrations e nas queries. A arquitetura do banco possui três tabelas (User, Message e Conversation), e suas colunas podem ser observadas a seguir:
Coluna | Tipo |
---|---|
id |
String |
firstName |
String |
lastName |
String |
email |
String |
password |
String |
createdAt |
Date |
updatedAt |
Date |
Coluna | Tipo |
---|---|
id |
String |
conversation |
Conversation |
content |
String |
response |
String |
createdAt |
Date |
updatedAt |
Date |
Coluna | Tipo |
---|---|
id |
String |
user |
User |
messages |
Message[] |
createdAt |
Date |
updatedAt |
Date |
Para um melhor fluxo de entrega e integrações contínuas, foram desenvolvidos dois scripts de workflow, que irão funcionar em momentos específicos do desenvolvimento. Ambos os workflows estão disponíveis na pasta .github.
Este script é responsável por atualizar as imagens da aplicação no Docker Hub, sempre que houver um push nas branch master
.
Este script é responsável por validar a integridade da aplicação e rodar todos os testes automatizados, sempre que um novo Pull Request for aberto.
A configuração do Terraform se encontra disponível na pasta Terraform, no arquivo main
pode-se encontrar toda a configuração de deploy das imagens Docker da aplicação, que são instanciadas no Cloud Run. Também como a instância do banco de dados MySQL no Cloud SQL.