Compreendendo a Arquitetura e o Funcionamento dos Modelos GPT

A rápida ascensão de modelos de linguagem generativos, como GPT-3.5, ChatGPT e GPT-4, despertou um grande interesse em como essas ferramentas poderosas funcionam internamente. Embora os detalhes específicos de sua implementação sejam proprietários e complexos, os princípios fundamentais por trás de todos os modelos GPT são acessíveis. Este artigo visa explicar os conceitos centrais dos modelos de linguagem em geral e, em particular, os modelos GPT, para profissionais de dados e engenheiros de machine learning.

Como Operam os Modelos de Linguagem Generativos

Modelos de linguagem generativos operam sob um princípio fundamental: eles recebem uma sequência de 'n' tokens como entrada e, com base nela, predizem e geram um único token de saída.

Para compreeender essa operação, é crucial entender o que é um 'token'. Um token representa uma unidade de texto, que pode ser uma palavra comum, uma parte de uma palavra, ou até mesmo um caractere especial. Em modelos GPT, palavras frequentes tendem a ser tokens únicos (ex: "nós"), enquanto palavras mais longas ou complexas podem ser divididas em múltiplos tokens (ex: "antropomorfizar" pode ser dividido em "antrop", "omorf", "izar"). A forma como as abreviações são tokenizadas depende da frequência com que aparecem juntas. A OpenAI oferece ferramentas, como seu tokenizer online e a biblioteca tiktoken para Python, que permitem visualizar como o texto é segmentado.

Para tokenizar usando Python e a biblioteca tiktoken, pode-se usar o seguinte código:

import tiktoken

# Obtém a codificação para o modelo GPT-3 'davinci', que é a codificação "r50k_base".
encoder = tiktoken.encoding_for_model("davinci")

texto_exemplo = "Precisamos parar de antropomorfizar o ChatGPT."
print(f"Texto original: {texto_exemplo}")

ids_tokens = encoder.encode(texto_exemplo)
print(f"Número total de tokens distintos no vocabulário: {encoder.n_vocab}")

print(f"IDs dos tokens: {ids_tokens}")
tokens_decodificados = [encoder.decode_single_token_bytes(token_id) for token_id in ids_tokens]
print(f"Representações em bytes dos tokens: {tokens_decodificados}")
print(f"Número de tokens no texto de exemplo: {len(ids_tokens)}")

texto_reconstruido = encoder.decode(ids_tokens)
print(f"Texto reconstruído após codificação/decodificação: {texto_reconstruido}")

A execução do código acima produzirá o seguinte resultado:

Texto original: Precisamos parar de antropomorfizar o ChatGPT.
Número total de tokens distintos no vocabulário: 50257
IDs dos tokens: [40502, 1279, 781, 313, 17911, 25831, 2890, 24101, 38, 11571, 13]
Representações em bytes dos tokens: [b'Precisamos', b' parar', b' de', b' antrop', b'omorf', b'izar', b' o', b' Chat', b'G', b'PT', b'.']
Número de tokens no texto de exemplo: 11
Texto reconstruído após codificação/decodificação: Precisamos parar de antropomorfizar o ChatGPT.

O resultado demonstra que cada token é internamente mapeado para um índice inteiro. É possível codificar uma string em uma sequência de IDs de token e, em seguida, decodificar esses IDs de volta para a sequência de caracteres original, garantindo a fidelidade do texto.

Analisando alternativas de tokenização, uma abordagem simplista seria tratar cada letra como um token. Isso facilitaria a divisão do texto, mas resultaria em muitas unidades para codificar pouca informação, dado o limite de tokens que os modelos podem processar. Por exemplo, os mesmos 11 tokens do exemplo acima codificariam apenas "Precisamos" se fosse por letra, em vez da frase completa. Por outro lado, considerar cada palavra como um token reduziria o número de unidades, mas exigiria um vocabulário impraticavelmente grande e dinâmico, incapaz de acompanhar novos termos. A escolha da OpenAI, e de outros sistemas como o SentencePiece do Google, reside em um equilíbrio entre esses extremos, buscando maximizar a informação por token dentro de um vocabulário gerenciável.

