Skip to content
This page has been auto-translated and may contain errors.View in English

Executando Embeddings e Bancos de Dados Vetoriais localmente ​

Use esta página para executar o chatbot de filmes ReelRecs extraído de Embeddings and Vector Databases em seu computador, com sua própria chave OpenAI e o banco de dados Supabase que você criou durante o curso. Três coisas diferem do editor do Scrimba: dois pacotes precisam ser instalados pelo nome, as leituras em config.js precisam da sintaxe do Vite, e o modelo de chat que o projeto usa foi descontinuado.

O que você precisa primeiro ​

Instale uma versão LTS suportada do Node.js. Node 24 é recomendado e inclui npm.

Verifique se ambos os comandos funcionam. Seus números de versão podem ser diferentes:

bash
$ node --version
v24.18.0
$ npm --version
11.18.0

Você também precisa de três valores:

  • Uma chave de API da OpenAI. Crie uma que você deletará quando terminar: este projeto chama a OpenAI direto do navegador, então a chave acaba aparecendo na página.
  • A URL do seu projeto Supabase, do projeto Supabase que contém os filmes e a função match_movies que você criou durante o curso.
  • A chave publicável desse projeto, que começa com sb_publishable_. Se seu projeto mostra apenas a chave anon mais antiga, use essa. Nunca use a chave secreta ou a chave service_role aqui.
JunoO que você precisa primeiro Instale a versão LTS do Node.js e verifique se node --version e npm --version imprimem uma versão.

Depois colete sua chave OpenAI, a URL do seu projeto Supabase e sua chave publicável. O projeto Supabase deve ser aquele que você preencheu com filmes durante o curso.

JunoO que você precisa primeiro Este projeto apenas lê seus filmes: nada nele cria a tabela, os números ou match_movies. Se esse projeto Supabase estiver vazio, o chatbot executa mas responde "Desculpe, não sei a resposta."
JunoO que você precisa primeiro A chave publicável só pode fazer o que suas políticas de Row Level Security permitem, é por isso que o Supabase a cria para código do navegador. A chave OpenAI não tem tal limite: quem a copiar pode gastar seu crédito até você deletá-la.

Instale os pacotes ​

Abra um terminal na pasta extraída. É aquela que contém package.json, config.js e index.js:

bash
$ cd caminho-para-seu-projeto-extraído

package.json lista apenas Vite, mas config.js também importa os pacotes OpenAI e Supabase. O editor do Scrimba instala esses para você; em seu computador, nomeie-os e npm os instala junto com Vite:

bash
$ npm install openai @supabase/supabase-js
added 25 packages, and audited 26 packages in 9s

npm termina informando quantos pacotes foram adicionados.

JunoInstale os pacotes Abra o terminal na pasta que contém package.json, depois execute npm install openai @supabase/supabase-js. npm termina dizendo quantos pacotes foram adicionados.

Se npm disser que não consegue encontrar package.json, você está na pasta errada.

JunoInstale os pacotes npm instala o que package.json lista, e nomear dois pacotes os adiciona àquela lista, então um comando instala todos os três. Um simples npm install lhe daria apenas Vite.
JunoInstale os pacotes Sem os dois pacotes, npm start ainda serve a página: a verificação de inicialização do Vite apenas imprime um aviso, e a importação falha quando o navegador solicita config.js, como um erro sobre a página.

Altere config.js e index.js ​

O editor do Scrimba preenche process.env.OPENAI_API_KEY, process.env.SUPABASE_API_KEY e process.env.SUPABASE_URL para você. O navegador não tem process, e Vite não cria um, então todas as quatro leituras em config.js devem mudar; a chave OpenAI é lida duas vezes. Vite passa ao código do navegador apenas as variáveis cujos nomes começam com VITE_, é por isso que cada nome recebe esse prefixo.

Substitua o conteúdo de config.js por:

js
import OpenAI from 'openai';
import { createClient } from "@supabase/supabase-js";

/** Configuração do OpenAI */
if (!import.meta.env.VITE_OPENAI_API_KEY) throw new Error("OpenAI API key is missing or invalid.");
export const openai = new OpenAI({
  apiKey: import.meta.env.VITE_OPENAI_API_KEY,
  dangerouslyAllowBrowser: true
});

