YouMind
Iniciar sessão

Engenhamos reversamente a Interface Inteligente do ChatGPT. Veja como ela realmente funciona

@rabi_guha
INGLÊS08/10/2026
206K
2.0K
146
66
3.5K

TL;DR

Este artigo detalha a arquitetura técnica por trás da recém-lançada Interface Inteligente do ChatGPT, explicando o uso de uma linguagem de inferência personalizada (DIL), a compilação no lado do servidor para JavaScript e JSON, e a execução segura no cliente via workers isolados.

O ChatGPT lançou a Generative UI (finalmente) e, da noite para o dia, rebatizou o conceito de Intelligent UI. Precisávamos entender como eles implementaram isso.

https://x.com/OpenAI/status/2107894997538525580

Este post é um estudo aprofundado sobre como a OpenAI implementou sua carro-chefe Intelligent UI: as camadas, os formatos e a renderização nativa na Web e no Mobile.

Blocos de construção

A implementação do ChatGPT divide o trabalho entre o modelo, o servidor de backend e o cliente:

  • Formato de inferência: o modelo escreve a interface em DIL, que combina Markdown com tags semelhantes ao JSX e JavaScript.
  • Compilação no servidor: o servidor converte cada resposta parcial em um programa JavaScript e em um documento JSON com texto e dados.
  • Runtime do cliente: um runtime em sandbox executa o programa e gera operações de UI.
  • Renderização: o ChatGPT aplica as operações aos seus próprios componentes nativos.
  • Design system e catálogo: os componentes, propriedades e design tokens disponíveis para o modelo.
Rabi Shanker Guha - inline image

Diagrama de arquitetura da Intelligent UI do ChatGPT

Formato de inferência

É isso que o modelo escreve. No ChatGPT, trata-se de uma linguagem que a OpenAI chama de DIL: Markdown para o texto corrido, tags parecidas com JSX para os componentes e JavaScript para estado e lógica. Vamos acompanhar uma pequena resposta passando por todas as camadas:

text
1## Estimativa do plano para equipes
2Arraste o controle deslizante para ver o **preço mensal** da sua equipe.
3{@body const [seats,setSeats] = DIL.useState(8)}
4{@body const price = seats*29}
5<box border padding={3} gap={2}>
6 <slider min={1} max={50} value={seats} onChange={setSeats}/>
7 <title size="xl">${price}/mês</title>
8</box>

O título e o parágrafo são Markdown comum. As tags são componentes do catálogo do ChatGPT. As duas linhas {@body …} são JavaScript: a primeira declara um pedaço de estado, seats, e a segunda deriva price a partir dele. O slider está vinculado a seats, então movê-lo atualiza o preço.

Um formato dedicado é necessário porque o modelo escreve a interface token por token.

  • Precisa ser fácil de escrever de forma confiável, por isso é construído a partir de notações que o modelo já conhece bem.
  • Precisa continuar utilizável mesmo quando escrito pela metade. As instruções ficam em linhas próprias, e qualquer elemento aberto pode ser fechado automaticamente. Isso permite que o servidor corte uma resposta parcial no último constructo completo e ainda assim consiga compilá-la.

Compilação no servidor

O cliente nunca executa a saída do modelo exatamente como ela foi escrita. O servidor da OpenAI a compila em um programa JavaScript e um documento JSON, que são armazenados junto com a mensagem (como model_dil_v2). A resposta é compilada para isto (formatado para facilitar a leitura):

javascript
1function __dilSafe(evaluate, failureValue) {
2 try { return evaluate(); } catch { return failureValue; }
3}
4
5DIL.render(__dil.jsx(() => {
6 const __dilConstants = DIL.useConstants();
7 const __dilModelDataBindings = DIL.useAppData((appData) => appData.opGenui?.modelDataBindings ?? {});
8 const [seats, setSeats] = DIL.useState(8, { key: "seats" });
9 const price = __dilSafe(() => seats * 29, undefined);
10 return __dil.jsx(__dil.Fragment, null,
11 __dil.jsx("title", { size: "lg" }, __dilConstants["0"]),
12 __dil.jsx("text", null, __dilConstants["1"], __dil.jsx("bold", null, __dilConstants["2"]), __dilConstants["3"]),
13 __dil.jsx("box", { border: true, padding: 3, gap: 2 },
14 __dilSafe(() => __dil.jsx("slider", { min: 1, max: 50, value: seats, onChange: setSeats }), null),
15 __dil.jsx("title", { size: "xl" }, __dilConstants["4"], __dilSafe(() => price, null), __dilConstants["5"])));
16}, { key: "body:2" }));
json
1{
2 "constants": {
3 "0": "Estimativa do plano para equipes",
4 "1": "Arraste o controle deslizante para ver o ",
5 "2": "preço mensal",
6 "3": " da sua equipe.",
7 "4": "$",
8 "5": "/mês"
9 },
10 "appData": { "opGenui": { "componentResults": {}, "modelDataBindings": {} } }
11}

O Markdown é compilado na mesma árvore dos componentes. O título vira um title, o parágrafo vira um text com um bold dentro, e as palavras vão para a tabela de constantes.

A compilação faz um trabalho que, de outra forma, cada cliente teria que repetir:

  • Chamadas de função simples. A marcação vira chamadas para __dil.jsx, permitindo que um runtime JavaScript avalie o programa sem precisar de um parser para DIL.
  • Isolamento de erros. As expressões são envolvidas em __dilSafe, então uma expressão que lance um erro remove apenas um elemento em vez de abortar toda a renderização.
  • Texto em uma tabela separada. O texto estático vai para a tabela de constantes, de modo que, durante o streaming da resposta, o crescimento do texto altere os dados, e não o programa.
  • Chaves de estado estáveis. Cada pedaço de estado recebe uma chave ({ key: "seats" }), para que seu valor sobreviva a todas as recompilações.
  • Reparo e validação. Instruções e tags incompletas são descartadas, elementos não fechados são fechados, e propriedades que falham na validação contra o catálogo são removidas e registradas como diagnósticos.

O documento JSON guarda as constantes de texto e quaisquer dados que o servidor resolva para a resposta, como resultados de busca de imagens (veja Dados).

Runtime do cliente

O cliente recebe o programa compilado e o documento JSON. Seu trabalho é dividido entre um runtime, que executa o programa, e um renderizador, que desenha o resultado.

Como o programa é um código escrito pelo modelo, ele não roda diretamente na página do ChatGPT. O ChatGPT carrega um iframe oculto (runner.html), isolado em sandbox com allow-scripts e uma política de segurança de conteúdo default-src 'none', que inicia um Web Worker.

  • Lockdown. Antes de avaliar um programa, o worker remove o acesso à rede, timers, mensagens e avaliação dinâmica de código de seu escopo global, além de congelar os globais restantes.
  • Avaliação. Em seguida, ele avalia o programa com new Function. Os objetos do runtime (DIL, __dil, GenUI) e os componentes compostos do catálogo são passados como parâmetros.
  • Watchdog. Um programa que não responder dentro de um tempo limite é colocado em quarentena, e o worker é reiniciado.

O runtime é um pequeno reconciler no estilo do React. Ele renderiza o componente e mantém o estado dos hooks em slots com chaves. Depois, compara a árvore resultante com a anterior e codifica as diferenças como uma lista de operações. Ele não desenha nada.

O exemplo ilustrativo abaixo mostra as operações de uma primeira renderização, com uma linha por nó. Entradas que listam os nomes das propriedades de cada elemento foram omitidas:

text
1CREATE #1 title SET size = "lg" PLACE under root at 0
2CREATE #2 text "Estimativa do plano para equipes" PLACE under #1 at 0
3CREATE #3 text PLACE under root at 1
4CREATE #4 text "Arraste o controle deslizante para ver o " PLACE under #3 at 0
5CREATE #5 bold PLACE under #3 at 1
6CREATE #6 text "preço mensal" PLACE under #5 at 0
7CREATE #7 text " da sua equipe." PLACE under #3 at 2
8CREATE #8 box SET border = true, padding = 3, gap = 2 PLACE under root at 2
9CREATE #9 slider SET min = 1, max = 50, value = 8, onChange = fn#1 PLACE under #8 at 0
10CREATE #10 title SET size = "xl" PLACE under #8 at 1
11CREATE #11 text "$" PLACE under #10 at 0
12CREATE #12 text "232" PLACE under #10 at 1
13CREATE #13 text "/mês" PLACE under #10 at 2