Ao interagir com interfaces como o ChatGPT, percebemos que o modelo gera sequências extensas de texto, não apenas um token. Isso ocorre porque o princípio fundamental de 'n tokens de entrada, 1 token de saída' é aplicado de forma iterativa, em um modo de janela deslizante. Cada token gerado é então adicionado à sequência de entrada para a próxima iteração, permitindo a construção de frases, parágrafos e textos completos até que uma condição de parada seja atingida (como um sinal de fim de texto ou um limite de comprimento).

É comum observar que, ao repetir uma mesma consulta ao ChatGPT, as respostas podem variar ligeiramente. Esse não-determinismo advém do fato de que o modelo não produz um único token previsto, mas sim uma distribuição de probabilidade sobre todos os tokens possíveis em seu vocabulário. O token final é selecionado por amostragem dessa distribuição, introduzindo uma variação controlada que evita respostas repetitivas. Essa distribuição de probabilidade é o resultado da fase de treinamento. Durante o treinamento, o modelo é exposto a vastas quantidades de texto, ajustando seus parâmetros (pesos) para aprender as relações contextuais entre os tokens e, assim, prever distribuições de probabilidade eficazes para os próximos tokens. Modelos GPT são treinados em uma porção significativa da internet, o que lhes permite refletir a complexidade e diversidade da linguagem.

Breve Histórico dos Modelos de Linguagem Generativos

A evolução dos modelos de linguagem começou com abordagens mais simples.

Modelos de Markov Ocultos (HMMs)

Nos anos 70, os Modelos de Markov Ocultos (HMMs) ganharam destaque. Sua limitação primária era o fato de serem processos de Markov, o que significava que, ao prever um novo token, consideravam apenas o token imediatamente anterior (n=1). Isso resultava em saídas pouco complexas, incapazes de capturar dependências de longo alcance na linguagem. Por exemplo, dada a frase "A rápida raposa marrom pula sobre o...", um HMM que visse apenas "o" teria dificuldade em prever "preguiçoso", que depende de "raposa". Era evidente que modelos de linguagem precisavam de suporte para múltiplos tokens de entrada para gerar resultados satisfatórios.

Modelos N-gram

Nos anos 90, os modelos N-gram surgiram como uma melhoria, permitindo a consideração de múltiplos tokens de entrada e superando a limitação dos HMMs. Um N-gram simples pode ser implementado para prever o próximo caractere com base nos caracteres precedentes. Por exemplo, para construir um bigram (N=2) baseado em caracteres, cria-se uma matriz de contagens onde cada linha representa um caractere e cada coluna, o caractere seguinte. Ao percorrer um texto de treinamento, cada par de caracteres adjacentes incrementa a contagem na célula correspondente da matriz. Após o treinamento, a matriz é normalizada para obter probabilidades. Para gerar texto, um caractere inicial é fornecido, e o próximo caractere é amostrado com base na distribuição de probabilidade da linha correspondente. No entanto, a complexidade computacional dos N-grams cresce exponencialmente com 'N' (o número de tokens de entrada), limitando sua escalabilidade para sequências mais longas e, consequentemente, a qualidade das previsões para contextos maiores.

Redes Neurais Recorrentes (RNNs)

A virada do século XXI viu a ascensão das Redes Neurais Recorrentes (RNNs), que superaram as limitações de contexto dos N-grams ao processar sequências de entrada de comprimento variável. Variantes como LSTMs (Long Short-Term Memory) e GRUs (Gated Recurrent Units) foram particularmente eficazes, introduzindo mecanismos de 'células de memória' internas que permitiam aos nós subsequentes 'lembrar' aspectos importantes de informações anteriores. Contudo, RNNs enfrentavam desafios de instabilidade de gradientes (explosão ou desaparecimento de gradientes) ao lidar com sequências muito longas, o que comprometia sua capacidade de aprender dependências distantes, limitando o comprimento efetivo do contexto que podiam gerenciar.

Modelos Transformer

Um avanço revolucionário ocorreu em 2017 com a publicação do artigo 'Attention Is All You Need' pelo Google, que introduziu a arquitetura Transformer. Essa nova abordagem permitiu um aumento significativo no número de tokens de entrada processáveis, resolveu os problemas de instabilidade de gradientes das RNNs e, crucialmente, demonstrou alta paralelização, aproveitando o poder das GPUs. Os Transformers são a base dos modernos modelos GPT da OpenAI. O cerne da arquitetura Transformer é o 'mecanismo de atenção', que permite ao modelo focar em partes específicas da sequência de entrada, independentemente de sua posição. Por exemplo, em uma frase como "A garota foi à loja e comprou um livro", ao prever "comprou", o modelo pode dar maior atenção a "foi" e "garota", mesmo que "foi" apareça antes na sequência.

