{"id":29580289,"url":"https://github.com/mathrb22/let-me-ask-server","last_synced_at":"2026-04-12T15:04:39.561Z","repository":{"id":303905376,"uuid":"1016944655","full_name":"mathrb22/let-me-ask-server","owner":"mathrb22","description":"Backend do projeto Let me ask (NLW Agents). Uma API com IA para responder perguntas em tempo real durante transmissões, usando Node.js, Fastify e busca semântica com pgvector.","archived":false,"fork":false,"pushed_at":"2025-07-18T04:51:00.000Z","size":61,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-18T08:19:39.243Z","etag":null,"topics":["ai","api","audio-processing","audio-transcription","backend","docker","drizzle-orm","fastify","gemini-api","let-me-ask","nlw","nlw-agents","nodejs","pgvector","postgresql","rocketseat","semantic-search","semantic-vector-evaluation","typescript","zod"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mathrb22.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-09T19:15:45.000Z","updated_at":"2025-07-18T04:51:03.000Z","dependencies_parsed_at":"2025-07-10T11:58:10.834Z","dependency_job_id":"1b5238f3-58e3-49f9-9b30-4c3f5b7622ab","html_url":"https://github.com/mathrb22/let-me-ask-server","commit_stats":null,"previous_names":["mathrb22/let-me-ask-server"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mathrb22/let-me-ask-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathrb22%2Flet-me-ask-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathrb22%2Flet-me-ask-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathrb22%2Flet-me-ask-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathrb22%2Flet-me-ask-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mathrb22","download_url":"https://codeload.github.com/mathrb22/let-me-ask-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mathrb22%2Flet-me-ask-server/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265992482,"owners_count":23860913,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","api","audio-processing","audio-transcription","backend","docker","drizzle-orm","fastify","gemini-api","let-me-ask","nlw","nlw-agents","nodejs","pgvector","postgresql","rocketseat","semantic-search","semantic-vector-evaluation","typescript","zod"],"created_at":"2025-07-19T19:00:31.184Z","updated_at":"2026-04-12T15:04:34.523Z","avatar_url":"https://github.com/mathrb22.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003ch1\u003eLet me ask - Backend\u003c/h1\u003e\n\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n   \u003ca href=\"https://github.com/mathrb22\"\u003e\n      \u003cimg alt=\"Made by mathrb22\" src=\"https://img.shields.io/badge/made%20by-mathrb22-yellow\"\u003e\n   \u003c/a\u003e\n   \u003ca href=\"https://github.com/mathrb22/let-me-ask-server/commits/main\"\u003e\n      \u003cimg alt=\"GitHub Last Commit\" src=\"https://img.shields.io/github/last-commit/mathrb22/let-me-ask-server\"\u003e\n   \u003c/a\u003e\n   \u003ca href=\"https://github.com/mathrb22/let-me-ask-server/issues\"\u003e\n      \u003cimg alt=\"GitHub Issues\" src=\"https://img.shields.io/github/issues/mathrb22/let-me-ask-server\"\u003e\n   \u003c/a\u003e\n   \u003ca href=\"https://github.com/mathrb22/let-me-ask-server/pulls\"\u003e\n      \u003cimg alt=\"Pull Requests Welcome\" src=\"https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square\"\u003e\n   \u003c/a\u003e\n   \u003ca href=\"https://github.com/mathrb22/let-me-ask-server/blob/main/LICENSE\"\u003e\n      \u003cimg alt=\"GitHub License\" src=\"https://img.shields.io/github/license/mathrb22/let-me-ask-server\"\u003e\n   \u003c/a\u003e\n\u003c/div\u003e\n\n\u003c/br\u003e\n\u003cdiv align=\"center\"\u003e\n\n[**Sobre**](#-sobre) \u0026nbsp;\u0026nbsp;**|**\u0026nbsp;\u0026nbsp;\n[**Objetivo**](#-objetivo) \u0026nbsp;\u0026nbsp;**|**\u0026nbsp;\u0026nbsp;\n[**Tecnologias e ferramentas**](#-tecnologias-e-ferramentas) \u0026nbsp;\u0026nbsp;**|**\u0026nbsp;\u0026nbsp;\n[**Features**](#-features) \u0026nbsp;\u0026nbsp;**|**\u0026nbsp;\u0026nbsp;\n[**Instalação e execução**](#-instalação-e-execução) \u0026nbsp;\u0026nbsp;**|**\u0026nbsp;\u0026nbsp;\n[**Estrutura do projeto**](#-estrutura-do-projeto) \u0026nbsp;\u0026nbsp;**|**\u0026nbsp;\u0026nbsp;\n[**Como contribuir**](#-como-contribuir) \u0026nbsp;\u0026nbsp;**|**\u0026nbsp;\u0026nbsp;\n[**Licença**](#-licença)\n\n\u003c/div\u003e\n\n## 📃 Sobre\n\nEste repositório contém o código-fonte do **backend** do projeto **Let me ask**, desenvolvido durante a **NLW Agents (Next Level Week)** da [Rocketseat](https://github.com/Rocketseat). O projeto é uma API moderna construída com **Node.js**, **TypeScript** e **Fastify**, utilizando **PostgreSQL** com a extensão **pgvector** para suporte a vetores e operações de IA.\n\nO sistema integra **agentes de IA**, **busca semântica** e **processamento de dados vetoriais** para fornecer respostas automáticas a perguntas de participantes durante transmissões ao vivo. Através do upload de trechos de áudio da transmissão, a IA realiza a transcrição, gera vetores semânticos do conteúdo e os armazena. Isso permite que o sistema utilize busca semântica para verificar se perguntas já foram respondidas e fornecer respostas contextualizadas automaticamente.\n\n## 🎯 Objetivo\n\nCriar uma solução inteligente para transmissões ao vivo onde perguntas dos participantes são respondidas automaticamente por uma inteligência artificial, utilizando:\n\n- **Upload e transcrição** de trechos de áudio de transmissões ao vivo.\n- **Geração e processamento de dados vetoriais** para armazenar o contexto semântico do que foi dito.\n- **Busca semântica** para identificar se perguntas já foram respondidas com base no conteúdo transcrito.\n- **Agente de IA** para fornecer respostas contextualmente relevantes e precisas.\n\n## 🚀 Tecnologias e ferramentas\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\" width=\"90\"\u003e\n      \u003ca href=\"https://nodejs.org/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n        \u003cimg width=\"60\" src=\"https://user-images.githubusercontent.com/25181517/183568594-85e280a7-0d7e-4d1a-9028-c8c2209e073c.png\" alt=\"Node.js\" title=\"Node.js\"/\u003e\n      \u003c/a\u003e\n      \u003cspan\u003eNode.js\u003c/span\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\" width=\"90\"\u003e\n      \u003ca href=\"https://www.typescriptlang.org/\"\u003e\n        \u003cimg width=\"60\" src=\"https://user-images.githubusercontent.com/25181517/183890598-19a0ac2d-e88a-4005-a8df-1ee36782fde1.png\" alt=\"TypeScript\" title=\"TypeScript\"/\u003e\n      \u003c/a\u003e\n      \u003cspan\u003eTypeScript\u003c/span\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\" width=\"100\"\u003e\n      \u003ca href=\"https://fastify.dev/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n        \u003cimg width=\"60\" src=\"https://avatars.githubusercontent.com/u/24939410?s=280\u0026v=4\" alt=\"Fastify\" title=\"Fastify\"/\u003e\n      \u003c/a\u003e\n      \u003cspan\u003eFastify\u003c/span\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\" width=\"90\"\u003e\n      \u003ca href=\"https://orm.drizzle.team/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n        \u003cimg width=\"60\" src=\"https://avatars.githubusercontent.com/u/108468352?s=200\u0026v=4\" alt=\"Drizzle ORM\" title=\"Drizzle ORM\"/\u003e\n      \u003c/a\u003e\n      \u003cspan\u003eDrizzle ORM\u003c/span\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\" width=\"90\"\u003e\n      \u003ca href=\"https://www.postgresql.org/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n        \u003cimg width=\"60\" src=\"https://www.postgresql.org/media/img/about/press/elephant.png\" alt=\"PostgreSQL\" title=\"PostgreSQL\"/\u003e\n      \u003c/a\u003e\n      \u003cspan\u003ePostgreSQL\u003c/span\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\" width=\"90\"\u003e\n      \u003ca href=\"https://github.com/pgvector/pgvector\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n        \u003cimg width=\"60\" src=\"https://www.postgresql.org/media/img/about/press/elephant.png\" alt=\"pgvector\" title=\"pgvector\"/\u003e\n      \u003c/a\u003e\n      \u003cspan\u003epgvector\u003c/span\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\" width=\"90\"\u003e\n      \u003ca href=\"https://zod.dev\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n        \u003cimg width=\"60\" src=\"https://zod.dev/_next/image?url=%2Flogo%2Flogo-glow.png\u0026w=640\u0026q=100\" alt=\"Zod\" title=\"Zod\"/\u003e\n      \u003c/a\u003e\n      \u003cspan\u003eZod\u003c/span\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\" width=\"100\"\u003e\n      \u003ca href=\"https://ai.google.dev/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n        \u003cimg width=\"60\" src=\"https://play-lh.googleusercontent.com/bTpNtZ6rYYX2SeI-wC4cnr7MJnOh2hjtgYu3UIrSxE09lM3GPl_Uhf9_Ih2Smje2bc0V=w240-h480-rw\" alt=\"Google Gemini API\" title=\"Google Gemini API\"/\u003e\n      \u003c/a\u003e\n      \u003cspan\u003eGoogle Gemini API\u003c/span\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\" width=\"90\"\u003e\n      \u003ca href=\"https://biomejs.dev/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n        \u003cimg width=\"60\" src=\"https://avatars.githubusercontent.com/u/140182603?v=4\" alt=\"Biome\" title=\"Biome\"/\u003e\n      \u003c/a\u003e\n      \u003cspan\u003eBiome\u003c/span\u003e\n    \u003c/td\u003e\n    \u003ctd align=\"center\" width=\"90\"\u003e\n      \u003ca href=\"https://www.docker.com/\" target=\"_blank\" rel=\"noopener noreferrer\"\u003e\n        \u003cimg width=\"60\" src=\"https://images-eds-ssl.xboxlive.com/image?url=4rt9.lXDC4H_93laV1_eHHFT949fUipzkiFOBH3fAiZZUCdYojwUyX2aTonS1aIwMrx6NUIsHfUHSLzjGJFxxvHMT0riO5Ze2r4kAINc_2Sf3i_lhd_UyN3p_M0zbCTnlfDqa8Z.oTShpYDF75lO38ORwn3qN2SS1GkJALG9t8s-\u0026format=source\" alt=\"Docker\" title=\"Docker\"/\u003e\n      \u003c/a\u003e\n      \u003cspan\u003eDocker\u003c/span\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## ✨ Features\n\n- **Gestão de Salas**:\n\n  - Criação e listagem de salas para eventos.\n  - Detalhamento de informações de uma sala específica.\n\n- **Gestão de Perguntas**:\n\n  - Envio de perguntas para uma sala.\n  - Listagem de perguntas de uma sala.\n\n- **Processamento de Áudio com IA**:\n\n  - **Upload de Áudio**: Endpoint para enviar trechos de áudio (`chunks`) de uma transmissão ao vivo para uma sala específica.\n  - **Transcrição Automática**: O áudio enviado é automaticamente transcrito para texto utilizando a API do **Google Gemini**.\n  - **Geração de Vetores Semânticos**: A transcrição é processada para gerar _embeddings_ (vetores semânticos) que capturam o significado do texto.\n  - **Armazenamento**: A transcrição e os vetores são salvos no banco de dados, associados à sala correspondente.\n  - **Busca Semântica**: ao criar uma nova pergunta, o sistema usará a busca por similaridade no banco de vetores para encontrar os trechos da transcrição mais relevantes e, assim, verificar se a pergunta já foi respondida.\n\n## 💿 Instalação e execução\n\nSiga os passos abaixo para configurar e executar o projeto em seu ambiente de desenvolvimento.\n\n**Pré-requisitos:**\n\n- [Node.js](https://nodejs.org/en/) (versão 20 ou superior)\n- [Docker](https://www.docker.com/get-started) e [Docker Compose](https://docs.docker.com/compose/install/)\n- Uma chave de API do [Google Gemini](https://aistudio.google.com/app/apikey)\n\n**Passos:**\n\n1. **Clone o repositório:**\n\n   ```bash\n   git clone https://github.com/mathrb22/let-me-ask-server.git\n   cd let-me-ask-server\n   ```\n\n2. **Instale as dependências:**\n\n   ```bash\n   npm install\n   ```\n\n3. **Configure as variáveis de ambiente:**\n\n   - Crie um arquivo `.env` na raiz do projeto, copiando o exemplo de `.env.example`.\n     ```bash\n     cp .env.example .env\n     ```\n   - Abra o arquivo `.env` e preencha as variáveis:\n\n     ```env\n     # Porta da aplicação\n     PORT=3333\n\n     # URL de conexão com o banco de dados PostgreSQL\n     DATABASE_URL=\"postgresql://docker:docker@localhost:5432/agents\"\n\n     # Sua chave de API do Google Gemini\n     GEMINI_API_KEY=\"SUA_CHAVE_DE_API_AQUI\"\n     ```\n\n4. **Inicie o banco de dados com Docker:**\n\n   - O comando abaixo irá iniciar um contêiner PostgreSQL com a extensão `pgvector`.\n\n   ```bash\n   docker-compose up -d\n   ```\n\n5. **Execute as migrações do banco de dados:**\n\n   - Este comando aplicará as tabelas e configurações necessárias ao banco.\n\n   ```bash\n   npm run db:migrate\n   ```\n\n6. **Execute o servidor de desenvolvimento:**\n   ```bash\n   npm run dev\n   ```\n\nA API estará disponível em `http://localhost:3333`.\n\n### Comandos úteis do banco de dados\n\n- **Gerar uma nova migração** (após alterar um schema em `src/db/schema/`):\n  ```bash\n  npm run db:generate\n  ```\n- **Abrir o Drizzle Studio** (para visualizar e gerenciar o banco de dados):\n  ```bash\n  npm run db:studio\n  ```\n\n## 📂 Estrutura do projeto\n\nO projeto está organizado da seguinte forma:\n\n```\n.\n├── drizzle.config.ts   # Configuração do Drizzle ORM\n├── docker-compose.yml  # Configuração do Docker para o banco de dados\n├── package.json\n├── biome.jsonc         # Configuração do Biome (linter e formatter)\n├── tsconfig.json\n└── src/\n    ├── db/\n    │   ├── connection.ts   # Conexão com o banco de dados (Drizzle)\n    │   ├── migrations/     # Arquivos de migração do banco\n    │   └── schema/         # Definições das tabelas do banco (schemas)\n    │       ├── index.ts\n    │       ├── rooms.ts\n    │       ├── questions.ts\n    │       └── audio-chunks.ts\n    ├── http/\n    │   ├── routes/         # Definição das rotas da API\n    │   │   ├── create-room.ts\n    │   │   ├── get-rooms.ts\n    │   │   ├── create-question.ts\n    │   │   └── upload-audio.ts\n    │   └── server.ts       # Arquivo principal do servidor Fastify\n    ├── services/\n    │   └── gemini.ts       # Lógica de integração com a API do Gemini\n    └── env.ts              # Validação de variáveis de ambiente com Zod\n```\n\n## 💡 Como contribuir\n\n- Faça um **_fork_** desse repositório;\n- Crie um **branch** para a sua feature: `git checkout -b minha-feature`;\n- Faça um **commit** com suas alterações: `git commit -m 'feat: Minha nova feature'`;\n- Faça um **push** para o seu branch: `git push origin minha-feature`;\n- Faça um **pull request** com sua feature;\n\nPull requests são sempre bem-vindos. Em caso de dúvidas ou sugestões, crie uma _**issue**_ ou entre em contato comigo.\n\n## 📝 Licença\n\n\u003ca href=\"https://github.com/mathrb22/let-me-ask-server/blob/main/LICENSE\"\u003e\n    \u003cimg alt=\"GitHub License\" src=\"https://img.shields.io/github/license/mathrb22/let-me-ask-server\"\u003e\n\u003c/a\u003e\n\nEsse projeto está sob a licença **MIT**. Veja o arquivo _**LICENSE**_ para mais detalhes.\n\n---\n\nDesenvolvido com 💚 por \u003ca href=\"https://github.com/mathrb22/\"\u003emathrb22\u003c/a\u003e\n\n\u003cdiv style=\"display: flex;\"\u003e\n  \u003ca href=\"https://www.linkedin.com/in/matheus-ribeiro-dev\" target=\"_blank\"\u003e\u003cimg src=\"https://img.shields.io/badge/-LinkedIn-%230077B5?style=for-the-badge\u0026logo=linkedin\u0026logoColor=white\" style=\"margin-right: 2vw\" target=\"_blank\"\u003e\u003c/a\u003e\n  \u003ca href=\"mailto:math.ribeiro.dev@gmail.com\"\u003e\u003cimg src=\"https://img.shields.io/badge/Gmail-D14836?style=for-the-badge\u0026logo=gmail\u0026logoColor=white\" alt=\"Gmail\" style=\"margin-right: 2vw\"/\u003e\u003c/a\u003e\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathrb22%2Flet-me-ask-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmathrb22%2Flet-me-ask-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathrb22%2Flet-me-ask-server/lists"}