YouMind
Anmelden

Wir haben die ChatGPT Intelligent UI reverse-engineered. So funktioniert sie wirklich

@rabi_guha
ENGLISCH08. Okt. 2026
206K
2.0K
146
66
3.5K

TL;DR

Dieser Artikel beschreibt die technische Architektur hinter der neu eingeführten ChatGPT Intelligent UI im Detail. Er erklärt den Einsatz einer benutzerdefinierten Inferenzsprache (DIL), die serverseitige Kompilierung in JavaScript und JSON sowie die sichere clientseitige Ausführung über sandboxed Worker.

ChatGPT hat endlich Generative UI eingeführt und das Feld über Nacht in Intelligent UI umbenannt. Das mussten wir uns genauer ansehen, um zu verstehen, wie sie es umgesetzt haben.

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

Dieser Beitrag ist eine tiefgehende Analyse darüber, wie OpenAI sein Vorzeigeprodukt Intelligent UI implementiert hat – die Schichten, Formate und das native Rendering auf Web und Mobile.

Bausteine

Die Implementierung von ChatGPT verteilt die Arbeit auf das Modell, den Backend-Server und den Client:

  • Inferenzformat: Das Modell schreibt die Benutzeroberfläche in DIL, einer Sprache, die Markdown mit JSX-ähnlichen Tags und JavaScript kombiniert.
  • Serverseitige Kompilierung: Der Server wandelt jede Teilantwort in ein JavaScript-Programm und ein JSON-Dokument aus Text und Daten um.
  • Client-Laufzeitumgebung: Eine isolierte Laufzeitumgebung führt das Programm aus und erzeugt UI-Operationen.
  • Rendering: ChatGPT wendet die Operationen auf seine eigenen nativen Komponenten an.
  • Designsystem und Katalog: Die Komponenten, Eigenschaften und Design-Tokens, die dem Modell zur Verfügung stehen.
Rabi Shanker Guha - inline image

Architekturdiagramm der ChatGPT Intelligent UI

Inferenzformat

Das ist es, was das Modell ausgibt. Bei ChatGPT handelt es sich um eine Sprache, die OpenAI DIL nennt: Markdown für Fließtext, JSX-ähnliche Tags für Komponenten und JavaScript für State und Logik. Wir verfolgen nun eine kleine Antwort durch alle Schichten:

text
1## Kostenschätzung Team-Tarif
2Ziehe den Schieberegler, um den **monatlichen Preis** für dein Team zu sehen.
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}/Monat</title>
8</box>

Überschrift und Absatz sind gewöhnliches Markdown. Die Tags sind Komponenten aus dem Katalog von ChatGPT. Die beiden {@body …}-Zeilen sind JavaScript: Die erste deklariert einen State namens „seats", die zweite leitet daraus „price" ab. Der Slider ist an „seats" gebunden, sodass eine Änderung direkt den Preis aktualisiert.

Ein eigenes Format ist notwendig, weil das Modell die Oberfläche Token für Token generiert.

  • Es muss zuverlässig und einfach zu schreiben sein, daher basiert es auf Notationen, die das Modell bereits gut beherrscht.
  • Es muss auch im halbfertigen Zustand nutzbar bleiben. Anweisungen stehen in eigenen Zeilen, und jedes offene Element kann automatisch geschlossen werden. So kann der Server eine unvollständige Antwort beim letzten vollständigen Konstrukt abschneiden und trotzdem kompilieren.

Serverseitige Kompilierung

Der Client führt die Ausgabe des Modells niemals direkt aus. Der Server von OpenAI kompiliert sie in ein JavaScript-Programm und ein JSON-Dokument, die zusammen mit der Nachricht gespeichert werden (als model_dil_v2). Die Antwort wird zu Folgendem kompiliert (zur besseren Lesbarkeit formatiert):

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": "Kostenschätzung Team-Tarif",
4 "1": "Ziehe den Schieberegler, um den ",
5 "2": "monatlichen Preis",
6 "3": " für dein Team zu sehen.",
7 "4": "$",
8 "5": "/Monat"
9 },
10 "appData": { "opGenui": { "componentResults": {}, "modelDataBindings": {} } }
11}

Das Markdown wird in denselben Baum wie die Komponenten kompiliert. Aus der Überschrift wird ein „title", aus dem Absatz ein „text" mit einem „bold"-Element darin, und die Wörter wandern in die Konstantentabelle.

