Mundo API

Implementação da API de Recomendações do Aprendizado de Máquina do Azure

Provavelmente você já tenha percebido as recomendações de outros produtos interessantes que costumam aparecer ao final das páginas e de vídeos, e, inclusive já tenha visto uma mensagem como essa surgindo em alguns sites, próximo às recomendações:

Ela aparece porque foi implementada a API de Recomendações do Aprendizado de Máquina do Azure, e essas recomendações dos vídeos que você poderia gostar de assistir estão sendo oferecidas por um modelo de inteligência artificial disponibilizado no Microsoft Azure exatamente para processar as melhores sugestões, como acontece no Canal 9 (Channel 9 da MSDN).

Nesse artigo, vamos visualizar um pouco mais sobre essa implementação.

A API de recomendações é bem amigável e bem documentada, e o aplicativo de demonstração é bem valioso, especialmente as classes que trabalham com a interpretação de XML e sintaxe de XPath.

Pode-se pontuar que eles possuem uma interface web conveniente para mostrar informações sobre o seu modelo. Um link para essa interface de usuário está no portal do datamarket (dentro da página da sua conta) como mostra a imagem abaixo:

Quanto à implementação, o Canal 9 utilizou basicamente o aplicativo de demonstração com pequenas modificações e uma tarefa agendada semanalmente que efetua quatro procedimentos:

1) Efetuar upload do último catálogo de todos os vídeos publicados do Canal 9;

2) Efetuar upload dos últimos dados de utilização, todos os dados de quais vídeos específicos um determinado usuário anônimo assistiu.

3) Construir um novo modelo e substituir o antigo.

4) Reconstruir o cache, o que significa que o Canal 9 mantém todas as recomendações em cache nos servidores.

Enviando o último catálogo

Sempre há conteúdo novo sendo adicionado no Canal 9, e eles precisam atualizar o modelo constantemente com as novidades… afinal o sistema de recomendação precisa conhecer o novo conteúdo para fazer as novas recomendações. Atualizar o catálogo é realmente uma tarefa muito importante, e essa atualização é feita utilizando a API ImportCatalogFile, que envia todos os IDs dos vídeos do Canal 9. Uma observação dessa API é que os dados não podem conter aspas e não existe forma de inserir aspas (nem com uso de caractere de escape ou outro).

Enviando os últimos dados de utilização

O próximo passo é alimentar o sistema com os dados de utilização. Por dados de utilização, temos todos os relatórios anônimos de exibição dos vídeos do Canal 9, algo como usuário anônimo 1 assistiu os vídeos 2 e 3, usuário anônimo 2, assistiu os vídeos 3 e 4. Ao invés de chamar a API toda vez que tiver um evento de uso, o pessoal do Canal 9 optou por condensar os relatórios de utilização diária e enviar tudo junto com a API ImportUsageFile.

Um cuidado especial nesse caso é para ter a certeza de não estar enviando um arquivo que já foi enviado anteriormente, e como a tarefa está sendo automatizada é importante diferenciar os arquivos. Esse código não está programado na API, mas pode ser feito manualmente utilizando o método GetAllModels que retorna os arquivos utilizados, e com isso, podemos extrair o nome dos arquivos com o elemento UsageFileNames. Segue o código utilizado:

public string GetRecommendationUsageFiles(string modelId) {
    string usageFiles = null;
    using (var request = new HttpRequestMessage(HttpMethod.Get, RecommendationUris.GetAllModels))
    using (var response = httpClient.SendAsync(request).Result) {
        if (!response.IsSuccessStatusCode) {
            Console.WriteLine(String.Format("Error {0}: Failed to start build for model {1}, \n reason {2}", response.StatusCode, modelId, response.ReasonPhrase));
            return null;
        }
        //process response if success
        var node = XmlUtils.ExtractXmlElement(response.Content.ReadAsStreamAsync().Result, string.Format("//a:entry/a:content/m:properties[d:Id='{0}']/d:UsageFileNames", modelId));
        if (node != null) {
            usageFiles = node.InnerText;
        }
    }
    return usageFiles;
}

Construindo e substituindo um modelo

Com as atualizações do catálogo e dos dados de utilização, o próximo passo é construir um novo modelo utilizando a API BuildModel. Essa API se executa em segundo plano, então é preciso verificar o status do serviço utilizando a chamada GetModelBuildsStatus. Não é possível executar mais de uma instância do BuildModel. Em média, construir o modelo do Canal 9, leva cerca de 20 minutos.

Quando o GetModelBuildsStatus retorna o status de BuildStatus.Success, pode-se chamar a API UpdateModel com o ID do novo modelo (BuildId) e já teremos o novo modelo no ar.

Construindo um cache das recomendações

Você pode solicitar as recomendações diretamente na API e em tempo real, mas o pessoal do Canal 9 optou por construir um cache com todas as recomendações, viabilizando a economia do tempo de processamento e de resposta ao usuário. Assim, com o modelo e os dados de utilização atualizados, é feita a iteração entre todos os IDs dos vídeos chamando a API ItemRecommend e armazenando os resultados no servidor de cache. Para agilizar esse processo (já que a quantidade de vídeos é considerável), pode-se efetuar a execução paralela com o ParallelForEach utilizando o ConcurrentBag para armazenar os resultados:

var resultCollection = new ConcurrentBag();
Parallel.ForEach(catalogGuids.Skip(i * 100).Take(100), guid => { resultCollection.Add(GetRec(guid)); });

Conclusão

Se você precisa de um serviço inteligente e poderoso de recomendação de serviços, o sistema da Azure é bem recomendado e há muitos cenários aonde esse aprendizado de máquina pode ser utilizado!

Adaptado de: Channel 9.