YouMind
Entrar

Engenharia reversa da Intelligent UI do ChatGPT: como ela realmente funciona

@rabi_guha
INGLÊS08 de out. de 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 Intelligent UI do ChatGPT, explicando o uso de uma linguagem de inferência customizada (DIL), a compilação no lado do servidor para JavaScript e JSON, e a execução segura no cliente via workers em sandbox.

O ChatGPT lançou a Generative UI (finalmente) e, da noite para o dia, rebatizou a área como 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 principal 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 parecidas com 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 no 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 é o 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 na última estrutura completa 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 precisaria 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 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 no 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 definida como default-src 'none', que inicia um Web Worker.

  • Lockdown. Antes de avaliar um programa, o worker remove acesso à rede, timers, mensagens e avaliação dinâmica de código do 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 puros 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 oposto. 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 puros, 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 têm a mesma cara do 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 um box (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 a 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.
  • Alguns conteúdos chegam 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 faz streaming de 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 normalmente atualiza 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 se parece com algo 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 dentro em 0,42 s;
  • gráficos são desenhados ao longo de 1,8 s;
  • as alturas dos contêineres fazem transição em vez de saltar abruptamente.

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

Rabi Shanker Guha - inline image

App inline gerado pelo ChatGPT

Algumas solicitações pedem coisas para as quais os componentes nativos não foram projetados, como uma bateria eletrônica que sintetiza som com 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="Drum Lab" 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">▶ Play</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 ela está pronta, mover um slider ou marcar uma caixa de seleção atualiza a interface localmente, sem precisar consultar o modelo de novo.

Uma linguagem específica para o modelo, uma etapa de compilação no servidor, renderizadores nativos e um design system bem fundamentado juntam todas as peças. 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 das nossas próprias contas do ChatGPT, do tráfego gerado pelo aplicativo web do ChatGPT e do JavaScript que o chatgpt.com serve publicamente. Elas foram feitas em outubro de 2026 com GPT-6 e GPT-6 Thinking.

Análise feita com a ajuda de Codex & Claude. Escrito com Codex, visualizações por Claude

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

Salvar com um clique

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

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

Explorar o YouMind
Para criadores

Transforme seu Markdown em um artigo 𝕏 impecável

Quando você publica 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 em um artigo 𝕏 impecável e pronto para publicar.

Experimente Markdown para 𝕏

Mais padrões para decifrar

Artigos virais recentes

Explorar mais artigos virais