Die Kompilierung übernimmt Aufgaben, die sonst jeder Client wiederholen müsste:

  • Einfache Funktionsaufrufe. Markup wird zu Aufrufen von __dil.jsx, sodass eine JavaScript-Laufzeitumgebung das Programm ohne Parser für DIL auswerten kann.
  • Fehlerisolierung. Ausdrücke werden in __dilSafe verpackt. Wenn ein Ausdruck einen Fehler wirft, fällt nur ein Element weg, statt das gesamte Rendering abzubrechen.
  • Text in einer separaten Tabelle. Statischer Text wandert in die Konstantentabelle. Während eine Antwort gestreamt wird, verändert der wachsende Text also die Daten und nicht das Programm.
  • Stabile State-Keys. Jeder State erhält einen Key ({ key: "seats" }), damit sein Wert jede Neukompilierung übersteht.
  • Reparatur und Validierung. Unvollständige Anweisungen und Tags werden verworfen, offene Elemente geschlossen und Eigenschaften, die bei der Validierung gegen den Katalog durchfallen, entfernt und als Diagnose protokolliert.

Das JSON-Dokument enthält die Textkonstanten sowie alle Daten, die der Server für die Antwort auflöst, etwa Bildsuchergebnisse (siehe Daten).

Client-Laufzeitumgebung

Der Client empfängt das kompilierte Programm und das JSON-Dokument. Seine Aufgabe teilt sich auf eine Laufzeitumgebung, die das Programm ausführt, und einen Renderer, der das Ergebnis zeichnet.

Da das Programm vom Modell geschriebener Code ist, läuft es nicht direkt auf der ChatGPT-Seite. ChatGPT lädt stattdessen ein verstecktes iframe (runner.html), das mit allow-scripts und einer Content Security Policy von default-src 'none' isoliert ist und einen Web Worker startet.

  • Lockdown. Bevor ein Programm ausgewertet wird, entfernt der Worker Netzwerkzugriff, Timer, Messaging und dynamische Codeauswertung aus seinem globalen Scope und friert die verbleibenden Globals ein.
  • Auswertung. Anschließend wertet er das Programm mit new Function aus. Die Laufzeitobjekte (DIL, __dil, GenUI) und die zusammengesetzten Komponenten des Katalogs werden als Parameter übergeben.
  • Watchdog. Ein Programm, das nicht innerhalb eines Timeouts antwortet, wird isoliert und der Worker neu gestartet.

Die Laufzeitumgebung ist ein kleiner Reconciler im Stil von React. Sie rendert die Komponente und hält den Hook-State in Schlüssel-Slots. Dann vergleicht sie den resultierenden Baum mit dem vorherigen und kodiert die Unterschiede als Liste von Operationen. Gezeichnet wird dabei nichts.

Das folgende anschauliche Beispiel zeigt die Operationen eines ersten Renderings, mit einer Zeile pro Knoten. Einträge, die die Eigenschaftsnamen der einzelnen Elemente auflisten, wurden weggelassen:

text
1CREATE #1 title SET size = "lg" PLACE under root at 0
2CREATE #2 text "Kostenschätzung Team-Tarif" PLACE under #1 at 0
3CREATE #3 text PLACE under root at 1
4CREATE #4 text "Ziehe den Schieberegler, um den " PLACE under #3 at 0
5CREATE #5 bold PLACE under #3 at 1
6CREATE #6 text "monatlichen Preis" PLACE under #5 at 0
7CREATE #7 text " für dein Team zu sehen." 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 "/Monat" PLACE under #10 at 2

