Skip to content

Tox1469/embed-search

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CI License Release Stars


embed-search

Busca semântica com embeddings — faça chunking de textos, gere embeddings via OpenAI (ou qualquer API compatível) e execute buscas por similaridade usando cosine similarity em memória ou pgvector no PostgreSQL.

Instalação

npm install embed-search
# com suporte a pgvector
npm install embed-search pg

Uso

Pipeline completo (chunking + embedding + busca)

import { chunkDocument } from 'embed-search/chunker';
import { Embedder, cosineSimilarity } from 'embed-search/embedder';
import { InMemoryVectorStore } from 'embed-search';

const embedder = new Embedder({
  apiKey: process.env.OPENAI_API_KEY!,
  model: 'text-embedding-3-small',
});

// 1. Dividir documento em chunks
const chunks = chunkDocument({
  id: 'doc-1',
  content: `Texto longo do seu documento aqui...
  
  Pode ser um artigo, contrato, FAQ ou qualquer texto.`,
  metadata: { fonte: 'manual', idioma: 'pt-BR' },
});

// 2. Gerar embeddings para todos os chunks
const chunksComEmbeddings = await embedder.embedChunks(chunks);

// 3. Armazenar
const store = new InMemoryVectorStore();
await store.upsert(chunksComEmbeddings);

// 4. Buscar por similaridade
const queryEmbedding = await embedder.embedText('como faço para cancelar minha conta?');
const resultados = await store.query(queryEmbedding, { topK: 3, minScore: 0.75 });

for (const r of resultados) {
  console.log(`Score: ${r.score.toFixed(3)} | ${r.chunk.text.slice(0, 100)}...`);
}

Chunking avançado

import { chunkText, chunkByTokenEstimate, splitByMarkdownHeadings } from 'embed-search/chunker';

// Chunking por caracteres com overlap
const chunks = chunkText(textoLongo, {
  chunkSize: 512,
  chunkOverlap: 64,
  separator: '\n\n',
  minChunkSize: 50,
});

// Chunking estimado por tokens (1 token ≈ 4 chars)
const chunksTokens = chunkByTokenEstimate(texto, 256, 20);

// Dividir markdown por headings
const secoes = splitByMarkdownHeadings(conteudoMarkdown);

Busca com pgvector (produção)

import { PgVectorStore } from 'embed-search';

const store = new PgVectorStore({
  connectionString: process.env.DATABASE_URL!,
  tableName: 'embeddings',
  dimensions: 1536,
});

// SQL para criar a tabela (rodar uma vez)
console.log(PgVectorStore.createTableSQL('embeddings', 1536));

await store.upsert(chunksComEmbeddings);
const resultados = await store.query(queryEmbedding, { topK: 5, minScore: 0.7 });

Re-ranking com boost de palavras-chave

import { rerank } from 'embed-search';

const rerankeados = rerank(resultados, 'cancelar conta assinatura');

Utilitários de embedding

import { cosineSimilarity, dotProduct, normalizeVector } from 'embed-search/embedder';

const similaridade = cosineSimilarity(embeddingA, embeddingB); // 0 a 1
const vetorNormalizado = normalizeVector(embedding);

Licença

MIT © 2026 Tox

built by tox

About

Semantic search with pgvector and OpenAI embeddings

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors