Embedbase é uma API de código aberto para construir, armazenar e recuperar embeddings.
Hoje vamos construir um mecanismo de busca para as redações de Paul Graham que usaremos com os Atalhos da Siri da Apple, por exemplo, fazendo perguntas à Siri sobre essas redações.
“Embeddings” são um conceito em aprendizado de máquina que permite comparar dados.
Não vamos nos aprofundar no tópico técnico de incorporações hoje.
Uma maneira de pensar sobre "incorporações" é como juntar coisas semelhantes em uma sacola. Então, se você tem uma sacola de brinquedos e quer encontrar um determinado brinquedo, você olha na sacola e vê quais outros brinquedos estão próximos a ela para descobrir qual você quer. Um computador pode fazer a mesma coisa com palavras, juntando palavras semelhantes em um saco e, em seguida, encontrando a palavra que deseja com base nas outras palavras próximas a ela.
Quando você deseja usar incorporações em seu software de produção, precisa ser capaz de armazená-las e acessá-las facilmente.
Existem muitos bancos de dados vetoriais e modelos NLP para armazenar e calcular embeddings. Existem também alguns truques adicionais para lidar com incorporações.
Por exemplo, pode se tornar caro e ineficiente recalcular quando não é necessário, por exemplo, se a nota contiver “cachorro” e depois “cachorro”, você não necessariamente deseja recalcular porque as informações alteradas podem não ser úteis.
Além disso, esses bancos de dados vetoriais exigem uma curva de aprendizado acentuada e a necessidade de entender o aprendizado de máquina.
O Embedbase permite sincronizar e pesquisar dados semanticamente sem saber nada sobre aprendizado de máquina, bancos de dados vetoriais e otimização de cálculos em algumas linhas de código.
Na ordem, iremos:
git clone https://github.com/another-ai/embedbase cd embedbase
Acesse o site da Pinecone , faça o login e crie um índice:
Vamos chamá-lo de “paul” e usar a dimensão “1536” ( importante acertar esse número , sob o capô, é o “tamanho” da estrutura de dados OpenAI “embeddings”), as outras configurações são menos importantes.
Você precisa obter sua chave de API do Pinecone que permitirá que o Embedbase se comunique com o Pinecone:
Agora você precisa obter sua configuração OpenAI em https://platform.openai.com/account/api-keys (crie uma conta se necessário).
Pressione “Criar uma nova chave”:
Além disso, obtenha o ID da sua organização aqui:
Agora escreva e preencha os valores no arquivo “config.yaml” ( no diretório embedbase ):
# embedbase/config.yaml # https://app.pinecone.io/ pinecone_index: "my index name" # replace this with your environment pinecone_environment: "us-east1-gcp" pinecone_api_key: "" # https://platform.openai.com/account/api-keys openai_api_key: "sk-xxxxxxx" # https://platform.openai.com/account/org-settings openai_organization: "org-xxxxx"
🎉 Você pode executar o Embedbase agora!
Inicie o Docker, se você não o tiver, instale-o seguindo as instruções no site oficial .
Agora execute o Embedbase:
docker-compose up
Isso é opcional, fique à vontade para pular para a próxima parte!
Se estiver motivado, você pode implantar o Embedbase no Google Cloud Run. Certifique-se de ter um projeto do Google Cloud e ter instalado a linha de comando “gcloud” por meio da documentação oficial .
# login to gcloud gcloud auth login # Get your Google Cloud project ID PROJECT_ID=$(gcloud config get-value project) # Enable container registry gcloud services enable containerregistry.googleapis.com # Enable Cloud Run gcloud services enable run.googleapis.com # Enable Secret Manager gcloud services enable secretmanager.googleapis.com # create a secret for the config gcloud secrets create EMBEDBASE_PAUL_GRAHAM --replication-policy=automatic # add a secret version based on your yaml config gcloud secrets versions add EMBEDBASE_PAUL_GRAHAM --data-file=config.yaml # Set your Docker image URL IMAGE_URL="gcr.io/${PROJECT_ID}/embedbase-paul-graham:0.0.1" # Build the Docker image for cloud deployment docker buildx build . --platform linux/amd64 -t ${IMAGE_URL} -f ./search/Dockerfile # Push the docker image to Google Cloud Docker registries # Make sure to be authenticated https://cloud.google.com/container-registry/docs/advanced-authentication docker push ${IMAGE_URL} # Deploy Embedbase to Google Cloud Run gcloud run deploy embedbase-paul-graham \ --image ${IMAGE_URL} \ --region us-central1 \ --allow-unauthenticated \ --set-secrets /secrets/config.yaml=EMBEDBASE_PAUL_GRAHAM:1
Os rastreadores da Web permitem que você baixe todas as páginas de um site, é o algoritmo subjacente usado pelo Google.
Clone o repositório e instale as dependências:
git clone https://github.com/another-ai/embedbase-paul-graham cd embedbase-paul-graham npm i
Vejamos o código, se você está sobrecarregado com todos os arquivos necessários para um projeto Typescript, não se preocupe e ignore-os.
// src/main.ts // Here we want to start from the page that list all Paul's essays const startUrls = ['http://www.paulgraham.com/articles.html']; const crawler = new PlaywrightCrawler({ requestHandler: router, }); await crawler.run(startUrls);
Você pode ver que o rastreador é inicializado com “rotas”, quais são essas rotas misteriosas?
// src/routes.ts router.addDefaultHandler(async ({ enqueueLinks, log }) => { log.info(`enqueueing new URLs`); await enqueueLinks({ // Here we tell the crawler to only accept pages that are under // "http://www.paulgraham.com/" domain name, // for example if we find a link on Paul's website to an url // like "https://ycombinator.com/startups" if it will ignored globs: ['http://www.paulgraham.com/**'], label: 'detail', }); }); router.addHandler('detail', async ({ request, page, log }) => { // Here we will do some logic on all pages under // "http://www.paulgraham.com/" domain name // for example, collecting the page title const title = await page.title(); // getting the essays' content const blogPost = await page.locator('body > table > tbody > tr > td:nth-child(3)').textContent(); if (!blogPost) { log.info(`no blog post found for ${title}, skipping`); return; } log.info(`${title}`, { url: request.loadedUrl }); // Remember that usually AI models and databases have some limits in input size // and thus we will split essays in chunks of paragraphs // split blog post in chunks on the \n\n const chunks = blogPost.split(/\n\n/); if (!chunks) { log.info(`no blog post found for ${title}, skipping`); return; } // If you are not familiar with Promises, don't worry for now // it's just a mean to do things faster await Promise.all(chunks.flatMap((chunk) => { const d = { url: request.loadedUrl, title: title, blogPost: chunk, }; // Here we just want to send the page interesting // content into Embedbase (don't mind Dataset, it's optional local storage) return Promise.all([Dataset.pushData(d), add(title, chunk)]); })); });
O que é add() ?
const add = (title: string, blogPost: string) => { // note "paul" in the URL, it can be anything you want // that will help you segment your data in // isolated parts const url = `${baseUrl}/v1/paul`; const data = { documents: [{ data: blogPost, }], }; // send the data to Embedbase using "node-fetch" library fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }).then((response) => { return response.json(); }).then((data) => { console.log('Success:', data); }).catch((error) => { console.error('Error:', error); }); };
Agora você pode executar o rastreador, deve levar menos de um minuto para baixar e ingerir tudo no Embedbase.
Créditos OpenAI serão usados, por menos de <$1
npm start
Se você implantou o Embedbase na nuvem, use
# you can get your cloud run URL like this: CLOUD_RUN_URL=$(gcloud run services list --platform managed --region us-central1 --format="value(status.url)" --filter="metadata.name=embedbase-paul-graham") npm run playground ${CLOUD_RUN_URL}
Você deve ver alguma atividade em seu terminal (tanto o contêiner do Embedbase Docker quanto o processo do nó) sem erros ( sinta-se à vontade para pedir ajuda caso contrário ).
No repositório de exemplo você pode observar “ src/playground.ts ” que é um script simples que permite interagir com o Embedbase em seu terminal, o código é direto:
// src/playground.ts const search = async (query: string) => { const url = `${baseUrl}/v1/paul/search`; const data = { query, }; return fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }).then((response) => { return response.json(); }).then((data) => { console.log('Success:', data); }).catch((error) => { console.error('Error:', error); }); }; const p = prompt(); // this is an interactive terminal that let you search in paul graham // blog posts using semantic search // It is an infinite loop that will ask you for a query // and show you the results const start = async () => { console.log('Welcome to the Embedbase playground!'); console.log('This playground is a simple example of how to use Embedbase'); console.log('Currently using Embedbase server at', baseUrl); console.log('This is an interactive terminal that let you search in paul graham blog posts using semantic search'); console.log('Try to run some queries such as "how to get rich"'); console.log('or "how to pitch investor"'); while (true) { const query = p('Enter a semantic query:'); if (!query) { console.log('Bye!'); return; } await search(query); } }; start();
Você pode executá-lo assim se estiver executando o Embedbase localmente:
npm run playground
Ou, assim, se você implantou o Embedbase na nuvem:
npm run playground ${CLOUD_RUN_URL}
Resultados:
Tempo de diversão! Vamos construir um atalho Apple Siri para poder fazer perguntas à Siri sobre os ensaios de Paul Graham 😜
Primeiro, vamos iniciar os Atalhos da Apple:
Crie um novo atalho:
Chamaremos esse atalho de “Pesquisar Paul” (esteja ciente de que será assim que você pedirá à Siri para iniciar o Atalho, então escolha algo fácil)
Em inglês simples, esse atalho faz uma consulta ao usuário e chama o Embedbase com ele, e diz à Siri para pronunciar em voz alta as redações que encontrou.
“Get for in” extrairá a propriedade “similarities” da resposta do Embedbase
“Repetir com cada item em” irá, para cada semelhança:
“Combine” irá “juntar” os resultados com uma nova linha
(Opcional, mostrarei como abaixo) Este é um truque divertido que você pode adicionar ao atalho para tempero, usando o OpenAI GPT3 para transformar um pouco do texto do resultado para soar melhor quando a Siri o pronunciar
Montamos o resultado em um “Texto” para ser compatível com a voz
Peça à Siri para falar
Você pode transformar os resultados em um texto mais agradável usando este atalho GPT3 funcional
(preencha o valor “Autorização” com “Portador [SUA CHAVE OPENAI]”)
Com o Embedbase, você pode criar um produto semântico em pouco tempo, sem ter a dor de cabeça de criar, armazenar e recuperar incorporações, mantendo o custo baixo.