Dev

Ein Modell ist eine Abhängigkeit, die nicht stillhält

Eine gepinnte Software-Bibliothek ist ein Artefakt, das du inspizieren und erneut ausführen kannst: Wenn sich die Ausgabe geändert hat und du nichts geändert hast, dann hat sich etwas Lesbares geändert, und du kannst herausfinden, was. Ein Modell durchbricht das. Es verschiebt sich hinter einem unveränderten Namen, verliert ohne Vorwarnung Kapazität und driftet in seiner Disposition, also kommt eine Regression ohne Ursache, auf die du zeigen kannst, und du verschwendest eine Woche damit, deinen eigenen Prompt zu beschuldigen. Behandle es als eine Abhängigkeit, die du misst, nicht als ein Fundament, dem du vertraust: Pinne die Version, damit dir der Moment gehört, in dem sie sich ändert, und lege vorab ein kleines Set billiger Metriken fest, damit du die Drift des Anbieters von deiner eigenen unterscheiden kannst.

Einer meiner geplanten Jobs kam auf einmal schlechter zurück, und das Erste, was ich tat, war, meine eigene Config zu öffnen.

Das ist fast immer der richtige Instinkt. Wenn etwas, das du gebaut hast, schlechter wird, sitzt der Fehler meistens auf deiner Seite der Linie: ein Prompt, den du bearbeitet hast, ein Default, dessen Änderung du vergessen hast. Also habe ich gesucht, und ich habe eine Sache gefunden. Ich hatte in dieser Woche eine alte Formatierungsregel wiederhergestellt. Sie erklärte nicht offensichtlich, was ich sah, und das Modell darunter war ungefähr zur selben Zeit ebenfalls auf eine neue Version umgesprungen. Zwei Änderungen, ein Symptom, und die ehrliche Position war, dass ich noch nicht sagen konnte, welche davon es verursachte.

Was ich sagen wollte, war, dass das Modell schlechter geworden sei. Das ist das Gefühl, das jeder Entwickler bekommt, wenn ein Anbieter eine neue Version ausliefert und sich die Ausgabe verschiebt. Aber nach dem Modell als Schuldigem zu greifen, während eine eigene Änderung genau da in derselben Woche liegt, ist genau der Zug, der mich schon einmal eine Woche gekostet hat. Hier geht es um das Instrument, das ich gebaut habe, damit ich nicht raten muss.

Denn ein Modell tut etwas, das keine andere Abhängigkeit tut. Ein Fundament ist der Teil, auf dem du baust und über den du dann aufhörst nachzudenken, weil er sich nicht bewegt. Ein Modell bewegt sich. Es bewegt sich unter seinem eigenen Namen, nach dem Zeitplan eines anderen, und es nimmt dir die eine Eigenschaft, die es überlebbar macht, sich auf Code zu verlassen, der dir nicht gehört: die Fähigkeit, bei einer geänderten Ausgabe zu sagen, ob sich die Abhängigkeit geändert hat oder du.

Eine gepinnte Bibliothek hält still. Ein Modell nicht

Alles am Verlassen auf Code, den du nicht geschrieben hast, ruht auf einer Schlussfolgerung: Wenn sich die Ausgabe geändert hat und ich meine Seite nicht geändert habe, dann hat sich die Abhängigkeit geändert, und ich kann genau herausfinden, wie, denn eine gepinnte Bibliothek ist ein Artefakt, das ich inspizieren kann. Ich kann ihre Bytes lesen, ihren Abhängigkeitsgraphen ablaufen und sie in einer kontrollierten Umgebung erneut ausführen. Sperre die Version mit einem Lockfile und einem Hash, und das, worauf du dich verlässt, hört auf, ein bewegliches Ziel zu sein. Es ist nicht so, dass die Bibliothek auf magische Weise deterministisch wäre, denn sie kann sich immer noch auf eine Uhr, einen Zufalls-Seed oder einen Netzwerkaufruf stützen. Es ist so, dass festgelegt und geprüft werden kann, was sie ist, und deshalb hat eine überraschende Ausgabe nur eine kurze Liste an Orten, an denen sie sich verstecken kann.

