<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Houssan Ali Hijazi - Software Developer</title><link href="https://www.hussan.com.br/" rel="alternate"/><link href="https://www.hussan.com.br/feeds/all.atom.xml" rel="self"/><id>https://www.hussan.com.br/</id><updated>2026-07-29T11:00:00-03:00</updated><entry><title>Como construí o MitAI: um chatbot que responde preço, cotação e dúvidas sobre lojas sem inventar dados</title><link href="https://www.hussan.com.br/blog/mitai-chatbot-open-webui.html" rel="alternate"/><published>2026-07-29T11:00:00-03:00</published><updated>2026-07-29T11:00:00-03:00</updated><author><name>Houssan A. Hijazi</name></author><id>tag:www.hussan.com.br,2026-07-29:/blog/mitai-chatbot-open-webui.html</id><summary type="html">&lt;p&gt;Open WebUI + function calling + RAG na frente da API do Lojas Paraguai, pra fechar a porta que mais mata projeto de chatbot em e-commerce: o modelo alucinar preço.&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Como construí o MitAI: um chatbot que responde preço, cotação e dúvidas sobre lojas sem inventar dados&lt;/h1&gt;
&lt;p&gt;Open WebUI + function calling + RAG na frente da API do Lojas Paraguai, pra fechar a porta que mais mata projeto de chatbot em e-commerce: o modelo alucinar preço.&lt;/p&gt;
&lt;h2&gt;🧢 Por que "MitAI"&lt;/h2&gt;
&lt;p&gt;O nome é um trocadilho: "mitã'i" (ou mitaí) significa "criança" no guarani paraguaio, forma carinhosa e cotidiana de chamar os pequenos no Paraguai. Aqui vira "mit-AI", a IA do &lt;a href="https://www.lojasparaguai.com.br/mitai"&gt;Lojas Paraguai&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;🎯 O problema&lt;/h2&gt;
&lt;p&gt;No Lojas Paraguai o usuário quer três coisas: "quanto custa esse produto?", "a quanto tá o dólar hoje?" e "essa loja é confiável?". Parece trabalho perfeito pra um chatbot. Mas num site de comparação de preços existe uma falha que mata o projeto inteiro: o modelo &lt;strong&gt;inventar&lt;/strong&gt; o preço.&lt;/p&gt;
&lt;p&gt;LLM sozinho, sem ferramentas, alucina com confiança. Testei a mesma pergunta, "iphone 17 pro max 256gb", três vezes seguidas, e recebi &lt;strong&gt;três preços diferentes&lt;/strong&gt;. Num site onde preço correto é o produto, isso é inaceitável. O modelo precisa &lt;strong&gt;buscar&lt;/strong&gt; o dado real e atualizado, não recitar de memória.&lt;/p&gt;
&lt;h2&gt;🛠️ A solução: Open WebUI + tools na própria API&lt;/h2&gt;
&lt;p&gt;Em vez de deixar o modelo responder de cabeça, ele chama ferramentas que batem no backend do Lojas Paraguai:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dolar&lt;/code&gt;: cotação real do dia e gráfico semanal&lt;/li&gt;
&lt;li&gt;&lt;code&gt;buscar-produto&lt;/code&gt; / &lt;code&gt;detalhe-produto&lt;/code&gt;: preço, lojas que vendem e detalhes do produto&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lojas&lt;/code&gt;: informações das lojas cadastradas&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fluxo é function calling clássico:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Modelo decide qual tool chamar, a partir da pergunta do usuário&lt;/li&gt;
&lt;li&gt;Backend executa a chamada na API interna do catálogo&lt;/li&gt;
&lt;li&gt;API devolve o resultado&lt;/li&gt;
&lt;li&gt;Modelo formata a resposta em linguagem natural, sem alterar o dado&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;O resultado: aquele mesmo "iphone 17 pro max 256gb" que antes dava três preços diferentes agora retorna sempre o valor do banco, igual em toda tentativa. Preço não vem mais da imaginação do modelo, vem do banco.&lt;/p&gt;
&lt;h2&gt;🧩 Por que Open WebUI&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://openwebui.com"&gt;Open WebUI&lt;/a&gt; é uma plataforma open source que roda em Docker e serve como camada de orquestração na frente do modelo. Criei um modelo próprio com base no &lt;code&gt;gpt-4.1-mini&lt;/code&gt; da OpenAI, adicionei minha FAQ na base de conhecimento (RAG) e criei as tools de acesso à minha API.&lt;/p&gt;
&lt;p&gt;Ele expõe uma API compatível com OpenAI (&lt;code&gt;/api/chat/completions&lt;/code&gt;), então o backend do Lojas Paraguai conversa com o Open WebUI exatamente como conversaria direto com a OpenAI, troca de provider é transparente. E já traz pronto: gestão de tools, workspaces, RAG, chaves de API e base de conhecimento. Isso poupou de construir do zero todo o encanamento de function calling e recuperação de contexto.&lt;/p&gt;
&lt;h2&gt;⚙️ A camada que fecha a porta pra alucinação&lt;/h2&gt;
&lt;p&gt;Passar o JSON cru da API pro modelo &lt;strong&gt;não resolve&lt;/strong&gt;. Testei assim primeiro, e sem enriquecer a resposta o modelo simplesmente inventa em cima do que falta:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cotação do dólar sem o cálculo pronto → modelo chuta uma cotação errada pra converter preço&lt;/li&gt;
&lt;li&gt;Slug de produto sem URL montada → modelo adivinha um caminho, que dá 404&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A correção foi uma camada de &lt;code&gt;enrich()&lt;/code&gt; na API, que já entrega o dado mastigado, exatamente o que a tool deveria trazer:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;cota&lt;/span&gt;çã&lt;span class="nv"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;×&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt;ó&lt;span class="nv"&gt;lar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;valor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;em&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;BRL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;j&lt;/span&gt;á&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;calculado&lt;/span&gt;
&lt;span class="nv"&gt;slug&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;→&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;URL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;completa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;á&lt;span class="nv"&gt;lida&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;produto&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Com isso o modelo não tem mais espaço pra "completar" nada: o dado que falta pra montar a resposta já vem pronto na tool.&lt;/p&gt;
&lt;p&gt;Fechei ainda mais a porta com &lt;code&gt;temperature = 0.2&lt;/code&gt;. Chatbot não é lugar pra criatividade, quero a resposta mais determinística possível em cima do dado que a tool entregou, não variação estilística. Temperatura baixa reduz a margem do modelo pra "florear" e inventar em cima do fato.&lt;/p&gt;
&lt;h2&gt;🎓 Principais lições&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dados crus não bastam.&lt;/strong&gt; Se falta um cálculo ou uma montagem de URL pro modelo terminar a resposta, ele preenche o vazio inventando. Enriquecer na API, não confiar que o modelo "resolve" em cima do JSON cru.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Num domínio específico, LLM é orquestrador, não fonte da verdade.&lt;/strong&gt; Ele decide &lt;strong&gt;o que&lt;/strong&gt; buscar (qual tool, com quais parâmetros); o dado sempre vem da API.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alucinação é o comportamento padrão quando a tool falha ou o dado chega incompleto.&lt;/strong&gt; Não é uma falha rara do modelo, é o que ele faz por padrão quando falta contexto.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Temperatura baixa em chatbot factual não é sobre estilo, é sobre correção.&lt;/strong&gt; Menos variação = menos chance do modelo se afastar do dado real que a tool trouxe.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;🔗 Onde testar&lt;/h2&gt;
&lt;p&gt;Chat disponível em &lt;a href="https://www.lojasparaguai.com.br/mitai"&gt;www.lojasparaguai.com.br/mitai&lt;/a&gt;. Além do site, o MitAI também está no app mobile do Lojas Paraguai.&lt;/p&gt;</content><category term="Inteligência Artificial, Python, Open WebUi"/></entry><entry><title>Como reduzir o custo de categorizar milhares de produtos treinando um modelo local</title><link href="https://www.hussan.com.br/blog/categorizar-produtos-modelo-local.html" rel="alternate"/><published>2026-06-29T11:00:00-03:00</published><updated>2026-06-29T11:00:00-03:00</updated><author><name>Houssan A. Hijazi</name></author><id>tag:www.hussan.com.br,2026-06-29:/blog/categorizar-produtos-modelo-local.html</id><summary type="html">&lt;p&gt;Como reduzimos o custo de categorizar milhares de produtos treinando um modelo local que resolve parte dos casos a custo zero antes de chamar uma LLM.&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Categorização Híbrida de Produtos: Sklearn local + IA como fallback&lt;/h1&gt;
&lt;p&gt;Como reduzimos o custo de categorizar milhares de produtos treinando um modelo local que resolve parte dos casos a custo zero antes de chamar uma LLM.&lt;/p&gt;
&lt;h2&gt;O problema&lt;/h2&gt;
&lt;p&gt;O catálogo do Lojas Paraguai recebe milhares de produtos novos vindos do crawler, e cada um precisa de &lt;strong&gt;categoria&lt;/strong&gt; e &lt;strong&gt;marca&lt;/strong&gt; para aparecer corretamente no site. Categorizar à mão é inviável, e a primeira solução automatizada, enviar todos os produtos para uma LLM, funcionava, mas com dois custos altos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tempo&lt;/strong&gt;: alguns segundos por batch via API (Ollama/Google/OpenAI). &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dinheiro&lt;/strong&gt;: cada batch de produtos era uma chamada de API paga, mesmo para casos óbvios como "Samsung Galaxy A50" → Smartphones / Samsung.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A maioria dos produtos é trivial de classificar. Pagar uma LLM para resolver o óbvio não fazia sentido.&lt;/p&gt;
&lt;h2&gt;A solução&lt;/h2&gt;
&lt;p&gt;Uma estratégia &lt;strong&gt;híbrida em duas fases&lt;/strong&gt;, implementada no comando &lt;code&gt;categorize_products_hybrid&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fase 1, Sklearn (local, custo zero, mais rápido)&lt;/strong&gt;
   Um classificador treinado com os próprios dados do banco prediz categoria e marca a partir do nome do produto. Se a confiança for ≥ ao threshold (padrão 0.75), o resultado é aceito direto.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fase 2, LLM (fallback, tem custo, mais lento)&lt;/strong&gt;
   Só os produtos em que o modelo local ficou inseguro vão para a IA (via LiteLLM, padrão &lt;code&gt;gemini-2.5-flash-lite&lt;/code&gt;), que retorna nomes de categoria/marca resolvidos contra o banco por um mapa de aliases. Esse custo de api é cortado com a possibilidade do uso de modelos locais.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A fração que o modelo local resolve sozinho &lt;strong&gt;depende do mix de produtos&lt;/strong&gt;: em itens comuns é alta, na cauda longa (nomes ruins, produtos raros, marcas obscuras) a confiança cai e a LLM assume. Cada produto que o Sklearn resolve é tempo e custo de API economizados.&lt;/p&gt;