/** Configuração do Supabase */
const privateKey = import.meta.env.VITE_SUPABASE_API_KEY;
if (!privateKey) throw new Error(`Expected env var SUPABASE_API_KEY`);
const url = import.meta.env.VITE_SUPABASE_URL;
if (!url) throw new Error(`Expected env var SUPABASE_URL`);
export const supabase = createClient(url, privateKey);

Apenas as quatro leituras diferem do arquivo que você baixou. As duas mensagens de erro do Supabase ainda nomeiam as variáveis antigas; deixe-as como estão.

Depois abra index.js. A solicitação de chat pede gpt-4, que a OpenAI descontinuou. Em getChatCompletion, altere:

js
model: 'gpt-4',

para:

js
model: 'gpt-4o-mini',

Deixe o outro modelo em index.js, text-embedding-ada-002, como está. Os filmes em seu banco de dados foram convertidos em números com esse modelo, e sua pergunta precisa ser convertida em números da mesma forma para ser comparada com eles.

JunoAltere config.js e index.js Cole o novo config.js sobre o antigo, depois altere gpt-4 para gpt-4o-mini em index.js.

Não toque em text-embedding-ada-002; seu banco de dados depende disso.

JunoAltere config.js e index.js Quando Vite serve config.js, ele substitui cada leitura import.meta.env.VITE_... pelo valor de .env. Um nome sem o prefixo fica oculto do código do navegador, chega como undefined, e dispara as verificações em config.js.
JunoAltere config.js e index.jsconfig.js lança um erro enquanto carrega, antes de index.js anexar seu manipulador de formulário. Então uma leitura ruim deixa uma página que parece normal, mas pressionar Enter a recarrega e sua pergunta desaparece.

Adicione suas chaves a .env ​

Crie .env ao lado de package.json com seus três valores:

dotenv
VITE_OPENAI_API_KEY=sua-chave-openai-api
VITE_SUPABASE_URL=https://seu-projeto.supabase.co
VITE_SUPABASE_API_KEY=sua-chave-publicavel

Crie .gitignore ao lado de package.json e adicione:

txt
.env
node_modules/

Uma chave que chega a um repositório Git permanece em seu histórico mesmo após você deletar o arquivo. O manual Git aborda o hábito em ignorando arquivos e boas práticas.

Essas chaves são visíveis no navegador

Vite escreve cada valor VITE_ no código que envia ao navegador, então qualquer pessoa que abra esta página pode ler sua chave OpenAI. Mantenha esta versão em seu próprio computador: nunca implante ou compartilhe, e nunca faça commit de .env. Uma versão que você publica precisa de um backend que mantenha a chave OpenAI no servidor, como no projeto Vercel AI SDK.

JunoAdicione suas chaves a .env Faça um arquivo chamado .env ao lado de package.json com seus três valores, um por linha, depois liste .env em .gitignore para que Git nunca o salve.
JunoAdicione suas chaves a .env Vite lê .env quando inicia e depois o monitora: salvar uma alteração imprime .env changed, restarting server..., e a página aberta recarrega com os novos valores.
JunoAdicione suas chaves a .env O prefixo VITE_ é uma lista de permissões de exposição, não armazenamento de segredos: a chave OpenAI fica no módulo que Vite serve e no cabeçalho de cada solicitação que o navegador envia para OpenAI.

Inicie o chatbot e faça uma pergunta ​

Inicie o servidor de desenvolvimento:

bash
$ npm start

Vite pode primeiro imprimir um aviso que começa com (!) Your Vite config uses features. Isso não para o app. Um aviso diferente, (!) Failed to run dependency scan, significa que os dois pacotes estão faltando: volte para a etapa de instalação. Abaixo dos avisos, Vite imprime o endereço para abrir:

text
  VITE v8.3.4  ready in 218 ms

  ➜  Local:   http://localhost:5173/

Abra o endereço Local exato. A página mostra ReelRecs e uma caixa que diz "Como posso ajudar?". Faça uma pergunta sobre um filme em seu banco de dados e pressione Enter. Pensando... aparece, e após alguns segundos a resposta a substitui. Uma resposta sobre seus filmes significa que OpenAI e Supabase funcionam.

Se sua pergunta desaparece e nada mais acontece, a página nunca recebeu suas chaves; as primeiras entradas de solução de problemas abaixo correspondem à linha do terminal.