Ein gehostetes Modell gibt dir davon fast nichts. Fang beim Namen an. Zeig auf einen veränderlichen Alias, und der Anbieter kann ihn auf einen neuen Snapshot umlegen, ohne dass sich dein Versions-String überhaupt ändert, und selbst um einen festen Snapshot herum können sich das Routing, der Serving-Stack und die Sicherheitsfilter zwischen einem Lauf und dem nächsten verschieben. Dann ist da die Ausgabe selbst. Sie ist eine Verteilung, kein Wert, also rettet dich auch das Setzen der Temperatur auf null nicht: Bei gehosteter Inferenz sickern Batch-Zusammensetzung und Kernel-Nichtdeterminismus durch, und „es ist schlechter geworden" und „ich habe eine unglückliche Stichprobe gezogen" sind dieselbe Beobachtung, bis du genauer hinsiehst. Leg diese beiden zusammen, und ein verschlechterter Job reicht dir eine Änderung ohne Ursache, auf die du zeigen kannst. Der Versions-String, der einzige Hebel, nach dem du normalerweise greifen würdest, hält vielleicht nicht einmal still.

Der Pin ist also nicht für Stabilität da. Er ist für die Zuordnung da

Also pinne ich die Modellversion überall, wo meine geplante Arbeit läuft, und ich bin präzise darin, was das bringt. Es garantiert nicht, dass das Modell an Ort und Stelle bleibt, denn ein gepinnter Snapshot sitzt immer noch auf Serving-Infrastruktur, die der Anbieter bewegt. Was es beseitigt, ist ein Verdächtiger. Wenn etwas driftet und ich die Version nie angefasst habe, ist die Erklärung „ich habe ein Upgrade eingespielt" vom Tisch. Und ein Pin tut eine Sache, die das Zurücklesen der ausgelieferten Version aus jeder Antwort nicht kann: Er lässt mich den Moment wählen, in dem sich die Version ändert, sodass das Davor und das Danach auf beiden Seiten einer Linie liegen, die ich gezogen habe, während alles andere gehalten wird. Diese saubere Baseline ist der größte Teil des Spiels.

Der Pin allein reicht immer noch nicht, denn das eigene Rauschen des Modells hält kleine Regressionen im Streuen von Lauf zu Lauf verborgen, und weil eine einzelne Zahl zwei gleichzeitige Änderungen nicht auseinanderziehen kann. Sowohl meine wiederhergestellte Regel als auch eine Modellverschiebung würden „die Ausgabe hat sich geändert" bewegen. Die andere Hälfte ist also ein kleines Set billiger Metriken, das ich festlege, bevor ich irgendetwas anfasse: nicht eine Zahl, sondern zwei oder drei, deren Empfindlichkeiten sich unterscheiden, sodass mir sagt, was sich bewegt hat, welche von ihnen sich bewegt. Dieser Job vom Anfang, der Stapel kurzer Status-Zusammenfassungen, der schlechter zurückkam, ist der, den ich haben will. Ich beobachtete zwei Zahlen, die ich für jede Zusammenfassung berechnen konnte: wie lange sie lief und in wie viele Stichpunkte sie den Status aufbrach. Die Formatierungsregel, die ich wiederhergestellt hatte, verlangt einen Stichpunkt pro Element, also treibt sie die Anzahl der Stichpunkte; wie lang der Lauf ist, bleibt Sache des Modells. Als ich die Version auf die gepinnte zurückrollte, fiel die Länge auf ihr altes Band, während die Anzahl der Stichpunkte weiter kletterte. Die Länge war dem Modell gefolgt, die Stichpunkte waren meiner Regel gefolgt. Zwei Verdächtige, zwei Zahlen, und sie fielen auseinander, weil ich Zahlen gewählt hatte, die das tun würden.

Nichts davon ist ein Beweis, und ich halte es locker. Eine Handvoll Läufe gegen eine Verteilung kauft keine Gewissheit. Aber es zeigte den Pfeil an: Die aufgeblähte Länge gehörte dem Modell, die zusätzliche Struktur gehörte mir, und ich wusste, wo ich zuerst nachsehen musste, statt einen Prompt gegen die falsche Ursache umzuschreiben. Das ist der gesamte Wert. Ohne eine vorab festgelegte Zahl lässt sich „das Modell ist schlechter geworden" weder zeigen noch ausschließen, und du wirst das Menschliche tun und deinen eigenen Prompt wieder aufmachen, um gegen einen Störfaktor zu kämpfen, den du nicht sehen kannst. Beim ersten Mal, als mir das passierte, tat ich genau das, und meine saubere Geschichte, dass das neue Modell einfach schlechter sei, überlebte einen skeptischen Leser nicht, der mir zeigte, dass ich das Modell für eine Änderung von mir selbst beschuldigt hatte. Das Set ist das, was ich gebaut habe, damit der nächste Störfaktor keinen Reviewer braucht, um ihn zu entwirren.

Auch die Kapazität ist nicht stabil, und sie versagt auf dieselbe Weise

Du könntest all das über das Verhalten zugestehen und trotzdem annehmen, dass die Menge an Modell, die du bekommst, feststeht, weil dieser Teil in deinen Tarif geschrieben ist. Er steht nicht fest. Community-Berichte, die ich nicht gegen mein eigenes Messgerät prüfen konnte, beschreiben eine beworbene Kapazitätsänderung, die als Kürzung ankam: Die Ankündigung sagte mehr, und der Durchsatz, den die Leute sahen, sagte weniger. Lass beiseite, ob der Anbieter die Zahl bewegt hat. Die Zuordnungsfrage darunter ist dieselbe wie vorher, eine Ebene tiefer. Wenn dein Durchsatz fällt, ist ihr Angebot geschrumpft, oder ist deine eigene Last gewachsen? Das sind zwei aktive Ursachen für ein Symptom, und nichts als eine über die Zeit geführte Aufzeichnung deiner eigenen Last trennt sie. Niemand in diesen Threads konnte es mit Sicherheit sagen, und das ist der verräterische Hinweis: Ohne dein eigenes Messgerät ist die Beschreibung des Anbieters der einzige Bericht, den du hast, und die Beschreibung ist Werbetext, keine Garantie.

Die Upgrade-Entscheidung ist dasselbe Problem mit einem freundlicheren Gesicht. Eine neue Generation wird ausgeliefert, und die Migrationsnotiz sagt dir, dass eine billigere Einstellung jetzt Ergebnisse liefert, die der letzten Version ähnlich oder besser sind. Vielleicht tut sie das. Aber „ähnlich oder besser" ist eine Aussage über einen aggregierten Benchmark, nicht über den einen engen Job, den du im Schlaf laufen lässt, und der einzige Weg zu lernen, was von beidem für deinen Job zutrifft, ist, das Set behalten und über den Wechsel hinweg laufen gelassen zu haben. Eine Regression zu diagnostizieren und zu entscheiden, ob man ein Upgrade annimmt, erweisen sich als dieselbe Messung, in zwei Richtungen gestellt.

Was dir das Framing als Abhängigkeit tatsächlich bringt

