LLMs (grandes modelos de linguagem)
Observação
Consulte a guia Texto e imagens para obter mais detalhes!
No núcleo da IA generativa, os grandes modelos de linguagem (LLMs) - e suas relações mais compactas, modelos de linguagem pequenos (SLMs) - encapsulam as relações linguísticas e semânticas entre as palavras e frases em um vocabulário. O modelo pode usar essas relações para raciocinar sobre a entrada de linguagem natural e gerar respostas significativas e relevantes.
Fundamentalmente, as LLMs são treinadas para gerar preenchimentos com base em solicitações. Pense neles como sendo exemplos super poderosos do recurso de texto preditivo em muitos celulares. Um prompt inicia uma sequência de previsões de texto que resulta em uma conclusão semanticamente correta. O truque é que o modelo entende as relações entre palavras e pode identificar quais palavras na sequência até agora são mais propensas a influenciar a próxima; e use-a para prever a continuação mais provável da sequência.
Por exemplo, considere a seguinte frase:
Ouvi um cachorro latir alto para um gato.
Agora, suponha que você só ouviu as primeiras palavras: "Eu ouvi um cachorro ...". Você sabe que algumas dessas palavras são pistas mais úteis sobre qual pode ser a próxima palavra do que outras. Você sabe que "ouvi" e "cão" são indicadores fortes do que vem a seguir, e isso ajuda você a reduzir as probabilidades. Você sabe que há uma boa chance de a frase continuar como " Ouvi um cachorrolatir".
Você pode adivinhar a próxima palavra porque:
- Você tem um grande vocabulário de palavras para desenhar.
- Você aprendeu estruturas linguísticas comuns, para saber como as palavras se relacionam entre si em frases significativas.
- Você tem uma compreensão dos conceitos semânticos associados às palavras - você sabe que algo que ouviu deve ser um som de algum tipo, e você sabe que há sons específicos que são feitos por um cão.
Então, como treinar um modelo para ter essas mesmas habilidades?
Tokenização
A primeira etapa é fornecer ao modelo um vocabulário grande de palavras e frases; e nós queremos dizer grande. A última geração de LLMs tem vocabulários que consistem em centenas de milhares de tokens, com base em grandes volumes de dados de treinamento de toda a Internet e outras fontes.
Espere um minuto. Tokens?
Embora tendemos a pensar na linguagem em termos de palavras, as LLMs dividem seu vocabulário em tokens. Os tokens incluem palavras, mas também sub-palavras (como “in” em “inacreditável” e “improvável”), pontuação e outras sequências de caracteres comumente usadas. A primeira etapa no treinamento de um modelo de linguagem grande, portanto, é dividir o texto de treinamento em seus tokens distintos e atribuir um identificador inteiro exclusivo a cada um deles, desta forma:
- Eu (1)
- ouvi (2)
- um (3)
- cachorro (4)
- latir (5)
- em voz alta (6)
- em (7)
- a (3) já atribuído
- gato (8)
e assim por diante.
À medida que você adiciona mais dados de treinamento, mais tokens serão adicionados ao vocabulário e identificadores atribuídos; você pode acabar com tokens para palavras como cachorrinho, skateboard, carro e outros.
Observação
Neste exemplo simples, tokenizamos o texto de exemplo com base em palavras. Na realidade, também haveria sub-palavras, pontuação e outros tokens.
Transformando tokens com um transformador
Agora que temos um conjunto de tokens com IDs exclusivas, precisamos encontrar uma maneira de relacioná-los uns com os outros. Para fazer isso, atribuimos a cada token um vetor (uma matriz de vários valores numéricos, como [1, 23, 45]). Cada vetor tem vários elementos numéricos ou dimensões, e podemos usá-los para codificar atributos linguísticos e semânticos do token para ajudar a fornecer uma grande quantidade de informações sobre o que o token significa e como ele se relaciona com outros tokens, em um formato eficiente.
Precisamos transformar as representações de vetor iniciais dos tokens em novos vetores com características linguísticas e semânticas inseridas neles, com base nos contextos nos quais eles aparecem nos dados de treinamento. Como os novos vetores têm valores semânticos inseridos neles, nós os chamamos de inserções.
Para realizar essa tarefa, usamos um modelo de transformador . Esse tipo de modelo consiste em dois "blocos":
- Um bloco de codificador que cria as inserções aplicando uma técnica chamada atenção. A camada de atenção examina cada token por sua vez e determina como ele é influenciado pelos tokens ao seu redor. Para tornar o processo de codificação mais eficiente, a atenção de várias cabeças é usada para avaliar vários elementos do token em paralelo e atribuir pesos que podem ser usados para calcular os novos valores de elemento de vetor. Os resultados da camada de atenção são fornecidos a uma rede neural totalmente conectada para encontrar a melhor representação vetorial do embedding.
- Uma camada de decodificador que usa as inserções calculadas pelo codificador para determinar o próximo token mais provável em uma sequência iniciada por um prompt. O decodificador também usa o mecanismo de atenção e uma rede neural feed-forward para fazer as previsões.
Observação
Simplificamos muito a arquitetura e o processo do transformador na descrição e no diagrama. Não se preocupe muito com os detalhes específicos de como a atenção funciona - o ponto chave é que ele ajuda a capturar características linguísticas e semânticas de cada token com base nos contextos em que ele é usado. Se você deseja se aprofundar na arquitetura do transformador e em como ela utiliza a atenção, leia o artigo original Attention is all you need.
Vetores iniciais e codificação posicional
Inicialmente, os valores de vetor de token são atribuídos aleatoriamente, antes de serem alimentados por meio do transformador para criar vetores de inserção. Os vetores de token são alimentados no transformador juntamente com uma codificação posicional que indica onde o token aparece na sequência de texto de treinamento (precisamos fazer isso porque a ordem na qual os tokens aparecem na sequência é relevante para como eles se relacionam uns com os outros). Por exemplo, nossos tokens podem começar com esta aparência:
| Símbolo | ID de token | Position | Vector |
|---|---|---|---|
| I | 1 | 1 | [3, 7, 10] |
| Ouvi | 2 | 2 | [2, 15, 1] |
| a | 3 | 3 | [9, 11, 1] |
| cachorro | 4 | 4 | [2, 7, 11] |
| latir | 5 | 5 | [9, 12, 0] |
| ruidosamente | 6 | 6 | [3, 8, 13] |
| at | 7 | 7 | [5, 7, 10] |
| a | 3 | 8 | [9, 11, 1] |
| gato | 8 | 9 | [8, -6, 9 ] |
| ... | ... | ... | ... |
| cachorrinho | 127 | 45 | [7, 7, -2] |
| carro | 128 | 56 | [5, -5, 1 ] |
| skate | 129 | 67 | [4, 7, 14] |
Observação
Mantivemos as coisas simples usando vetores com apenas três elementos (o que nos ajudará a visualizá-los em três dimensões mais tarde). Na realidade, os vetores têm milhares de elementos.
Atenção e inserções
Para determinar as representações de vetor de tokens que incluem informações contextuais inseridas, o transformador usa camadas de atenção. Uma camada de atenção considera cada token, por sua vez, dentro do contexto da sequência de tokens em que ele aparece. Os tokens ao redor do atual são ponderados para refletir a influência, e os pesos são usados para calcular os valores dos elementos para o vetor de incorporação do token atual. Por exemplo, ao considerar o token “latir” no contexto de “Eu ouvi um cachorro latir”, os tokens para “ouvi” e “cachorro” receberão mais peso do que “Eu” ou “um”, já que são indicadores mais fortes para “latir”.
Inicialmente, o modelo não "sabe" quais tokens influenciam outras pessoas; mas, como ele é exposto a volumes maiores de texto, ele pode aprender iterativamente quais tokens normalmente aparecem juntos e começar a encontrar padrões que ajudam a atribuir valores aos elementos vetoriais que refletem as características linguísticas e semânticas dos tokens, com base em sua proximidade e frequência de uso juntos. O processo torna-se mais eficiente usando a atenção de várias cabeças para considerar diferentes elementos dos vetores em paralelo.
O resultado do processo de codificação é um conjunto de inserções; vetores que incluem informações contextuais sobre como os tokens no vocabulário se relacionam entre si. Um transformador real produz inserções que incluem milhares de elementos, mas para manter as coisas simples, vamos manter os vetores com apenas três vetores em nosso exemplo. O resultado do processo de codificação para nosso vocabulário pode ter esta aparência:
| Símbolo | ID de token | Integração |
|---|---|---|
| I | 1 | [2, 0, -1] |
| Ouvi | 2 | [-2, 2, 4 ] |
| a | 3 | [-3, 5, 5 ] |
| cachorro | 4 | [10, 3, 2 ] |
| latir | 5 | [9, 2, 10 ] |
| ruidosamente | 6 | [-3, 8, 3 ] |
| at | 7 | [-5, -1, 1] |
| gato | 8 | [10, 3, 1] |
| cachorrinho | 127 | [5, 3, 2 ] |
| carro | 128 | [-2, -2, 1 ] |
| skate | 129 | [-3, -2, 2 ] |
| latir | 203 | [2, -2, 3 ] |
Se você for observador, talvez tenha visto que nossos resultados incluem duas inserções para o token “latir”. É importante entender que as inserções representam um token em um contexto específico; e alguns tokens podem ser usados para significar várias coisas. Por exemplo, a casca de um cão é diferente da casca de uma árvore! Tokens que normalmente são usados em vários contextos podem produzir várias inserções.
Podemos pensar nos elementos das inserções como dimensões em um espaço vetor multidimensional. Em nosso exemplo simples, nossas inserções têm apenas três elementos, para que possamos visualizá-los como vetores no espaço tridimensional, assim:
Como as dimensões são calculadas com base em como os tokens se relacionam linguisticamente entre si, tokens usados em contextos semelhantes (e, portanto, têm significados semelhantes) resultam em vetores com direções semelhantes. Por exemplo, as incorporações para “cachorro” e “cachorrinho” apontam mais ou menos na mesma direção, o que não é muito diferente da incorporação para “gato”; mas muito diferente da incorporação para “skateboard” ou “carro”. Podemos medir o quão próximos os tokens são uns dos outros semanticamente calculando a semelhança de cosseno dos vetores.
Previsão de preenchimentos de solicitações
Agora que temos um conjunto de inserções que encapsulam a relação contextual entre tokens, podemos usar o bloco de decodificador de um transformador para prever iterativamente a próxima palavra em uma sequência com base em um prompt inicial.
Mais uma vez, a atenção é usada para considerar cada token no contexto; mas desta vez o contexto a ser considerado só pode incluir os tokens que precedem o token que estamos tentando prever. O modelo de decodificador é treinado, usando dados para os quais já temos a sequência completa, ao aplicar uma técnica chamada atenção mascarada, em que os tokens após o token atual são ignorados. Como já sabemos o próximo token durante o treinamento, o transformador pode compará-lo com o token previsto e ajustar os pesos aprendidos em iterações de treinamento posteriores para reduzir o erro no modelo.
Ao prever um novo preenchimento, para a qual os próximos tokens são desconhecidos, as camadas de atenção calculam possíveis vetores para o próximo token, e a rede feed-forward é usada para ajudar a determinar o candidato mais provável. O valor previsto é adicionado à sequência e todo o processo se repete para prever o próximo token; e assim por diante, até que o decodificador preveja que a sequência foi encerrada.
Por exemplo, dada a sequência "Quando meu cachorro era um ...", o modelo avaliará os tokens na sequência até agora, usará atenção para atribuir pesos e preverá que o próximo token mais provável é "cachorrinho" em vez de, digamos, "gato" ou "skateboard".