Funktionen verlassen den Worker nie; der Handler des Sliders wird nur als Kennung (fn#1) gesendet. Über die Leitung werden die Operationen als binäre Folge von Ganzzahlen kodiert, während Strings in einer separaten Tabelle gehalten werden.

Rendering

Die ChatGPT-Seite wendet die Operationen auf ihren eigenen Komponentenbaum an. Jedes CREATE instanziiert eine native Komponente aus dem Designsystem von ChatGPT, und die Seite animiert Änderungen, sobald sie eintreffen. Die Seite akzeptiert Operationen nur für bekannte Komponententypen, sodass die Modellausgabe kein beliebiges Markup oder Styles einschleusen kann. Ausnahmen bilden rohe CSS-Werte, die manche Eigenschaften akzeptieren (siehe Designsystem und Katalog), sowie AppBlock-Apps, die in einem iframe laufen (siehe Notausgang).

Interaktionen laufen in die entgegengesetzte Richtung. Zieht der Nutzer den Slider auf 9, sendet die Seite die Kennung des Handlers und die Argumente an den Worker. Der Worker ruft setSeats(9) auf, rendert neu und gibt Update-Operationen zurück. Ein Modellaufruf ist dafür nicht nötig.

Designsystem und Katalog

Der Katalog definiert, was das Modell anfordern darf. Er ist notwendig, weil das Modell keine Oberfläche aus rohen Layout- und Styling-Regeln baut. Es wählt aus Komponenten, die ChatGPT bereits zeichnen kann, und gestaltet sie mit Design-Tokens wie padding={3}. Rohe CSS-Werte wie Pixelbreiten oder Hex-Farben werden für einige Eigenschaften akzeptiert, aber Design-Tokens sind bevorzugt. Das Ergebnis:

  • Generierte Oberflächen passen auf jeder Plattform zum restlichen ChatGPT.
  • Der Compiler hat ein Schema, gegen das er die Ausgabe prüfen kann. Eine Eigenschaft, die bei einer Komponente nicht existiert, oder ein Literal vom falschen Typ wird während der Kompilierung entfernt und als Diagnose protokolliert.

In einer von uns erfassten Antwort entfernte der Compiler zwei Eigenschaften: fill bei einem Icon (Diagnose unknown_prop) und gap="1" bei einer Box (Diagnose invalid_literal).

Der Katalog besteht aus drei Teilen:

  • Native Komponenten. Rund 70 Komponenten sind in der Komponentenregistrierung im Client-Code von ChatGPT definiert; 39 davon tauchen in den von uns erfassten Antworten auf.
  • Design-Tokens für Abstände, Radius, Farbe und Größe.
  • Zusammengesetzte Komponenten, die OpenAI in DIL geschrieben hat und die vorgefertigt an die Sandbox gesendet werden, etwa die Bild- und Produktkomponenten. In unseren Aufzeichnungen nutzte das Modell diese Komponenten, definierte aber nie eigene.

Streaming

Text zu streamen ist einfach: Jedes neue Token wird an das angehängt, was bereits auf dem Bildschirm steht. Eine Oberfläche zu streamen ist aus drei Gründen schwieriger:

  • Die Ausgabe ist meist noch nicht ausführbar. In den meisten Momenten ist es ein unvollständiges Programm mit einem noch offenen Tag oder Ausdruck, das so nicht ausgeführt werden kann.
  • Die Oberfläche muss während des Wachstums funktionsfähig bleiben. Komponenten, die der Nutzer bereits berührt hat, müssen ihren State behalten.
  • Manche Inhalte treffen separat ein. Daten wie Bilder kommen vom Server, nicht aus dem Text.

Serverseitiges Streaming

Ein einfacher Stream aus angehängten Tokens kann das nicht abbilden. Stattdessen streamt ChatGPT Patches für eine strukturierte Nachricht, die Rohtext, kompiliertes Programm und dessen Daten nebeneinander enthält.

Die Antwort erreicht den Browser über einen Server-Sent-Event-Stream (POST /backend-api/f/conversation). Jedes Event ist ein Update im JSON-Patch-Stil für die gerade aufgebaute Nachricht. Ein einzelnes Event aktualisiert meist den rohen DIL-Text und seine kompilierte Form gleichzeitig. Hier ein gekürztes Update aus einer erfassten Antwort:

json
1{"o": "patch", "v": [
2 {"p": "/message/content/parts/0", "o": "append", "v": " Sonntags Lammbraten mit Freunden — reichlich Essen, …"},
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": "Hier ist ein Plan für einen richtigen Sonntags-Lammbraten mit Freunden — …"}},
5 {"p": "/message/metadata/model_dil_v2/constants", "o": "append", "v": {"1": "Da du"}},
6 {"p": "/message/metadata/model_dil_v2/fallbackMarkdown", "o": "append", "v": " Sonntags Lammbraten mit Freunden — …"}
7]}

Der Server kompiliert nicht inkrementell. Alle paar hundert Millisekunden – höchstwahrscheinlich mit jedem neuen Chunk der Modellausgabe – kompiliert er alles neu, was das Modell bisher geschrieben hat, und sendet das Ergebnis. Die Kompilierung beginnt mit dem ersten Token, bevor überhaupt ein Tag auftaucht.

Der Compiler muss sich um Folgendes kümmern:

  • Kompilieren einer halb geschriebenen Antwort
  • Aktualisieren von Text
  • Aktualisieren der UI

Der Zeitablauf sieht ungefähr so aus:

Rabi Shanker Guha - inline image

GIF

Clientseitiges Streaming

Die Seite übergibt jedes neue Update an den isolierten Worker. Der Worker wertet es aus, rendert mit dem bestehenden State neu und sendet Update-Operationen an die Seite. Der State behält seine Werte über Neukompilierungen hinweg, dank der Keys, die während der Kompilierung hinzugefügt werden. Schlägt die Auswertung oder das Rendering eines neuen Programms fehl, behält der Worker das letzte funktionierende bei.

Die Seite animiert dann jede Änderung:

  • Text blendet sich über 0,7 s ein;
  • neue Zeilen und Grid-Elemente gleiten über 0,42 s herein;
  • Diagramme zeichnen sich über 1,8 s auf;
  • Containerhöhen gehen fließend über, statt zu springen.

Notausgang: AppBlock, eine App im iframe

Rabi Shanker Guha - inline image

Von ChatGPT generierte Inline-App

Manche Anfragen erfordern Dinge, für die die nativen Komponenten nicht gemacht sind, etwa eine Drum Machine, die Sound mit Web Audio synthetisiert. Dafür kann das Modell einen AppBlock schreiben: eine eigenständige Web-App in HTML, CSS und JavaScript, eingebettet in die Antwort. Hier der gekürzte Anfang eines solchen Blocks:

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>

AppBlocks werden anders gerendert als die Komponenten der Intelligent UI.

Alles fügt sich zusammen

Du gibst einen Prompt ein. Das Modell beginnt, die Oberfläche zu schreiben, der Server macht daraus etwas, das ChatGPT ausführen kann, und die Seite baut sie Stück für Stück auf, während die Antwort eintrifft. Sobald sie da ist, aktualisiert das Verschieben eines Sliders oder das Setzen eines Häkchens die Oberfläche lokal, ohne das Modell erneut zu fragen.

Eine modellspezifische Sprache, ein serverseitiger Kompilierungsschritt, native Renderer und ein fundiertes Designsystem bringen alles zusammen. Jeder Teil erfüllt eine entscheidende Rolle, und gemeinsam liefern sie die nächste Generation KI-nativer Oberflächen an Milliarden Nutzer weltweit aus. Was für eine Zeit, um am Leben zu sein!

Rabi Shanker Guha - inline image

Screenshots der ChatGPT Intelligent UI

Methodik

Alle Beobachtungen stammen von unseren eigenen ChatGPT-Konten, aus dem Traffic, den die ChatGPT-Web-App erzeugt, und aus dem JavaScript, das chatgpt.com öffentlich ausliefert. Sie wurden im Oktober 2026 mit GPT-6 und GPT-6 Thinking durchgeführt.

Analyse mit Unterstützung von Codex & Claude. Geschrieben mit Codex, Visualisierungen von Claude

(Eine ausführlichere Version findest du unter https://www.openui.com/blog/how-chatgpt-intelligent-ui-works

Mit einem Klick speichern

Virale Artikel mit YouMind per KI tief lesen

Speichere die Quelle, stelle gezielte Fragen, fasse die Argumentation zusammen und verwandle einen viralen Artikel in wiederverwendbare Notizen in einem einzigen KI-Arbeitsbereich.

YouMind entdecken
Für Creator

Verwandle dein Markdown in einen sauberen 𝕏-Artikel

Wenn du eigene Langtexte veröffentlichst, wird die 𝕏-Formatierung von Bildern, Tabellen und Codeblöcken mühsam. YouMind macht aus einem ganzen Markdown-Entwurf einen sauberen, sofort postbaren 𝕏-Artikel.

Markdown zu 𝕏 testen

Mehr Muster zum Entschlüsseln

Aktuelle virale Artikel

Mehr virale Artikel entdecken