Sistemas de Recomendação em Produção com LSH Forest, MinHash e Cache LRU Serverless (latência de 200ms)
Quando falamos de Inteligência Artificial hoje, quase toda a atenção vai para LLMs. Mas em produtos de alto volume — como e-commerce, delivery e plataformas de saúde — Sistemas de Recomendação Clássicos continuam sendo a
Quando falamos de Inteligência Artificial hoje, quase toda a atenção vai para LLMs. Mas em produtos de alto volume — como e-commerce, delivery e plataformas de saúde — Sistemas de Recomendação Clássicos continuam sendo a espinha dorsal da personalização em larga escala.
Durante 12 meses de pesquisa e extensão na Universidade Estadual de Feira de Santana (UEFS), sob orientação do Prof. Dr. João Batista da Rocha Junior, projetei e coloquei em produção o módulo de recomendação do LogicFarma (plataforma SaaS da Farmácia Universitária com mais de 4.700 operações registradas, 666 históricos clínicos avaliados e 1.060 medicamentos).
O desafio de engenharia era claro: como recomendar procedimentos e consultas personalizadas para centenas de pacientes em tempo real e em disparos em lote (e-mail/WhatsApp), rodando sobre funções Serverless com limites rígidos de memória e tempo de execução?
Neste artigo, compartilho a arquitetura Memory-First, a adaptação do Locality-Sensitive Hashing (LSH Forest) com MinHash e a estratégia de degradação graciosa em 4 níveis que levou a latência de consulta para ~200ms.
1. O gargalo da Filtragem Colaborativa tradicional O(N × M)
Na Filtragem Colaborativa Baseada no Usuário, queremos encontrar pacientes com histórico clínico semelhante ao paciente-alvo e recomendar procedimentos que esses vizinhos realizaram, mas que o paciente ainda não conhece.
A métrica natural para conjuntos binários (realizou / não realizou um procedimento) é a Similaridade de Jaccard:
J(A, B) = |A ∩ B| / |A ∪ B|
O problema é que comparar um paciente contra todos os outros a cada requisição tem custo linear no número de usuários e itens. Em um endpoint HTTP ou num disparo de mensagens para 300 pacientes de uma vez, calcular Jaccard exato no banco de dados é inviável.
2. MinHash + LSH Forest: busca aproximada em tempo sublinear
Baseado nos experimentos de Rocha-Junior et al. (2025) sobre sistemas de recomendação com LSH em e-commerce, substituímos a comparação exata por duas estruturas probabilísticas:
-
MinHash (
l = 200permutações): transforma o conjunto de procedimentos e consultas de cada paciente (de tamanho variável) em uma assinatura compacta de comprimento fixol = 200. A probabilidade de duas assinaturas coincidirem em uma posição é exatamente igual à Similaridade de Jaccard entre os conjuntos. Os experimentos mostraram quel = 200atinge o pico de Precisão Média (15,1%) mantendo Recall próximo de 92%, enquantol = 250degrada a relação custo/precisão em RAM. -
LSH Forest (Bawa et al., WWW 2005): em vez do LSH tradicional (que exige calibrar manualmente o número de buckets e o limiar de similaridade), utilizamos uma floresta de árvores de prefixos auto-ajustável (
MinHashLSHForest), consultandok_build = 80vizinhos na indexação ek_query = 20vizinhos em tempo real.
3. Adaptação do E-commerce para o Domínio Clínico
No modelo original de e-commerce, as interações possuem pesos graduados (visited = 1, cart_added = 4, bought = 8). No domínio farmacêutico, a interação é estritamente binária (o paciente realizou ou não o procedimento/consulta).
Fizemos três adaptações de domínio:
-
Unificação de pesos por co-ocorrência: cada item é codificado como
"Nome|Categoria"(ex.:"Glicemia|Procedimento","Cefaleia|Consulta"), e a pontuação dos itens candidatos nosk = 20vizinhos mais próximos é calculada pela frequência de co-ocorrência entre os vizinhos que possuem o item (excluindo o que o paciente já realizou). -
Filtro de elegibilidade e outliers: apenas perfis com
min_items = 2atémax_items = 100entram no índice LSH Forest. -
Filtro determinístico por restrição clínica de gênero: consultas exclusivas ao público feminino (como
"Cólica Menstrual") são filtradas tanto na saída do LSH quanto na pré-computação do ranking de fallback masculino (GLOBAL_MASCULINO).
4. Arquitetura Memory-First com Cache LRU e Batch Inference
Como a aplicação principal rodava em Next.js / TypeScript e a biblioteca de referência acadêmica para LSH (datasketch) estava em Python, separamos o motor de recomendação em funções Serverless Python integradas ao MongoDB.
Para evitar ler e desserializar o índice do banco a cada chamada, desenhamos uma arquitetura Memory-First:
[Cron Mensal Python] ---> Constrói LSH Forest (l=200) ---> Serializa blobs no MongoDB
|
[Next.js Top Tags] ---> POST /api/lsh/batch (até 300 pac.) ---> Cache LRU em RAM (50 farmácias)
-
Cold Start (~2 a 3s): carrega os pickle blobs (
forestBlob,minhashesBlob,fallbacksBlob,itemsByPatientBlob) do MongoDB e hidrata o container. - Warm Start (~0,2 a 0,3s): o Cache LRU em RAM responde diretamente da memória da função Serverless, sem tocar no banco.
-
Endpoint em Lote (
/api/lsh/batch): quando o farmacêutico dispara comunicados com Top Tags (#Top3ProcedimentosRec,#Top3ConsultasRec), o módulorecommendationTagResolver.tsagrupa até 300 pacientes em uma única chamada HTTP POST, carregando o cache da farmácia uma só vez.
5. Degradação Graciosa em 4 Níveis (Zero Falha no Disparo)
Em um sistema real, o algoritmo de recomendação nunca pode derrubar o fluxo principal de comunicação (seja por cold start de um paciente novo sem histórico, seja por timeout de rede). Implementamos 4 níveis de degradação:
-
LSH Completo (
lsh): os 20 vizinhos do LSH Forest preenchem todas asksugestões pedidas. -
LSH Parcial + Suplementação (
lsh_partial): quando os vizinhos têm pouca variedade, o sistema completa as vagas faltantes com o Fallback Global segmentado por gênero (GLOBAL_FEMININOouGLOBAL_MASCULINO). -
Fallback de Cold Start (
fallback): paciente recém-cadastrado (sem histórico) recebe imediatamente o ranking global segmentado pré-computado em memória, ou via leitura direta da coleçãorecomendacoesMensais. - Fail-safe de Timeout (30s): se a API Python falhar, as Top Tags degradam para string vazia e a mensagem transacional segue normalmente.
Em produção na Farmácia Universitária da UEFS, o indexador processou 666 históricos de pacientes em 4 unidades, indexando 353 perfis elegíveis e 1.978 registros clínicos em menos de 1,7 segundo.
Links relacionados
- Código de referência e Model Card no Hugging Face: huggingface.co/TheAndr3/lsh-forest-clinical-recommender
- GitHub: github.com/TheAndr3
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.