Essa capacidade de atenção seletiva nos modelos GPT é viabilizada por uma inovação da pesquisa de 2017: a camada de 'Atenção Multicabeça Mascarada'. Vamos detalhar seus componentes:

  • Atenção (Attention): Uma camada de atenção consiste em uma matriz de pesos que quantifica a força das relações entre todos os pares de posições de tokens na sequência de entrada. Esses pesos são aprendidos durante o treinamento. Um peso alto entre dois tokens indica uma forte interdependência, permitindo que o modelo 'priorize' certas partes da entrada.
  • Mascarada (Masked): No contexto da geração de texto (como nos modelos GPT), a atenção é 'mascarada' para garantir que cada token de saída só possa depender dos tokens que o precedem na sequência. Isso evita que o modelo "veja" o futuro durante a previsão.
  • Multicabeça (Multi-head): A arquitetura Transformer emprega múltiplas camadas de atenção mascarada operando em paralelo ('múltiplas cabeças'). Cada 'cabeça' aprende diferentes tipos de relações de atenção, e suas saídas são combinadas, proporcionando ao modelo uma compreensão mais rica e multifacetada do contexto.

A grande vantagem dos Transformers sobre LSTMs e GRUs é que, embora as células de memória dessas últimas ajudem a reter informações, problemas de gradiente podem surgir com tokens muito distantes. Nos Transformers, cada token tem uma conexão direta com todos os tokens anteriores, superando essa limitação.

Diferentes Modelos GPT e Suas Implementações

Os modelos de geração de texto mais recentes da OpenAI, como GPT-3.5, ChatGPT e GPT-4, todos compartilham a arquitetura Transformer — daí o acrônimo 'GPT' (Generative Pre-trained Transformer).

  • GPT-3.5: Este é um Transformer treinado como um modelo de 'completion'. Sua função é completar uma sequência de texto fornecida, prevendo as palavras mais prováveis que se seguirão.
  • ChatGPT: Embora baseado na mesma arquitetura fundamental do GPT-3.5, o ChatGPT é refinado como um modelo conversacional. Ele foi ajustado usando dados de diálogo e, posteriormente, otimizado com Aprendizagem por Reforço com Feedback Humano (RLHF - Reinforcement Learning from Human Feedback). O RLHF, introduzido no artigo InstructGPT de 2022, envolve humanos classificando as saídas do modelo para ensinar a ele quais respostas são preferíveis, alinhando suas interações com as expectativas humanas.
  • GPT-4: Representa uma nova geração, com seu próprio modelo base. Ele também é versátil, capaz de realizar tanto 'completions' quanto diálogos. Assim como o ChatGPT, o GPT-4 foi aprimorado com RLHF para maximizar sua utilidade e alinhamento com as intenções humanas.

Desenvolvendo com Modelos GPT

Para desenvolver aplicações que utilizam modelos GPT, há duas principais plataformas de acesso: diretamente via API da OpenAI ou através do serviço Azure OpenAI. Embora as chamadas de API sejam as mesmas em ambos, o Azure OpenAI oferece vantagens adicionais:

  • Filtros de IA responsável automatizados para mitigar o uso antiético da API.
  • Recursos de segurança robustos do Azure, incluindo redes privadas.
  • Disponibilidade regional para otimização de desempenho.

Ao escolher um modelo, conisdere as seguintes versões disponíveis no serviço Azure OpenAI:

  • GPT-3.5: text-davinci-002, text-davinci-003 (ambos suportam até 4.000 tokens).
  • ChatGPT: gpt-35-turbo.
  • GPT-4: gpt-4 (8.000 tokens), gpt-4-32k (32.000 tokens).

O gpt-4-32k, embora mais caro, é ideal para tarefas que exigem um contexto muito mais longo. Recomenda-se iniciar com um modelo mais acessível e migrar para o GPT-4 apenas quando o requisito de capacidade for indispensável.

Tags: GPT Large Language Models LLM Transformer machine learning

Publicado em 7-12 07:49