Se a página diz "Desculpe, algo deu errado. Por favor, tente novamente.", procure no terminal onde npm start está em execução. Vite copia o erro do navegador ali, em uma linha contendo Error in main function.; a solução de problemas abaixo corresponde a cada mensagem. A mesma linha está nas ferramentas de desenvolvedor do seu navegador (F12, ou Cmd+Option+J no Chrome em um Mac), na aba Console.

Pare o projeto com Ctrl+C. Se você salvar .env enquanto ele está em execução, Vite o reinicia (.env changed, restarting server...) e a página recarrega com os novos valores.

JunoInicie o chatbot e faça uma pergunta Execute npm start, ignore o aviso de configuração se aparecer, e abra o endereço Local. Faça uma pergunta sobre um de seus filmes e aguarde a resposta.

Se receber "Desculpe, algo deu errado", leia a linha mais recente no terminal.

JunoInicie o chatbot e faça uma pergunta Uma pergunta executa três solicitações em ordem: OpenAI faz números a partir dela, match_movies do Supabase encontra os filmes mais próximos, e OpenAI escreve a resposta. Qualquer uma falhando mostra a mesma mensagem de desculpas, então a linha de erro diz qual corrigir.
JunoInicie o chatbot e faça uma perguntamain envolve todas as três solicitações em um try/catch e registra apenas a mensagem do erro. Vite 8 encaminha esse console.error do navegador para o terminal, é por isso que o terminal mostra uma falha do navegador.

Solução de problemas ​

O terminal mostra (!) Failed to run dependency scan, e o navegador mostra Failed to resolve import "openai" from "config.js": Os dois pacotes não estão instalados. Pare o projeto, execute npm install openai @supabase/supabase-js na pasta que contém package.json, depois inicie o projeto novamente.

Sua pergunta desaparece quando você pressiona Enter, e o terminal mostra ReferenceError: process is not defined: Uma leitura process.env ainda está em config.js. Substitua o arquivo pela versão mostrada acima e salve.

Sua pergunta desaparece, e o terminal mostra OpenAI API key is missing or invalid ou Expected env var: Vite não encontrou um valor. Verifique se .env está ao lado de package.json e se cada nome começa com VITE_, depois salve; Vite se reinicia e a página recarrega. As mensagens nomeiam as variáveis antigas, mas os nomes em .env são os com VITE_.

Error in main function. 401 Incorrect API key provided: OpenAI não aceitou a chave. Copie-a novamente de sua conta OpenAI e verifique se ela não foi deletada.

Error in main function. 429 You exceeded your current quota: A chave funciona, mas a conta não tem crédito para gastar. Adicione crédito em Billing em sua conta OpenAI, depois pergunte novamente.

Error in main function. Cannot read properties of null (reading 'map'): OpenAI funcionou, mas Supabase retornou um erro em vez de filmes. Verifique a URL do projeto, use a chave publicável, e verifique se match_movies existe nesse mesmo projeto. Para o motivo exato, abra a aba Network das ferramentas de desenvolvedor, pergunte novamente, e clique na solicitação denominada match_movies.

O chatbot responde "Desculpe, não sei a resposta.": Tudo executou, mas Supabase não encontrou nenhum filme próximo o suficiente de sua pergunta. Pergunte sobre um filme que está em sua tabela. Se cada pergunta receber essa resposta, verifique no Supabase que a tabela tem linhas e que Row Level Security permite que a chave publicável as leia.

Error in main function. seguido por uma mensagem que nomeia o modelo (gpt-4 ou gpt-4o-mini): Verifique se index.js solicita gpt-4o-mini, não gpt-4. Após 14 de janeiro de 2027, OpenAI também deixa de servir gpt-4o-mini; daí em diante, use o substituto que sua página de depreciações nomeia.

JunoSolução de problemas Encontre a linha no terminal que começa com Error in main function. e corresponda as palavras após ela a um título em negrito acima. Se sua pergunta apenas desaparece, procure em config.js e .env primeiro.
JunoSolução de problemas As falhas vêm na ordem que o código executa: os pacotes, as leituras em config.js, a chave OpenAI, depois Supabase, depois seus dados. Corrija a primeira que encontrar; a próxima apenas aparece quando ela se foi.
JunoSolução de problemasfindNearestMatch ignora o error que Supabase retorna e chama data.map no null ao lado. Então uma URL errada, uma chave rejeitada e uma função faltante tudo lê como o mesmo null; a aba Network segura o motivo real.