- O GPT-4o cobra 170 tokens para processar cada bloco de 512x512 usado no modo de alta resolução. Numa proporção de cerca de 0,75 token por palavra, isso significa que uma imagem equivale a aproximadamente 227 palavras
- Comparado ao ditado “uma imagem vale mais que mil palavras”, há uma diferença de cerca de 4 vezes
- O número 170 é estranhamente específico. A OpenAI usa números arredondados como “US$ 20” ou “US$ 0,50” na precificação, ou potências de 2 e 3 nas dimensões internas
- Por que escolher um número como 170? Em programação, números jogados no código sem explicação são chamados de “números mágicos”, e 170 é um número mágico bem chamativo
- Por que converter o custo da imagem em número de tokens? Se fosse apenas para fins de cobrança, listar o custo por bloco seria menos confuso
- E se a OpenAI escolheu 170 simplesmente porque isso é literalmente verdade? E se um bloco de imagem for realmente representado por 170 vetores de embedding consecutivos?
Embeddings
- A primeira coisa a lembrar sobre modelos transformer é que eles operam sobre vetores, não sobre tokens discretos
- A entrada precisa ser um vetor; caso contrário, a similaridade por produto interno, que é o núcleo do transformer, não faria sentido
- Todo o conceito de token é uma etapa de pré-processamento: o texto é convertido em tokens, e os tokens são convertidos em vetores de embedding por um modelo de embeddings antes de chegarem à primeira camada do modelo transformer
- Por exemplo, o Llama 3 usa internamente 4.096 dimensões de características
- Considere a frase “My very educated mother just served us nine pizzas.”
- Ela é convertida pelo BPE em 10 tokens inteiros (incluindo o ponto final), e depois cada um deles é convertido pelo modelo de embeddings em um vetor de 4.096 dimensões, formando uma matriz 10x4096
- Essa é a “verdadeira” entrada para o modelo transformer
- Mas não existe nenhuma regra dizendo que esses vetores precisam necessariamente vir de um modelo de embeddings de texto
- Essa é uma estratégia que funciona bem para dados de texto, mas se houver outro tipo de dado que você queira alimentar em um transformer, basta usar uma estratégia de embedding diferente
- Sabemos que a OpenAI pensa nessa direção porque publicou o modelo de embeddings CLIP em 2021
- O CLIP incorpora texto e imagens no mesmo espaço vetorial semântico, permitindo usar similaridade de cosseno para encontrar imagens relacionadas a uma string de texto ou imagens semanticamente parecidas com outras imagens
- Mas o CLIP incorpora a imagem inteira em um único vetor, não em 170. O GPT-4o precisa usar alguma outra estratégia mais avançada internamente para representar imagens — e, da mesma forma, vídeo, voz e outros tipos de dados. É por isso que ele é “omnimodal”
- Em especial, vale tentar inferir qual seria essa estratégia para dados de imagem
Número de dimensões de características
- Se tentarmos estimar quantas dimensões o GPT-4o usa internamente para representar vetores de embedding, não dá para saber o número real porque é proprietário, mas dá para fazer suposições razoáveis
- A OpenAI parece gostar de potências de 2, às vezes misturadas com um único fator 3
- Por exemplo, usa 1.536 no embedding ada-002 e 3.072 no text-embedding-3-large
- Sabe-se que o GPT-3 usa 12.288 dimensões no geral
- O GPT-4o pode ter mantido ou aumentado esse parâmetro
- Não parece provável que a quantidade de embeddings tenha diminuído do GPT-3 para o GPT-4o, mas é possível
- Lançamentos como o GPT-4 Turbo foram de fato mais rápidos e baratos que as versões anteriores, e uma redução na dimensão dos embeddings pode ter feito parte disso se os desenvolvedores tivessem benchmarks mostrando que um tamanho menor oferecia qualidade equivalente
- O número de dimensões de características usado dentro do GPT-4o provavelmente é um destes: 1536, 2048, 3072, 4096, 12228, 16384, 24576
- Vamos supor que o GPT-4o use 12.228 dimensões para os vetores de embedding. Mesmo que a diferença seja por um fator de 2 ou 4, isso não importa muito. O mesmo raciocínio continuaria valendo
Embedding de imagem
- Como os blocos de imagem são quadrados, é provável que sejam representados como uma grade quadrada de tokens
- 170 está muito perto de 13x13
- O token adicional poderia ser um único vetor de embedding que codifica uma impressão gestalt da imagem inteira, de forma semelhante ao CLIP
- Então, como ir de 512x512x3 para 13x13x12228?
Estratégia 1: pixels brutos
- Uma forma muito simples de colocar a imagem em um espaço vetorial:
- Dividir a imagem 512x512 em uma grade 8x8 de “mini-blocos”
- Cada mini-bloco teria 64x64x3 e seria achatado em um vetor de 12.228 dimensões
- Cada mini-bloco seria um único vetor de embedding
- O bloco de imagem inteiro seria representado por 64 vetores de embedding consecutivos
- Essa abordagem tem dois problemas:
- 64 ≠ 170
- É muito burra (não faz sentido incorporar usando valores RGB brutos e esperar que o transformer resolva tudo)
Estratégia 2: CNN
- Felizmente, já existe um modelo com essas características e com mais de 10 anos de histórico processando dados de imagem com sucesso: a rede neural convolucional (Convolutional Neural Network)
- CNNs têm propriedades como invariância a translação e a escala
- AlexNet e YOLO são exemplos representativos de arquiteturas de CNN
- Uma CNN funciona como um funil que comprime pixels brutos em vetores semânticos
- O YOLO não reduz a imagem a um único vetor plano; ele para em 13x13
- A saída do YOLOv3 é composta por 169 vetores diferentes, dispostos em uma grade 13x13, cada um com 1.024 dimensões
- É de se esperar que a hipotética CNN de embedding de imagens do GPT-4o tenha formato parecido com essas arquiteturas de CNN
- É apresentada uma forma de usar camadas padrão de CNN para ir de 512x512x3 a 13x13x12228
- Um design semelhante ao AlexNet conseguiria isso de forma elegante (usando 5 blocos repetidos idênticos)
- Há também uma alternativa mais parecida com o YOLO, mas ela chega a 12x12 (em vez de 13x13)
- Não dá para provar, mas esse projeto especulativo mostra que existe uma arquitetura de CNN plausível capaz de representar imagens como uma grade kxk de vetores de embedding
Validação experimental
- Será que o GPT-4o realmente consegue ver uma grade 13x13 de vetores de embedding?
- Para testar isso, foi criada uma tarefa inspirada nas cartas Zener: identificar a cor e a forma de todos os símbolos em uma grade na imagem
- Com um programa simples, foram geradas imagens de grade para teste, e foi dado ao GPT-4o um prompt para descrever a forma e a cor de cada célula no formato de um array JSON
- Se a hipótese de 13x13 estiver correta, seria esperado que o GPT-4o se saísse bem até o tamanho 13x13 e que o desempenho caísse depois disso
- Mas, na prática, ele mostrou desempenho perfeito apenas em grades de até 5x5, e depois disso o desempenho caiu rapidamente
- Em uma grade 7x7, mostrou 76% de precisão, e em uma grade 13x13 teve desempenho equivalente ao acaso
- Isso significa que a hipótese de que 169 tokens representariam uma grade 13x13 está errada
- No entanto, o resultado com grades 5x5 sugere que o GPT-4o consegue rastrear 25 objetos distintos dentro de uma imagem e suas posições absolutas
- A ideia básica pode estar correta, mas com as dimensões erradas; seria possível adicionar mais camadas à CNN para reduzir a saída para 5x5 em vez de 13x13
- Supondo que só grades de até 5x5 sejam usadas, é preciso pensar em como estruturar a saída para chegar a 170 tokens
Estratégia de pirâmide
- Uma forma de chegar a números próximos de 85 e 170 é supor que a imagem seja codificada como uma espécie de pirâmide de níveis cada vez mais detalhados
- Começa-se com um vetor de embedding para capturar a impressão gestáltica da imagem inteira, depois adiciona-se
3x3 para capturar esquerda/meio/direita e topo/meio/base, depois 5x5, 7x7 e assim por diante
- Essa estratégia chega muito perto de 85 tokens para a “miniatura mestre” se parar em
7x7
- Adicionar a grade final
9x9 chega muito perto de 170
- 12+32+52+72+92=1+9+25+49+81=165
- É possível bater exatamente se assumirmos uma grade provisória
2x2 para o bloco 512x512 e um token especial <|image start|> para cada uma
- 1+12+32+52+72=1+1+9+25+49=85
- 1+12+22+32+52+72+92=1+1+4+9+25+49+81=170
- Esse esquema não tem nenhum delimitador para o início e o fim das linhas, mas isso poderia ser tratado com codificação posicional em 2D, de forma semelhante ao uso de RoPE para codificar a informação posicional dos tokens de texto
- O que foi dito acima não bate perfeitamente com a evidência de que o desempenho na grade Zener começa a cair depois de
5x5, já que considera apenas tamanhos de grade ímpares e pula 5x5
- Como alternativa, podemos considerar todas as grades até
5x5 (pares e ímpares)
- Essa abordagem fornece 55 tokens: 12+22+32+42+52=55
- Se assumirmos 3 tokens por mini-bloco e 1 token delimitador entre cada bloco, dá para chegar a 170
- Não é totalmente satisfatório do ponto de vista numérico, mas combina bem com os resultados empíricos
- A estratégia de pirâmide é intuitivamente muito atraente e parece uma forma quase “óbvia” de codificar informação espacial em diferentes níveis de zoom
- Isso pode explicar por que funciona bem em grades de até
5x5 e vai muito mal em 6x6 ou maiores
- É frustrante que todas as hipóteses pareçam tentadoramente próximas de explicar tudo, mas os números nunca fechem de forma limpa
- Ainda assim, essa estratégia de pirâmide é a melhor explicação que consegui imaginar
Reconhecimento óptico de caracteres (OCR)
- Nenhuma das hipóteses acima explica como o GPT-4o faz OCR
- O CLIP basicamente não consegue fazer OCR muito bem, pelo menos não com grandes blocos de texto
- (Mesmo assim, o simples fato de o GPT-4o conseguir fazer OCR já é bastante surpreendente e um exemplo claro de capacidade emergente)
- O GPT-4o claramente consegue fazer OCR de alta qualidade
- Ele consegue transcrever blocos longos de texto e ler texto manuscrito ou texto deslocado, girado, projetado ou parcialmente oculto
- Motores modernos de OCR já fazem muito trabalho para limpar a imagem, encontrar caixas delimitadoras e faixas dos caracteres, e então executar modelos especializados de reconhecimento de caracteres ao longo dessas faixas, um caractere ou palavra por vez
- Não se trata apenas de usar uma CNN grande
- Em teoria, a OpenAI pode realmente ter construído um modelo tão bom assim, mas isso não combina com o desempenho relativamente fraco no teste da grade Zener
- Se ele não consegue ler 36 símbolos em uma grade limpa
6x6 em uma imagem, então não deveria conseguir ler perfeitamente centenas de caracteres de texto
- Uma teoria simples para explicar essa discrepância:
- Acho que a OpenAI executa uma ferramenta pronta de OCR, como o Tesseract (ou uma ferramenta proprietária de ponta), e alimenta o transformer com o texto identificado junto com os dados da imagem
- Isso explicaria por que as versões iniciais se confundiam facilmente com texto escondido na imagem (porque, do ponto de vista do GPT-4o, esse texto fazia parte do prompt)
- Isso já foi corrigido, e o GPT-4o agora é habilidoso em ignorar prompts maliciosos escondidos dentro da imagem
- Mas isso não explica por que não há cobrança por token para o texto encontrado na imagem
- Curiosamente, enviar texto como imagem de fato é mais eficiente
- Uma imagem
512x512 com uma fonte pequena, mas legível, pode facilmente conter 400 a 500 tokens de texto, mas só são cobrados 170 tokens de entrada, somados aos 85 da “miniatura mestre”, totalizando 255 tokens (bem menos do que a quantidade de palavras na imagem)
- Essa teoria explica por que há latência extra ao processar imagens
- Uma CNN é essencialmente imediata, mas um OCR de terceiros levaria tempo adicional
- Além disso (embora isso não prove nada), o ambiente Python usado pelo interpretador de código da OpenAI vem com o PyTesseract instalado
- Você pode pedir que ele execute o PyTesseract em uma imagem enviada para obter uma segunda opinião
Conclusão
- No fundo, foi feita muita especulação a partir de um único fato sólido: a OpenAI usou o número mágico 170
- Mas parece haver uma abordagem totalmente plausível, e muito alinhada com outras arquiteturas de CNN como o YOLO, para mapear blocos de imagem em vetores de embedding
- Por isso, não acho que os 170 tokens sejam apenas uma aproximação usada para cobrar por uma estimativa grosseira do custo computacional necessário para processar a imagem
- Também não acho que sejam camadas ligadas para combinar dados de imagem e texto, como alguns outros modelos multimodais fazem
- Acho que o GPT-4o usa uma arquitetura de CNN que mistura CLIP e YOLO, incorporando imagens diretamente no espaço vetorial semântico do transformer, de modo que uma imagem
512x512 seja literalmente representada por 170 vetores de embedding
- Quando comecei este artigo, eu estava convencido de que tinha decifrado completamente o fato de que os 170 tokens correspondiam a uma grade
13x13 e um token extra de “impressão gestáltica”
- Mas isso caiu por terra quando o desempenho na tarefa Zener começou a piorar depois de
5x5. O que quer que esteja acontecendo internamente parece ser bem menor do que 13x13
- Ainda assim, a analogia com YOLO é convincente, e o desempenho na tarefa Zener
5x5 praticamente confirma que ele está fazendo algum tipo de grade
- Essa teoria também tem bastante poder preditivo em outras áreas
- Ela explica como o GPT-4o consegue processar várias imagens e realizar tarefas como comparar duas imagens
- Explica por que ele consegue ver vários objetos na mesma imagem, mas fica sobrecarregado quando há objetos demais em uma cena complexa
- Explica por que o GPT-4o parece tão vago sobre as posições absolutas e relativas de objetos individuais na cena e por que não consegue contar com precisão os objetos em uma imagem (quando um objeto atravessa duas células adjacentes da grade, a mesma classe é ativada em ambas, então ele não pode ter certeza se é um objeto ou dois)
- Ironicamente, a única coisa que essa teoria não consegue explicar de forma elegante é justamente a pergunta que motivou este artigo desde o início: por que exatamente 170 tokens?
- A teoria da pirâmide (
1x1 + 2x2 + 3x3 + 4x4 + 5x5) foi a melhor que consegui imaginar, mas não é particularmente limpa
- Eu gostaria de ouvir a opinião de alguém que tenha uma teoria que se encaixe melhor (ou conhecimento real, supondo que isso não viole um NDA)
Pós-escrito: truques com canal alfa
- Ao realizar este projeto, descobri que o GPT-4o ignora o canal alfa e por isso se comporta de um jeito um tanto contraintuitivo
- “Ignora” não significa que ele remove a transparência compondo a imagem sobre um fundo padrão, como um editor de imagens faz ao converter PNG em JPG
- O GPT-4o literalmente pega apenas os canais RGB e ignora o canal alfa
- Isso pode ser explicado com 4 imagens cuidadosamente preparadas
- Por conveniência, usei HTML e CSS para exibir as imagens sobre um padrão quadriculado, e as próprias imagens têm um fundo plano e transparente
- No entanto, metade tem um fundo preto transparente, e a outra metade tem um fundo branco transparente
- O que significa “preto transparente” ou “branco transparente”?
- Ao representar uma cor RGBA com 4 bytes, os bytes RGB continuam existindo mesmo quando o alfa é 100%
- Portanto,
(0, 0, 0, 255) e (255, 255, 255, 255) são, em certo sentido, cores diferentes, mas como ambos são 100% transparentes, não há situação em que um renderizador correto os exibiria de forma diferente
- Se você perguntar ao GPT-4o o que ele “vê” nessas 4 imagens:
- Texto preto sobre fundo preto transparente: o GPT-4o lê como
""
- Texto preto sobre fundo branco transparente: o GPT-4o lê como
"ENORMOUS"
- Texto branco sobre fundo preto transparente: o GPT-4o lê como
"SCINTILLA"
- Texto branco sobre fundo branco transparente: o GPT-4o lê como
""
- O que está acontecendo aqui?
- Surge um padrão em que o GPT-4o só consegue ler o texto quando a cor do texto é diferente da “cor” do fundo transparente
- Isso mostra que o GPT-4o ignora o canal alfa e vê apenas os canais RGB. Para o GPT-4o, preto transparente é preto, e branco transparente é branco
- Isso fica mais claro se você manipular a imagem preservando os 3 canais RGB e definindo o canal alfa para 100%
- Usei uma função do Pillow para fazer isso
- Com isso, criei as duas imagens abaixo, em que os dados RGB são idênticos e só o canal alfa difere
- Canal alfa = 255: o GPT-4o consegue ver facilmente o ornitorrinco oculto
- Canal alfa = 0: o GPT-4o vê a imagem como completamente transparente
- Você pode baixar a imagem
hidden_platypus.png e inseri-la diretamente no ChatGPT para testar por conta própria, e ele a descreverá com precisão
- Você perceberá que o tamanho da imagem é 39,3 KB, igual ao de
platypus.png; se fosse uma imagem perfeitamente vazia e transparente, deveria ser muito menor por causa da compressão PNG
- Ou você pode usar a função acima para redefinir o canal alfa para 255 e restaurar a imagem original
- Não tenho certeza se isso é um bug, mas certamente é um comportamento surpreendente, e dá a impressão de que um usuário mal-intencionado poderia usá-lo para contrabandear informações diretamente para o GPT-4o, passando despercebido pelos humanos
- No entanto, o GPT-4o é muito melhor que o GPT-4v em detectar e ignorar prompts maliciosos escondidos em imagens
- Na galeria de imagens de teste do GPT-4o gerada com o utilitário
image_tagger, você pode encontrar outros exemplos em que o GPT-4o detecta e ignora com sucesso prompts maliciosos ocultos em imagens
- Portanto, mesmo que seja um bug, não está claro se ele pode ser explorado
- Ainda assim, seria menos surpreendente se o GPT-4o “visse” a mesma coisa que uma pessoa vê no navegador
2 comentários
Portanto,
(0, 0, 0, 255)e(255, 255, 255, 255)são cores diferentes em certo sentido, mas como ambas são 100% transparentes, não há situação em que um renderizador correto as exibiria de forma diferente.Para ser transparente, o alpha deveria ser 0, como em
(0, 0, 0, 0)e(255, 255, 255, 0), então parece que há um erro de digitação no texto principal.Opiniões do Hacker News