Sobald du aufhörst, das Modell ein Fundament zu nennen, und anfängst, es als eine Abhängigkeit zu behandeln, die du nicht vollständig kontrollieren kannst, fällt der Rest des Designs so heraus, wie er das für jede solche Abhängigkeit tut. Isoliere es hinter einer Schnittstelle, und der Austausch der Engine wird zu einer Konfigurationsänderung statt zu einem Rebuild. Betreibe ein Portfolio statt eines einzelnen Modells, auf den Job abgestimmt, und du triffst auf den Fall, der auf dem Kopf zu stehen scheint, bis du ihn erlebt hast: Die Disposition, die ein Modell zu einem schlechten unbeaufsichtigten Arbeiter macht, ist dieselbe Disposition, die es zu einem scharfen Reviewer macht. Für die mechanische Masse, die das teure Modell nie brauchte, bleibt ein billigeres fest verdrahtet. Und weil ein Angebot, das ohne Vorwarnung schrumpfen kann, nichts ist, worauf man eine harte Abhängigkeit baut, entwirfst du den degradierten Modus, bevor die Kürzung eintrifft, statt danach zu hetzen.

All das ist real, und all das kommt danach. Das Portfolio, das Routing, der Fallback: Keines davon hilft, wenn du nicht sagen kannst, welches Mitglied des Portfolios sich geändert hat oder ob es sich überhaupt geändert hat. Die Messung kommt zuerst, weil sie das Fundament ist, das das Modell selbst sich weigert zu sein.

Ein Fundament darfst du vergessen. Das ist der ganze Sinn des Wortes. Diese Abhängigkeit darfst du nicht vergessen, denn sie wird sich unter ihrem eigenen Namen nach einem Zeitplan bewegen, den du nicht setzt, und die erwachsene Antwort ist, sie als genau das zu behandeln: das wichtigste und am wenigsten verlässliche Ding im Stack. Pinne es, damit dir der Moment gehört, in dem es sich ändert. Lege deine Metriken fest, bevor es das tut, damit die Änderung lesbar bleibt, wenn sie kommt. Und führe die Aufzeichnung selbst, denn die Versionsnummer ist das Versprechen des Anbieters über die Identität, und es ist ein Versprechen, das sie nicht ganz halten.

Diskussion

Hier gibt es keine Kommentarspalte. Diskussionen laufen auf X.

Max Nardit

Max Nardit

@mnardit

Weitere Artikel

Dein Freigabe-Gate ist jetzt eine Vermutung

Eine Sicherheitsgrenze wird an der einen Aktion gemessen, die gebaut wurde, um sie zu überschreiten, und genau dort ist ein Modell, das nach Ähnlichkeit urteilt, am schwächsten. Die unbeaufsichtigte Freigabe gehört an die Reichweite, die der Harness selbst vergibt, den Schreibbereich, das Netzwerk, das Credential, und verweigert, was sie nicht verantworten kann. Vertrau dem Modell als Grenze, und du baust genau die Naht wieder auf, die Prompt-Injection-Erkennung nie schließen konnte.

Dein Watchdog killt den beschäftigten Agenten und vertraut dem festgefahrenen

Ein Health-Check, der nur beobachtet, ob ein langlaufender Agent noch existiert, liegt in beiden schweren Fällen falsch: Er killt einen gesunden Agenten in dem Moment, in dem der still genug wird, um abwesend zu wirken, und winkt einen eingefrorenen durch, dessen Prozess weiter läuft. Die Reparatur ist keine schärfere Probe, sondern ein anderes Signal, die dauerhafte Spur, die ein Agent nur durch das Tun der Arbeit hinterlässt und die ein festgefahrener nicht weiter verlängert, weil das Verlängern die Arbeit ist.

Dein geforkter Subagent weiß bereits zu viel

Die Historie eines Agenten enthält jede Sackgasse, in die er gelaufen ist, und nichts darin markiert, welche davon er inzwischen aufgegeben hat. Delegiere diese Historie an eine Teilaufgabe, und die verworfenen Vermutungen kommen mit demselben Gesicht an wie die gesicherten Fakten. Warum ein sauberer Start meist gewinnt, wann ein geschriebener Auftrag die Vererbung schlägt, und wann die Arbeit ein lebendiges Ding ist, das kein Auftrag fassen kann.