Publicado em: 09, janeiro 2026
Antes de mais nada, vale entender o conceito: ao invés de comparar apenas palavras, busca semântica converte textos e consultas em vetores numéricos (embeddings) que capturam o significado do conteúdo. Com isso, sua aplicação consegue encontrar resultados relevantes mesmo que os termos pesquisados não apareçam literalmente no texto — porque eles ocupam posições próximas no espaço vetorial.
✔️ Laravel – framework PHP
✔️ PostgreSQL com pgvector – extensão para armazenar e buscar vetores
✔️ OpenAI (ou outro serviço de embeddings) – gerar representações vetoriais dos textos
✔️ SQL direto – consultas de similaridade sem camadas de abstração como Laravel Scout
No PostgreSQL você precisa habilitar a extensão que permite armazenar vetores:
CREATE EXTENSION IF NOT EXISTS vector;
Essa extensão adiciona um tipo de dado vector ao PostgreSQL, possibilitando operações de similaridade diretamente no banco.
Na sua migration do Laravel, inclua uma coluna para guardar o vetor resultante do embedding:
Schema::table('articles', function (Blueprint $table) {
$table->vector('embedding', 1536)->nullable();
});O número 1536 representa a dimensão escolhida para os embeddings — ajuste conforme o modelo de linguagem que você usar.
Para cada item que você quer buscar (por exemplo, um artigo, produto ou FAQ), gere um embedding usando uma API de linguagem, como a de OpenAI:
$client = new \OpenAI\Client(env('OPENAI_API_KEY'));
$response = $client->embeddings()->create([
'model' => 'text-embedding-3-small',
'input' => $article->content,
]);
$embedding = $response->data[0]->embedding;
$article->embedding = $embedding;
$article->save();
Esse vetor agora representa semanticamente o conteúdo do artigo. Você pode fazer isso em Jobs em background para não travar a experiência do usuário.
Quando o usuário faz uma consulta, você também converte essa pesquisa em um embedding:
$queryEmbedding = $client->embeddings()->create([
'model' => 'text-embedding-3-small',
'input' => $request->query('search')
])->data[0]->embedding;Em seguida você faz uma consulta SQL para encontrar os registros mais próximos no espaço vetorial — ou seja, semanticamente mais similares:
$results = DB::select(
"SELECT *, embedding <=> :query AS distance
FROM articles
ORDER BY embedding <=> :query
LIMIT 10",
['query' => $queryEmbedding]
);Aqui, o operador <=> calcula a distância cosseno entre vetores no PostgreSQL habilitado com a extensão pgvector — ou seja, ele mede o quão semanticamente próximos dois vetores estão. Quanto menor a distância cosseno, mais semanticamente similares os textos são, e mais relevante será o resultado para a consulta do usuário.
Quando você usa similaridade vetorial (como com embeddings e o operador <=> no PostgreSQL com pgvector), o valor retornado representa a distância cosseno entre dois vetores que codificam significado (por exemplo: a consulta do usuário e o texto de um documento).
👉 Distância cosseno é uma maneira de medir o ângulo entre dois vetores no espaço multidimensional — quanto menor a distância, mais parecidos semanticamente eles são.
Vamos pegar um exemplo, distance = 0,4523423
💡 Um valor de 0,4523423 significa que os vetores — ou seja, o texto do documento e a consulta — têm um ângulo considerável entre eles:
✔️ Não são semanticamente idênticos
✔️ Têm alguma relação de significado, mas não tão próxima quanto um valor menor (por exemplo ~0,1–0,2)
Isso pode acontecer quando:
📌 Em buscas semânticas, geralmente ordenamos os resultados do menor para o maior valor de distância — ou seja, quanto menor a distância cosseno, mais relevante o resultado tende a ser.
Pense nos vetores como setas apontando em direções no espaço:
✅ Distância = 0 → as setas apontam quase exatamente para a mesma direção.
📍 Distância ≈ 0,45 → as setas ainda estão relativamente alinhadas, mas com um ângulo perceptível entre elas — ou seja, existe alguma conexão, mas não uma correspondência perfeita.
✅ Pré-indexe os embeddings ao criar/atualizar documentos
✅ Realize a geração de embeddings em background com Jobs
✅ Use caches de resultados populares para reduzir chamadas à API
✅ Combine com busca full-text tradicional para um sistema híbrido ainda mais eficaz (semântica + palavras-chave)
✔️ Resultados relevantes mesmo sem termos exatos
✔️ Busca por intenção e significado em vez de apenas correspondência textual
✔️ Funciona com qualquer texto estruturado — artigos, produtos, FAQs, etc.
✔️ Escalável, porque a maior parte da lógica fica no banco de dados
Implementar busca semântica no Laravel sem usar frameworks como Scout é totalmente possível e valioso. Com PostgreSQL + pgvector + embeddings, você cria um sistema de busca que realmente entende o conteúdo, entregando resultados mais inteligentes e relevantes aos seus usuários — e tudo sem depender de ferramentas externas para indexação.
Mais de 10 anos de experiência com Laravel e sólidos conhecimentos em frameworks front-end, como ReactJS, React Native e Vue JS. Experiência em Design de Serviço. No primeiro projeto profissional como júnior, desenvolveu em e-commerce para a maior indústria de equipamentos odontológicos da América Latina. Atualmente, atua como Full Stack Engineer Specialist em uma grande multinacional. Lidera decisões técnicas e é um suporte fundamental para a equipe de desenvolvimento.