&lt;p&gt;Comparativo por &lt;strong&gt;batch de 50 produtos&lt;/strong&gt; (mesma carga nas duas colunas):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Métrica&lt;/th&gt;
&lt;th&gt;Sklearn (local)&lt;/th&gt;
&lt;th&gt;LLM (se tudo fosse IA)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tempo/batch (50)&lt;/td&gt;
&lt;td&gt;&amp;lt;50ms&lt;/td&gt;
&lt;td&gt;alguns segundos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custo API/batch&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;~0.005 USD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Acurácia&lt;/td&gt;
&lt;td&gt;cat ~94% · marca ~90%&lt;/td&gt;
&lt;td&gt;~95–98% &lt;em&gt;(estimado)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Como resolvemos&lt;/h2&gt;
&lt;h3&gt;1. Treinamos um modelo para rodar localmente&lt;/h3&gt;
&lt;p&gt;O comando &lt;code&gt;train_category_brand_model&lt;/code&gt; treina dois classificadores independentes, um para categoria (~1000 classes) e outro para marca (~200), salvos como pickles separados.&lt;/p&gt;
&lt;p&gt;O pipeline é &lt;strong&gt;TF-IDF + SGDClassifier&lt;/strong&gt;, gera os modelos como pickle:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;crawler/data/models/categoria_classifier.pkl
crawler/data/models/marca_classifier.pkl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;lnp&lt;span class="w"&gt; &lt;/span&gt;train_category_brand_model
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Esse é o ponto-chave: &lt;strong&gt;o modelo roda 100% local&lt;/strong&gt;, sem API, sem rede, sem custo por predição. Carregado uma vez, classifica milhares de produtos por segundo. E como é treinado com os dados do próprio banco, retorna IDs diretos de categoria e marca, sem necessidade de resolução de nomes.&lt;/p&gt;
&lt;h3&gt;2. Orquestramos as duas fases com threshold de confiança&lt;/h3&gt;
&lt;p&gt;O &lt;code&gt;processor_hybrid.py&lt;/code&gt; decide por produto: aceita a predição do Sklearn se a confiança passa do threshold, senão acumula em lotes para a LLM. O threshold é o botão de ajuste entre custo e qualidade:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Threshold&lt;/th&gt;
&lt;th&gt;Efeito&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.50&lt;/td&gt;
&lt;td&gt;Aceita mais predições locais → menos IA, mais barato, menor precisão&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.75 (padrão)&lt;/td&gt;
&lt;td&gt;Equilíbrio entre custo e qualidade&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.95&lt;/td&gt;
&lt;td&gt;Só aceita predições muito confiantes → mais IA, mais caro, maior precisão&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Quanto cada threshold resolve localmente depende do mix de produtos do lote, não é um percentual fixo.&lt;/p&gt;
&lt;h2&gt;Resultados&lt;/h2&gt;
&lt;p&gt;Saída real de uma execução sobre o backlog de produtos não categorizados:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;📊 Resumo Categorização
  Modo               HÍBRIDO
  Total processado   164
  Sklearn            80 (49%)
  IA                 84 (51%)
  Cat adicionada     98
  Marca adicionada   84
  Sem categoria      66
  Cat novas          34
  Erros              1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Medindo 4 execuções seguidas (764 produtos do backlog), o modelo local resolveu &lt;strong&gt;~36% a custo zero&lt;/strong&gt; e o restante foi para a LLM, uma economia de custo de &lt;strong&gt;~1,5×&lt;/strong&gt; neste cenário.&lt;/p&gt;
