Olá Habr!
Compartilharei minha experiência sobre como montamos nosso próprio sistema de personalização com base no "conhecimento" sobre um potencial comprador.

A única diferença entre nossa solução e a clássica foi o uso de um pacote combinado de várias soluções e atendeu à lista de requisitos:
- o serviço deveria funcionar imediatamente em N sites
- segmentação dinâmica de público-alvo
- Filtragem colaborativa para fins de previsão em diferentes condições de segmentos de público-alvo
- estática pré-gerada na forma de conteúdo recomendado + mix dinâmico de mercadorias com base na análise do fluxo de cliques
- mudança de conteúdo, quase em tempo real, da RAM, levando em consideração os coeficientes dinâmicos
Isso é mais detalhado :) E sobre o rake que nos ajudou a mudar a pilha para melhor.
Antecedentes
Há um grupo de sites do mesmo assunto, cujas audiências são semelhantes - sites de uma exploração. O conteúdo é diferente, como regra, cada site publica informações sobre os produtos que a holding produz. Além desses sites de "conteúdo", há também sua própria loja on-line na qual esses produtos são vendidos.
Cada site possui sua própria equipe de marketing, seus próprios contadores GA e Ya Metrics. Analisando seu próprio público, colegas profissionais de marketing personalizaram o conteúdo do site, levando em consideração as necessidades dos visitantes. Naturalmente, o público desses sites se cruzou, mas como na época não havia um contador único, os resultados da análise eram locais.
Qualquer analista tomará a decisão certa, estará à mão com mais dados. Para esse propósito, ele desenvolveu sua própria versão do balcão.
Por que não o Google Analytics?Amostragem, falta de capacidade de puxar tudo sobre o usuário com sua cadeia de movimentos do site externo, através de vários sites, com detalhes que ele assistiu etc. Sim, em termos de tarefas do GA, é uma boa ferramenta, mas quando você deseja obter dados em tempo real e decidir imediatamente qual conteúdo mostrar ao visitante, então ... o gigante da análise não tem essa solução. Dançar com pandeiros de identificação de cliente para transferência entre sites não é nossa opção.
Definir um contador único para todos os sites não é uma decisão "política" completamente correta, e eles cairiam imediatamente na restrição da versão gratuita.
Devo dizer imediatamente que não comecei a reinventar a roda e me limitei a um funcional modesto cujas tarefas eram:
- Corrija cada usuário único, independentemente do site em que o grupo está localizado. Isso foi necessário para criar um único perfil de cliente no qual todos os seus dados seriam gravados com referência a cada site.
- Rastreando uma longa cadeia de transições entre todos os sites de um grupo em uma sessão. Isso foi necessário para identificar: os interesses dos usuários; o que eles assistiram; o que eles compraram; o que foi colocado na cesta, mas não comprado; quais produtos de sites diferentes poderiam ser "produtos substitutos" durante o processo de compra etc.
- Acompanhamento das atividades de publicidade de todos os profissionais de marketing (em cada equipe do site) para posterior análise. Isso foi necessário para: enriquecer o perfil de cada visitante; identificação de ótimas campanhas publicitárias vinculadas ao produto; identificação de canais de publicidade eficazes com referência a um produto ou campanha, etc. a lista é muito longa.
Todos os dados foram despejados em tempo real na coleção local. Acabou não muito ruim. No futuro, foi possível gerar relatórios agregados por produto e por: público-alvo, campanhas publicitárias, fontes de tráfego e tudo o que vier à mente. Para cada unidade de mercadorias havia dados sobre preços, quantidade em estoque, descontos, promoções e até um mar de dados.
Louvado seja a situação, sou analista, desenvolvedor, comerciante + gerente, tive acesso a tudo que foi digitalizado na holding. Eu não tinha uma tarefa técnica no início, fiz isso sozinho para resolver tarefas comuns de análise de dados.
Momento técnico:
- O MongoDB foi usado como um sistema de armazenamento unificado
- coleta de dados em tempo real baseada em javascript
- troca local de dados entre sites com base no rabbitmq
Enquanto tudo, como todo mundo ... Mas então começou
Dado o fato de o conhecimento adquirido sobre compradores e produtos ter se acumulado o suficiente, decidimos criar nosso próprio sistema de recomendação para a loja on-line.
Tudo ficou ótimo. Analisamos tudo, mas sem fanatismo. O modelo aumentou de tamanho e, como geralmente acontece, chegou a hora em que eu queria mais.
Momento técnico 2:
- A replicação do MongoDB ajudou a sobreviver, mas o sharding foi imediatamente abandonado. Este momento não passou por vários aspectos internos. Se a coleção de fluxo de cliques puder ser espalhada pelos shards, a coleção de perfis de usuário não estará mais lá. Foi possível coletar os resultados de consultas agregadas de diferentes shards para parte dos relatórios, mas a velocidade de execução deixou muito a desejar. Sem sharding, funcionou melhor e mais estável
- Coleta de dados em tempo real com base em javascript - aqui o pacote CORS + HTTPS era um ditador. Caso, quando um usuário acessou um dos sites do grupo, e nosso serviço o "autorizou" imediatamente na zona de vários domínios (eu me lembro, havia cinco sites independentes independentes na época), era tecnologicamente bonito e misterioso para colegas profissionais de marketing que agora podiam ver tudo cadeia de ocorrências para todos os sites de uma só vez.
- O modelo do serviço de recomendação foi escrito em Python. Mas o treinamento levou muito tempo. O arquivo de modelo possui várias dezenas de GB.
- O serviço de recomendação funcionou de maneira padrão em sua própria API, mas a resposta do servidor se tornou um gargalo, ou melhor, o tempo necessário para obter o resultado. Quanto mais dados, quanto maior o modelo, maior o modelo, mais lento será o resultado. Em resposta, era necessário levar em consideração muitos fatores que mudavam a cada hora (estoques de mercadorias em estoque, características do usuário e moda, todos os tipos de descontos etc.)
Alguns meses depois, a qualidade da API ultrapassou todos os limites sãos de "qualidade". Para os usuários, a velocidade de resposta excedeu a marca de 400ms. Blocos de conteúdo se reuniram lentamente, o site começou a ficar visivelmente sem graça. As coleções do MongoDB totalizaram dezenas de milhões de registros ...
É hora de mudar alguma coisa
Quase todos os instrumentos foram registrados no nível das operações, cada espirro foi medido.
O que mudou para o que:
- Clickhouse no MongoDB
- mais MongoDB para MongoDB + Tarantool
- EVE no frasco
- Frasco adicional em Falcon
- um arquivo separado estava com promessas em js e com autorização do usuário em todos os domínios. Eles não mudaram a lógica, a refatoração ganhou
Por que não a API métrica?No começo, eu estava apenas olhando na direção de soluções prontas da Yandex, mas não demorou muito. Isso é bom quando um site está em operação. e quando houver n e você desejar processar os dados imediatamente, não haverá tempo para dançar com pandeiros.
Por que o MongoDB?As especificações do produto eram constantemente adicionadas, algumas delas, infelizmente, nem sempre eram apresentadas.
Usando consultas agregadas - muito bem se encaixam no formato do estilo tecnológico local da equipe. O SQL clássico não queria produzir tabelas.
Com bastante frequência, os tipos e variantes de dados que foram armazenados e processados foram modificados.
No começo, pensei em usar o Yandex clickhouse como base para o serviço, mas depois abandonei essa ideia, mas o clickhouse também estava em nosso suporte de pilha.
Chegou um novo momento, 2000 solicitações por segundo ... desde que em uma semana implante nova funcionalidade e a carga aumentará ainda mais.
Durante o aprendizado de máquina, pela primeira vez no htop, vi 100% de carga de 12 núcleos ao mesmo tempo e uma troca completa em um servidor produtivo. O Zabbix informou ativamente que o MongoDB já havia mudado de mestre na réplica duas vezes em 10 minutos. Todos queriam estabilidade e um estado previsível.
É hora de mudar algo 2.0
O número de usuários aumentou. O número de clientes é semelhante. Para todos que já estiveram em qualquer um dos sites, acumulamos um perfil pessoal. A audiência de visitantes regulares foi parcialmente formada.
O que você sabia fazer? Sim, qualquer relatório não padrão para análise + diversidade de conteúdo:
- Selecione todos os usuários que vieram da campanha de publicidade A, que foi no último trimestre, entre eles, encontre aqueles que estavam interessados em mercadorias da posição N e exclua aqueles que compraram apenas ações, exclua aqueles que colocaram qualquer produto na cesta e deixaram site. Segundo eles, faça a classificação em ordem decrescente da receita da loja, se esses usuários agora acessarem o site da loja e comprarem produtos Z. Algo assim, e com outros botões de madrepérola ...
- Para analisar o tráfego de entrada, os usuários com a tag utm Y formam uma oferta de conteúdo, mas ANTES da criação, identifique o usuário, exclua aqueles que estavam na semana passada, mas estavam no site S (um do grupo de sites de retenção) e estavam interessados no produto Q - para tal gerar conteúdo classificado pelos critérios x, y, z
- É banal encontrar aqueles que costumam visitar o site A, às vezes acontece no site B (eles visitaram uma determinada seção) e que fazem uma verificação média na loja on-line de mais de N rublos
Na verdade, isso não estava no formato de "programação anormal", eu queria outra coisa. Outro veio até nós. No momento das campanhas publicitárias, a loja on-line estava curvada a partir do carregamento, o que podemos dizer sobre a nossa API-shki, que capturou essa carga "ao lado dela".
Decisões tomadas a tempo
Realizamos uma análise do público, decidimos coletar conteúdo não para todos, mas para grupos de visitantes. A multidão inteira estava aglomerada. Cada cluster tinha suas próprias características e "gosto" para fazer compras. O agrupamento é feito todos os dias. Isso é necessário para que, na próxima visita, o usuário mostre exatamente o conteúdo que mais lhe corresponde.
De sessão para sessão, os interesses e as necessidades do cliente mudam e, se da última vez em que ele foi automaticamente atribuído ao cluster nº 788897, levando em consideração seus interesses atuais, o sistema pode transferi-lo para o cluster nº 9464, o que afetará mais efetivamente a conversão subsequente.
Após o procedimento diário de agrupamento, foi lançada a próxima etapa - treinando o modelo, levando em consideração novos dados e conhecimentos sobre os clientes e levando em consideração os produtos que apareceram nas prateleiras das lojas ou os deixaram para sempre.
Para cada cluster, formamos blocos de conteúdo com antecedência e os gravamos na memória. Então Tarantool entrou em cena com toda a sua glória. Anteriormente, nós o usamos para armazenar dados rápidos, que depois eram usados no aprendizado de máquina. Essa foi a melhor solução, para não perturbar o MongoDB, que já estava ocupado com outras tarefas. No espaço, Tarantool armazenava dados de mercadorias, dados de usuários (conhecimento necessário sobre o comprador).
De maneira geral, hoje à noite "preparamos" conteúdo para cada grupo de audiências que poderá visitar o site amanhã. O usuário entrou, determinamos rapidamente se sabíamos alguma coisa sobre ele e, se a resposta fosse afirmativa, o pacote de conteúdo necessário seria enviado para o Nginx. Separadamente, para usuários NoName, um cluster padrão foi montado com seu conteúdo.
Pós-processamento para personalização
Sabíamos que existem usuários simples e existem aqueles para os quais temos todo um arquivo de conhecimento. Todo esse material estava no Tarantool e atualizado em tempo real.
No momento da montagem da página, conhecíamos todo o histórico de compras e cestas abandonadas de cada visitante (se ele já era nosso cliente), determinamos a afiliação de cluster, o módulo de fluxo de cliques deu conhecimento sobre a origem do tráfego, sabíamos sobre seus interesses passados e imediatos. Construindo uma matriz TOP50 em tempo real a partir de produtos visualizados anteriormente (em qualquer site do grupo), "determinamos a moda" e misturamos o conteúdo "sabor" desses produtos, cujos assuntos são mais frequentemente filos no TOP50. Essa análise simples dos últimos produtos visualizados deu um lucro real. Conteúdo do cluster, enriquecemos personalizado.
Resultado da nossa experiência
- Temos a aceleração do processo de criação de conteúdo pessoal N vezes
- Carregamento do servidor reduzido em 15 vezes
- Podemos criar quase todo o conteúdo pessoalmente, levando em consideração muitos profissionais de marketing de lista de desejos, recursos da apresentação do produto e muitas exceções, levando em consideração dados do perfil do usuário e eventos que estão acontecendo no site no momento - e tudo isso por ~ 25ms
- A conversão para esses blocos não cai abaixo de 5,6% - os usuários estão dispostos a comprar o que está mais próximo de suas necessidades no momento
- A velocidade de carregamento da página é ideal - eles removeram o conteúdo que estava "passado" no cluster em> 67%, o que está correto
- Temos uma ferramenta que, de acordo com as tarefas dos profissionais de marketing, não apenas fornece a resposta "o que aconteceu antes", mas também ajuda a formular conteúdo em um futuro próximo fragmentado, levando em consideração os interesses e as necessidades dos potenciais compradores
- As informações do DMP foram adicionadas ao perfil de cada comprador, agora podemos fazer agrupamentos, inclusive por redes sociais, interesses, nível de renda e outros doces
- Nosso serviço de recomendação tornou-se melhor, mais pedidos na loja
Que bom é isso?
Adquirimos uma nova experiência, testamos várias hipóteses que não sabíamos abordar antes, não usamos soluções pagas de terceiros para um serviço de recomendação que não levou em consideração todos os nossos recursos e trabalhou no mesmo domínio. A equipe recebeu um caso bom e interessante, que eles gerenciaram com sucesso.
Os apetites estão crescendo ... agora estamos testando uma nova lógica de montagem de conteúdo. Queremos coletar páginas para campanhas publicitárias, boletins e outras atividades externas. Os planos incluem transferir a lógica de configuração do modo de gerenciamento para a direção de aprendizado de máquina. Os sites viverão suas próprias vidas, e nós, além da “pipoca”, observaremos a evolução da apresentação do conteúdo do site com base na opinião da IA.