Como implementar o Vector Search do SQL Database
Vector Search é um recurso do SQL Database da Azion que permite aos clientes implementar mecanismos de busca semântica. Enquanto os modelos de busca tradicionais visam encontrar correspondências exatas, como correspondências de palavras-chave, os modelos de busca vetorial usam algoritmos especializados para identificar itens semelhantes com base em suas representações matemáticas, ou embeddings vetoriais.
Saiba mais sobre o Vector SearchComo exemplo de implementação, este guia abordará a configuração da lógica de busca vetorial em uma aplicação TypeScript, com um banco de dados usando a biblioteca Langchain com OpenAI e a SQL Database API da Azion.
Pré-requisitos
- Gere um personal token da Azion.
- Gere uma OpenAI API Key.
- Instale a Azion CLI.
- Crie uma aplicação TypeScript.
- Como no exemplo, você pode usar a Azion CLI para criar uma aplicação Simple Typescript Router.
- Configure o SQL Database.
- Instale as Azion Libraries.
Configure o arquivo main.ts
A primeira etapa é configurar o arquivo main.ts, o ponto de entrada para sua implementação. Ele estabelece a conexão com a API da Azion e a OpenAI, configura o ambiente usando credenciais e contém a lógica principal para realizar e testar consultas de busca baseadas em vetores.
- No arquivo
.env, adicione seu personal token da Azion e a OpenAI API Key como variáveis. - Configure o arquivo
main.ts, usando a seguinte estrutura como exemplo:
import { OpenAIEmbeddings } from "@langchain/openai";import { useExecute, useQuery, createDatabase } from "azion/sql";
export default async function vectorSearch() {
// // Create the database const {data:createDatabaseData, error:createDatabaseError} = await createDatabase('vectorDatabase',{debug:true})
if (createDatabaseError) { return Response.json({ error: createDatabaseError.message }, { status: 500 }); }
// // Setup the database // // Create the embeddings column according to the dimension of the embeddings model // // In this case, the text-embedding-3-small model has 1536 dimensions // // You should also create the index, which makes the search faster! const setupStatements = [ `CREATE TABLE documents ( id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT NOT NULL, embedding F32_BLOB(1536) );`, `CREATE INDEX documents_idx ON documents ( libsql_vector_idx(embedding, 'metric=cosine') );` ];
// Here, use useExecute, which supports create and insert statements const {data:setupData, error:setupError} = await useExecute('vectorDatabase',setupStatements)
if (setupError) { return Response.json({ error: setupError.message }, { status: 500 }); }
// Create the embeddings model const embeddings = new OpenAIEmbeddings({ model: "text-embedding-3-small", verbose: false, apiKey: process.env.OPENAI_API_KEY });
// Sample documents about France, England, and Brazil const documents = [ "Paris is the capital of France", "The Eiffel Tower is a French landmark", "London is the capital of England", "Big Ben is located in London", "Brasilia is the capital of Brazil", "The Amazon rainforest is in Brazil", "French cuisine is world-famous", "Tea is popular in England", "The English Channel separates Britain and France" ];
// Generate embeddings for all documents and prepare statements const insertStatements = []; for (const doc of documents) { const embedding = await embeddings.embedQuery(doc); insertStatements.push( `INSERT INTO documents (content, embedding) VALUES ('${doc}', vector('[${embedding}]'));` ); }
// Here, use useExecute, which supports insert statements const {data:insertData, error:insertError} = await useExecute('vectorDatabase',insertStatements,{debug:true})
if (insertError) { return Response.json({ error: insertError.message }, { status: 500 }); }
// Search for the most similar document to the query // The same embedding model is used to generate the query embedding const query = "What is the capital of Brazil?"; const queryEmbedding = await embeddings.embedQuery(query);
// Prepare the search statement // The vector_top_k function is used to find the most similar documents to the query const searchStatements = [ ` SELECT id, content FROM documents WHERE rowid IN vector_top_k('documents_idx', vector('[${queryEmbedding}]'), 2) ` ];
const {data:searchData, error:searchError} = await useQuery('vectorDatabase',searchStatements)
if (searchError) { return Response.json({ error: searchError.message }, { status: 500 }); }
return Response.json({ data: searchData });}Em resumo, este código cria uma função TypeScript chamada vectorSearch, que implementa um recurso de busca semântica no SQL Database da Azion:
- Configuração do banco de dados: conecta-se a um banco de dados (
vectorDatabase) e cria uma tabeladocumentscomcontente uma columnaembedding, indexando os embeddings para buscas vetoriais mais rápidas. - Modelo de embedding: utiliza o modelo
text-embedding-3-smallpara gerar embeddings vetoriais para cada documento. - Inserção de dados: insere dados de texto de exemplo com embeddings no banco de dados.
- Execução de consultas: busca os documentos mais relevantes relacionados a uma consulta dada, usando similaridade para classificar os resultados.
- Tratamento de erros: cada operação principal possui uma configuração de tratamento de erros, garantindo que uma mensagem de erro em JSON seja retornada se ocorrer um erro.
Execute e teste a busca vetorial
Agora, é hora de executar sua aplicação e testar a implementação da busca vetorial. Para fazer isso:
- Crie sua aplicação localmente usando o comando
azion build. - Inicie um servidor de desenvolvimento local para a aplicação com o comando
azion dev. - Com a aplicação em execução, faça um query no SQL Database da Azion para criar o banco de dados na plataforma.
- Envie seu query para o localhost com o valor.
- Por exemplo:
What is the capital of Brazil?
- Por exemplo:
- O servidor deve interpretar a consulta e retornar uma resposta apropriada.
- Neste caso, o servidor retorna uma representação vetorial do query e você receberá uma lista dos documentos mais semelhantes à consulta.
- Se estiver pesquisando no shell do SQL Database, você pode encontrar as informações inseridas na tabela do banco de dados
vectorDatabase.
Pronto! Você implementou uma busca vetorial em sua aplicação. Agora você pode refiná-la e adaptá-la para atender melhor ao seu caso de uso.