As funções nunca saem do worker; o handler do slider é enviado apenas como um identificador (fn#1). Na transmissão, as operações são codificadas como uma sequência binária de inteiros, com as strings mantidas em uma tabela separada.

Renderização

A página do ChatGPT aplica as operações à sua própria árvore de componentes. Cada CREATE instancia um componente nativo do design system do ChatGPT, e a página anima as mudanças conforme elas chegam. A página aceita operações apenas para tipos de componentes conhecidos, então a saída do modelo não pode introduzir marcações ou estilos arbitrários. As exceções são os valores CSS brutos aceitos por algumas propriedades (veja Design system e catálogo) e os apps AppBlock, que rodam em um iframe (veja Válvula de escape).

A interação segue o caminho inverso. Quando o usuário arrasta o slider para 9, a página envia o identificador e os argumentos do handler para o worker. O worker chama setSeats(9), renderiza novamente e devolve as operações de atualização. Nenhuma chamada ao modelo está envolvida.

Design system e catálogo

O catálogo define o que o modelo pode solicitar. Ele é necessário porque o modelo não constrói uma interface a partir de regras brutas de layout e estilo. Ele escolhe entre componentes que o ChatGPT já sabe desenhar e os estiliza com design tokens, como padding={3}. Valores CSS brutos, como larguras em pixels e cores hexadecimais, são aceitos em algumas propriedades, mas os design tokens são preferidos. Como resultado:

  • As interfaces geradas se parecem com o resto do ChatGPT em todas as plataformas.
  • O compilador tem um esquema para validar a saída. Uma propriedade que não existe em um componente, ou um literal do tipo errado, é removida durante a compilação e registrada como diagnóstico.

Em uma resposta que capturamos, o compilador removeu duas propriedades: fill em um ícone (um diagnóstico unknown_prop) e gap="1" em uma caixa (um diagnóstico invalid_literal).

O catálogo tem três partes:

  • Componentes nativos. Cerca de 70 componentes estão definidos no registro de componentes no código do cliente do ChatGPT; 39 deles apareceram nas respostas que capturamos.
  • Design tokens para espaçamento, raio, cor e tamanho.
  • Componentes compostos escritos pela OpenAI em DIL e enviados pré-construídos para o sandbox, como os componentes de imagem e produto. Nas nossas capturas, o modelo usou esses componentes, mas nunca definiu os seus próprios.

Streaming

Fazer streaming de texto é simples: cada novo token é anexado ao que já está na tela. Fazer streaming de uma interface é mais difícil, por três motivos:

  • A saída geralmente ainda não é executável. Na maior parte do tempo, é um programa incompleto, com uma tag ou expressão ainda aberta, e não pode ser executado como está.
  • A interface precisa continuar funcionando enquanto cresce. Componentes com os quais o usuário já interagiu devem manter seu estado.
  • Parte do conteúdo chega separadamente. Dados como imagens vêm do servidor, e não do texto.

Streaming no servidor

Um fluxo simples de tokens anexados não consegue expressar isso. Em vez disso, o ChatGPT transmite patches para uma mensagem estruturada que mantém o texto bruto, o programa compilado e seus dados lado a lado.

A resposta chega ao navegador por meio de um stream de server-sent events (POST /backend-api/f/conversation). Cada evento é uma atualização no estilo JSON-Patch para a mensagem que está sendo construída. Um único evento costuma atualizar o texto DIL bruto e sua forma compilada ao mesmo tempo. Esta é uma atualização de uma resposta capturada, encurtada:

json
1{"o": "patch", "v": [
2 {"p": "/message/content/parts/0", "o": "append", "v": " Assado de cordeiro de domingo com amigos — comida farta, …"},
3 {"p": "/message/metadata/model_dil_v2/code", "o": "replace", "v": "DIL.render(__dil.jsx(()=>{…"},
4 {"p": "/message/metadata/model_dil_v2/constants", "o": "append", "v": {"0": "Aqui está um plano para um autêntico assado de cordeiro de domingo com amigos — …"}},
5 {"p": "/message/metadata/model_dil_v2/constants", "o": "append", "v": {"1": "Já que você está"}},
6 {"p": "/message/metadata/model_dil_v2/fallbackMarkdown", "o": "append", "v": " Assado de cordeiro de domingo com amigos — …"}
7]}

O servidor não compila de forma incremental. A cada poucas centenas de milissegundos, muito provavelmente a cada novo bloco de saída do modelo, ele recompila tudo o que o modelo escreveu até aquele momento e envia o resultado. A compilação começa com o primeiro token, antes mesmo de qualquer tag aparecer.

O compilador precisa cuidar de:

  • Compilar uma resposta escrita pela metade
  • Atualizar o texto
  • Atualizar a UI

A linha do tempo funciona mais ou menos assim:

Rabi Shanker Guha - inline image

GIF

Streaming no cliente

A página passa cada nova atualização para o worker em sandbox. O worker a avalia, renderiza novamente usando o estado existente e envia as operações de atualização para a página. O estado mantém seus valores entre as recompilações graças às chaves adicionadas durante a compilação. Se um novo programa falhar na avaliação ou na renderização, o worker mantém o último que funcionou.

A página então anima cada mudança:

  • o texto aparece suavemente em 0,7 s;
  • novas linhas e itens de grid deslizam para a tela em 0,42 s;
  • gráficos são desenhados ao longo de 1,8 s;
  • as alturas dos contêineres fazem uma transição suave em vez de saltarem abruptamente.

Válvula de escape: AppBlock, um app em um iframe

Rabi Shanker Guha - inline image

App inline gerado pelo ChatGPT

Algumas solicitações exigem coisas para as quais os componentes nativos não foram projetados, como uma bateria eletrônica que sintetiza som com o Web Audio. Para esses casos, o modelo pode escrever um AppBlock: um web app independente em HTML, CSS e JavaScript, incorporado na resposta. Este é o início de um deles, encurtado:

text
1<AppBlock title="Laboratório de Bateria" icon="app-chatgpt" variant="inline" app_block_id="drum-lab-01">
2<div id="dl" class="w-full min-w-0 space-y-4 text-base">
3 <style>
4 #dl{color:var(--viz-text)}#dl button{touch-action:manipulation}#dl .panel{background:var(--viz-panel);border:1px solid var(--viz-border);border-radius:15px}…
5 </style>
6 …
7 <button id="dl-play" class="btn" style="background:var(--viz-text);color:var(--viz-card);min-width:100px">▶ Tocar</button>
8 …
9</div>
10<script>
11(function(){
12const root=document.getElementById('dl');if(root.dataset.init)return;root.dataset.init="yes";
13…
14function audioInit(){if(!audio){const C=window.AudioContext||window.webkitAudioContext; if(!C)return false;audio=new C();…
15…
16})();
17</script>
18</AppBlock>

Os AppBlocks são renderizados de maneira diferente dos componentes da Intelligent UI.

Juntando tudo

Você digita um prompt. O modelo começa a escrever a interface, o servidor a transforma em algo que o ChatGPT possa executar, e a página a constrói peça por peça enquanto a resposta chega via streaming. Quando está pronta, mover um slider ou marcar uma caixa de seleção atualiza a interface localmente, sem precisar consultar o modelo novamente.

Uma linguagem específica para o modelo, uma etapa de compilação no servidor, renderizadores nativos e um design system bem fundamentado fazem tudo funcionar em conjunto. Cada parte cumpre um papel essencial e, juntas, entregam a próxima geração de interfaces nativas de IA para bilhões de usuários no mundo todo. Que época para estar vivo!

Rabi Shanker Guha - inline image

Capturas de tela da Intelligent UI do ChatGPT

Metodologia

Todas as observações vieram de nossas próprias contas do ChatGPT, do tráfego gerado pelo aplicativo web do ChatGPT e do JavaScript que o chatgpt.com disponibiliza publicamente. Elas foram feitas em outubro de 2026 com o GPT-6 e o GPT-6 Thinking.

Análise feita com a ajuda do Codex e do Claude. Escrito com o Codex, visualizações pelo Claude.

(Uma versão mais detalhada está em https://www.openui.com/blog/how-chatgpt-intelligent-ui-works

Guardar com um clique

Faça leitura aprofundada de artigos virais com IA no YouMind

Guarde a fonte, faça perguntas específicas, resuma o argumento e transforme um artigo viral em notas reutilizáveis num único espaço de trabalho com IA.

Explorar o YouMind
Para criadores

Transforme o seu Markdown num artigo 𝕏 impecável

Quando publica os seus próprios textos longos, formatar imagens, tabelas e blocos de código para o 𝕏 é uma dor de cabeça. O YouMind transforma um rascunho completo em Markdown num artigo 𝕏 impecável e pronto a publicar.

Experimente Markdown para 𝕏

Mais padrões para decifrar

Artigos virais recentes

Explorar mais artigos virais