&lt;p&gt;⚠️ Importante: esse teste consome o &lt;strong&gt;backlog acumulado de casos difíceis&lt;/strong&gt; (a cauda longa que sobrou sem categoria), o pior cenário para o modelo local. A fração resolvida cai a cada execução (49% → 37% → 27% → 32%) conforme os fáceis são esgotados. Em produção contínua, com produtos comuns chegando do crawler e retreino frequente, a fração local tende a ser maior, mas isso depende do mix real de cada dia.&lt;/p&gt;
&lt;h2&gt;Lições&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nem todo problema de classificação precisa de LLM.&lt;/strong&gt; Um TF-IDF + classificador linear treinado nos próprios dados resolve boa parte dos casos em menos de 1ms e a custo zero, quanto mais comum o produto, maior a fatia que ele cobre.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A LLM brilha como fallback&lt;/strong&gt;, não como primeira linha: ela cuida dos casos ambíguos, genéricos ou novos que o modelo local nunca viu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modelo local melhora com o tempo&lt;/strong&gt;: cada produto categorizado (por IA ou revisão) vira dado de treino para o próximo &lt;code&gt;train_category_brand_model&lt;/code&gt;, reduzindo progressivamente a dependência da LLM.&lt;/li&gt;
&lt;/ul&gt;</content><category term="Inteligência Artificial, Python"/></entry><entry><title>Como agrupar 200k produtos de lojas diferentes com embeddings e consenso multi-LLM</title><link href="https://www.hussan.com.br/blog/agrupar-produtos-embeddings-multi-llm.html" rel="alternate"/><published>2026-06-15T10:00:00-03:00</published><updated>2026-06-15T10:00:00-03:00</updated><author><name>Houssan A. Hijazi</name></author><id>tag:www.hussan.com.br,2026-06-15:/blog/agrupar-produtos-embeddings-multi-llm.html</id><summary type="html">&lt;p&gt;Como agrupar 200 mil produtos de lojas diferentes, cada uma com um nome distinto pro mesmo item, usando embeddings e consenso entre múltiplas LLMs.&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Contexto&lt;/h2&gt;
&lt;p&gt;O &lt;a href="http://lojasparaguai.com.br"&gt;lojasparaguai.com.br&lt;/a&gt; é um comparador de preços de produtos das lojas do Paraguai, Ciudade del Este em sua maioria. O sistema obtem os dados dos preços dos produtos diariamente e atualiza na base de dados. O grande desafio enfrentado pelo projeto é o agrupamento de produtos, onde o mesmo produto pode ter nomes diferentes na lojas, deixando o agrupamento complexo de ser feito.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;🎯 O problema&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Várias lojas vendem o mesmo produto, mas cada uma escreve o nome de um jeito:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Loja A: iPhone 17 Pro Max 256gb Titânio - Apple
Loja B: APPLE IPHONE 17 PROMAX 256 GB Cor Titanium
Loja C: iPhone17 Pro Max - 256GB - novo lacrado
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Para mostrar a comparação de preços em uma única página do produto, eu preciso saber que &lt;strong&gt;os três são o mesmo item&lt;/strong&gt;. A primeira solução foi criar uma área na painel onde faríamos esse agrupamento manualmente, buscando produto, selecionando os produtos das lojas, subindo a foto e as especificações. Com 200k+ produtos no banco, agrupar manualmente é muito trabalhoso. Foram feitas algumas tentativas de automatizar esse processo. Abaixo mostro como foi o caminho.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;🔧 Primeira tentativa: TF(Frequência do Termo)-IDF(Frequência Inversa do Documento)&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Comecei pelo básico, TF-IDF + similaridade. Funciona mais ou menos assim: cada nome vira um vetor de palavras com pesos, e eu comparo os vetores.&lt;/p&gt;
&lt;p&gt;Problemas encontrados:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;TF-IDF é "burro", não entende que &lt;code&gt;Promax&lt;/code&gt; e &lt;code&gt;Pro Max&lt;/code&gt; são a mesma coisa&lt;/li&gt;
&lt;li&gt;Em português, sinônimos e variações de marca quebram tudo (&lt;code&gt;Galaxy S24&lt;/code&gt; vs &lt;code&gt;Samsung S24&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Acessórios acabavam agrupados com o produto principal (&lt;code&gt;capa iPhone 17&lt;/code&gt; virava grupo do &lt;code&gt;iPhone 17&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Produto novo no catálogo? O algoritmo nunca tinha visto e errava feio&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tentei melhorar com regras manuais, listas de sinônimos, regex para normalizar marcas, blacklist de palavras como "case", "capa", "película". Virou um Frankenstein de manutenção infinita.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;strong&gt;🧠 Segunda tentativa: embeddings semânticos&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Troquei TF-IDF por &lt;strong&gt;Sentence-Transformers&lt;/strong&gt; (BERT pré-treinado para português). Em vez de comparar palavras, compara &lt;strong&gt;significado&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;sentence_transformers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SentenceTransformer&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SentenceTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;paraphrase-multilingual-MiniLM-L12-v2&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;emb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;iPhone 17 Pro Max 256gb&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;APPLE IPHONE 17 PROMAX 256 GB&amp;#39;&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;# similaridade: 0.94 (mesmo item)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Ganho imediato:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Promax&lt;/code&gt; ≈ &lt;code&gt;Pro Max&lt;/code&gt; (o modelo entende que é uma variação da mesma palavra)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Galaxy&lt;/code&gt; ≈ &lt;code&gt;Samsung Galaxy&lt;/code&gt; (contexto semântico)&lt;/li&gt;
&lt;li&gt;Português funciona bem (o modelo é multilingual)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Mas&lt;/strong&gt; ainda errava em casos sutis:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;iPhone 17 Pro&lt;/code&gt; vs &lt;code&gt;iPhone 17 Pro Max&lt;/code&gt;, similaridade 0.91, mas são produtos diferentes&lt;/li&gt;
&lt;li&gt;Cores e capacidades diferentes eram agrupadas&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Embeddings resolvem bem o "óbvio". Casos sutis precisavam de algo mais inteligente.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;strong&gt;⚙️ Solução final: pipeline híbrido em 2 fases&lt;/strong&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Fase 1, Clustering semântico (offline, grátis)&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Calcula embeddings de todos os produtos&lt;/li&gt;
&lt;li&gt;Agrupa por similaridade &amp;gt; 0.80 usando clustering aglomerativo&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduz os produtos de 200k para produtos pré agrupados&lt;/strong&gt; (batches menores para o LLM)&lt;/li&gt;
&lt;li&gt;Passa cada grupo para o LLM, sem exceção&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;strong&gt;Fase 2, LLM (validação total)&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Manda &lt;strong&gt;todos os grupos&lt;/strong&gt; para Gemini/Claude/Ollama em paralelo&lt;/li&gt;
&lt;li&gt;O LLM responde: "estes formam um grupo? qual é o nome canônico?"&lt;/li&gt;
&lt;li&gt;Valida semântica (cor != modelo) e nomeia canonicamente&lt;/li&gt;
&lt;li&gt;Salva metadata: quais LLMs concordaram com cada grupo&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;💰 &lt;strong&gt;Ganho:&lt;/strong&gt; o clustering reduz o volume em 40x antes de chamar o LLM. O custo de API cai porque processamos batches menores, em vez de comparar 200k produtos pairwise.
&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;&lt;strong&gt;🗳️ A sacada do consenso multi-LLM&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Mesmo assim, LLM erra. Gemini às vezes inventa modelos. Llama foca demais em palavra-chave. Cada um tem um viés diferente.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solução:&lt;/strong&gt; rodar várias LLMs em paralelo e comparar as respostas.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;lnp&lt;span class="w"&gt; &lt;/span&gt;get_suggest_produtos_ai&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--model&lt;span class="w"&gt; &lt;/span&gt;gemini/gemini-2.5-flash-lite&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--model&lt;span class="w"&gt; &lt;/span&gt;groq/llama-3.3-70b-versatile&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--model&lt;span class="w"&gt; &lt;/span&gt;anthropic/claude-haiku-4-5&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;--model&lt;span class="w"&gt; &lt;/span&gt;ollama/qwen2.5:7b
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Cada produto agrupado guarda quais LLMs concordaram com a sugestão:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;nome_sugerido&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;iPhone 17 Pro Max 256GB&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;descricao&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Experimente a combinação perfeita de design e performance com o iPhone 17 Pro Max de 256GB. Capture momentos inesquecíveis com sua câmera de ponta e desfrute de velocidade excepcional para aplicativos e jogos. Com amplo espaço de armazenamento, você terá liberdade para guardar todos os seus arquivos importantes. Seu display vibrante e recursos avançados garantem uma experiência de usuário imersiva e produtiva. Descubra a inovação Apple em suas mãos.&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;produtos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;llms&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;gemini&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;claude&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;llama&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;67890&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;llms&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;gemini&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;categoria_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;categoria_nome&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Placa de Vídeo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;marca_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1473&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;marca_nome&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Zotac&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;confianca&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.95&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;llms&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;gemini&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;claude&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;llama&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Foi desenvolvido um comando que basicamente faz a busca no banco de sugestões de grupos e faz o agrupamento caso alguns parâmetros estejam contemplados. Além desse comando uma interface no admin foi desenvolvida para agrupar as sugestões.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;lnp&lt;span class="w"&gt; &lt;/span&gt;auto_group&lt;span class="w"&gt; &lt;/span&gt;--min_llms_grupo&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--min_llms_produto&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--min_lojas&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--min_produtos&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--images&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--add&lt;span class="w"&gt; &lt;/span&gt;--update&lt;span class="w"&gt; &lt;/span&gt;--category&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;notebook&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;O comando acima, busca nas sugestões obtidas antes onde:
--min_llms_grupo=4 - no mínimo 4 llms concordam com o grupo sugerido.
--min_llms_produto=4 - no mínimo 4 llms concordam com os produtos sugeridos nos grupos.
--min_lojas=2 - deve ter no mínimo 2 lojas no grupo
--min_produtos=2  - deve ter no mínimo 2 produtos no grupo
--images=3 - faz o download das imagens sugeridas pela api do serper caso o grupo esteja em 2 lojas e 2 produtos no mínimo.
--add --update - Adiciona os novos grupos e atualiza os existentes
--category - Filtra a categoria&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;━━━&lt;span class="w"&gt; &lt;/span&gt;Categoria:&lt;span class="w"&gt; &lt;/span&gt;Notebook&lt;span class="w"&gt; &lt;/span&gt;━━━
&lt;span class="w"&gt;  &lt;/span&gt;▸&lt;span class="w"&gt; &lt;/span&gt;Marca:&lt;span class="w"&gt; &lt;/span&gt;Apple
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;UPDATE&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;MacBook&lt;span class="w"&gt; &lt;/span&gt;Air&lt;span class="w"&gt; &lt;/span&gt;M4&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;13&lt;/span&gt;.6&lt;span class="w"&gt; &lt;/span&gt;16GB&lt;span class="w"&gt; &lt;/span&gt;256GB&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;llms_grupo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;produtos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Atual&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Novos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;+0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;≥4&lt;span class="w"&gt; &lt;/span&gt;llms&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;📷&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;UPDATE&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;MacBook&lt;span class="w"&gt; &lt;/span&gt;Air&lt;span class="w"&gt; &lt;/span&gt;M4&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;.3&lt;span class="w"&gt; &lt;/span&gt;16GB&lt;span class="w"&gt; &lt;/span&gt;512GB&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;llms_grupo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;produtos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Atual&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Novos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;+0&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;≥4&lt;span class="w"&gt; &lt;/span&gt;llms&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;📷&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;SKIP&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;Macbook&lt;span class="w"&gt; &lt;/span&gt;Air&lt;span class="w"&gt; &lt;/span&gt;M4&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;15&lt;/span&gt;.3&lt;span class="s2"&gt;&amp;quot; 24GB/512GB] sem produtos após filtro llms_produto&lt;/span&gt;
&lt;span class="s2"&gt;    [NOVO]   [Macbook Air M5 16Gb/512Gb 13&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;llms_grupo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;produtos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;≥4&lt;span class="w"&gt; &lt;/span&gt;llms&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;📷&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;
------------------------------------------------------------
Resumo&lt;span class="w"&gt; &lt;/span&gt;por&lt;span class="w"&gt; &lt;/span&gt;categoria:
&lt;span class="w"&gt;  &lt;/span&gt;Notebook&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;total&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;novos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;update&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;skip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
------------------------------------------------------------
Resumo&lt;span class="w"&gt; &lt;/span&gt;por&lt;span class="w"&gt; &lt;/span&gt;marca:
&lt;span class="w"&gt;  &lt;/span&gt;Apple&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nv"&gt;total&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;novos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;update&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;skip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Isso reduziu drasticamente meu tempo de revisão. Em vez de olhar 4000 grupos um por um, eu foco nos casos em que as LLMs &lt;strong&gt;discordam&lt;/strong&gt; entre si, exatamente os casos ambíguos em que minha decisão importa.&lt;/p&gt;</content><category term="Inteligência Artificial, Python"/></entry></feed>