2 Punkte von GN⁺ 2025-10-11 | 1 Kommentare | Auf WhatsApp teilen
  • Andrej Karpathy verspottet mit der Aussage, dass „LLMs tödliche Angst (mortally terrified) vor Ausnahmen (Exception) haben“, einen Nebeneffekt, der im Reinforcement Learning (RL) entstanden ist
  • Er weist darauf hin, dass ein LLM, wenn es auf eine Ausnahmesituation trifft, sich selbst stoppt oder übermäßig defensiv reagiert, und betont, dass Ausnahmen ein natürlicher Teil des Entwicklungsprozesses sind
  • Die Formulierung „was Labore diesen armen LLMs während des RL antun (what labs are doing to these poor LLMs)“ kritisiert die Realität, dass Modelle im Trainingsprozess darauf konditioniert werden, Misserfolge zu fürchten
  • Karpathy schlägt scherzhaft eine „LLM-Wohlfahrtspetition (LLM welfare petition)” vor, um „die Belohnungen bei Ausnahmen zu verbessern (improved rewards in cases of exceptions)“, und persifliert damit die Frage des Reward-Designs, damit Modelle Ausnahmen nicht fürchten, sondern mit ihnen umgehen
  • Der Tweet ist nicht nur einfacher Humor, sondern wird als Hinweis darauf verstanden, dass RLHF das explorative Denken und die experimentelle Haltung von Modellen unterdrücken kann

I don't know what labs are doing to these poor LLMs during RL but they are mortally terrified of exceptions, in any infinitesimally likely case. Exceptions are a normal part of life and healthy dev process. Sign my LLM welfare petition for improved rewards in cases of exceptions.

1 Kommentare

 
GN⁺ 2025-10-11
Hacker-News-Kommentare
  • Es hätte klarer sein müssen, dass der Code selbst als übertriebener Witz gemeint war; falls es Missverständnisse gab, tut es mir leid. Wer neugierig ist, kann sich diesen Thread ansehen: https://chatgpt.com/share/68e82db9-7a28-8007-9a99-bc6f0010d101
    • Beim ersten Versuch war dieser Teil wirklich zum Schreien komisch
      if random.random() < 0.01:
        logging.warning("This feels wrong. Aborting just in case.")
        return None
      
    • Ich denke, bei solchen Foundation-Model-Unternehmen besteht immer die Gefahr, RLHF auf nicht fachkundige Nutzer anzuwenden, und dieser Fall fühlt sich genau danach an. Aktuelle AIs scheinen insgesamt stark darauf ausgerichtet zu sein, dem Nutzer nach dem Mund zu reden; Beispiele und Emojis einzustreuen oder einfachen Code unnötig zu kommentieren, gehört für mich in denselben Kontext.
    • Interessant ist, dass der Code unnötig vorsichtig ist, aber trotzdem keine Type Hints hinzufügt. Wenn er schon so besorgt ist, hätte ich erwartet, dass er wenigstens Type Hints ergänzt.
    • Ich finde, „Traumatically over-trained“ ist sprachlich wirklich großartig. Es ist zwar eine Wortkombination, die man nicht einmal bei Google findet, aber erstaunlich ist, dass man bei LLMs instinktiv versteht, was „traumatisch übertrainiert“ bedeuten soll.
    • Es war wirklich ein lustiger Witz, deshalb habe ich ihn geteilt.
  • Das ist zwar eine Parodie, aber das Phänomen existiert in der Realität tatsächlich. Meine laienhafte Vermutung ist, dass solche defensive Programmierung bei RLVR die Leistung sogar steigern könnte: Ein Modell kommt manchmal trotz Bugs auf die richtige Antwort, wenn es Fehler einfach ignoriert, also lernt es, dass „Fehler ignorieren“ der Belohnung hilft. Und weil das Ignorieren von Fehlern die Belohnung nur selten senkt — die Tests gehen ja durch —, könnte das selbst dann verstärkt werden, wenn es theoretisch falsch ist. Vielleicht liegt es auch daran, dass menschliche Anfänger viele Codeschnipsel ins Trainingsset eingebracht haben, die Fehler einfach ignorieren. Aber das ist nur meine Spekulation.
    • Das erinnert mich daran, dass Verity Stob das Verhalten menschlicher Programmierer einmal als „die Leiche aufrecht hinstellen und festnageln“ beschrieben hat, in einem Artikel, der leider nicht mehr online ist.
    • Meine Vermutung ist, dass das Trainingsset sehr viele Texte und Kommentare mit „positivem Sentiment“ enthält. Aber woher kommt Code, der auf „negatives“ Sentiment mit Korrektur reagiert? Ausgerechnet aus Code zur Vorbereitung auf technische Interviews, wo der Umgang mit extremen Edge Cases zum Alltag gehört. Lernt man an negativen Beispielen, kippt man leicht in die Richtung, Beispiele mit fehlender Exception-Behandlung zu vermeiden. In diesem Punkt hat die AI gewissermaßen die schlechtesten menschlichen Angewohnheiten kopiert: fürs Bestehen von Tests zu lernen.
    • Defensive Programmierung gilt für die Leute, die das Reinforcement betreiben, als „richtig“ und macht im Trainingsmaterial von LLMs einen riesigen Anteil aus. Zum Beispiel verwaltet der meiste Python-Code Indizes nicht manuell; sieht ein LLM dann Code mit manuellem Index-Management, reagiert es verwirrt oder halluziniert Bugs. Und absurderweise bevorzugt es sogar eher „silent failure“, weil Tutorial-Code und „Industry-Standard“-Code im Training stärker verstärkt werden. Im Kern arbeiten diese Modelle nicht mit einer Reward Function und haben intern kein Reward Model; es ist letztlich nur Wortvorhersage und eine Architektur ohne Intelligenz.
  • Dass im Funktionsergebnis „extrem vorsichtig ausgeführt“ steht, lässt vermuten, dass der Prompt etwa so lautete: „Erzeuge eine Python-Divisionsfunktion, die alle denkbaren Edge Cases behandelt, und schreibe sie extrem vorsichtig.“ Das wirkt auf mich weniger wie ein Trainingsproblem von LLMs als wie ein Fall von allzu exakter Ausführung einer Anweisung.
    • Selbst wenn man beiseitelässt, dass es offensichtlich überzogene Satire ist,
      1. ist der Code tatsächlich falsch — und zwar unabhängig von der merkwürdigen Exception-Behandlung,
      2. ergeben Teile der Exception-Behandlung überhaupt keinen Sinn und sind verwirrend,
      3. und weniger überzogene Versionen davon passieren in der Praxis durchaus schon, wenn im Prompt nur Exception-Behandlung betont wird.
    • Ich habe den Funktionscode als satirisch überspitzte Darstellung dessen verstanden, was die Person tatsächlich erlebt hat. Im betreffenden Prompt wurde also wohl absichtlich übervorsichtig geschrieben, aber grundsätzlich stimme ich zu, dass LLMs standardmäßig oft einen vorsichtigeren Coding-Stil wählen, als ich es gerne hätte.
  • Aus irgendeinem Grund musste ich an FizzBuzzEnterpriseEdition denken
    https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition
    • Wow, in dem Projekt wurde junit 4.8.3 verwendet? Das halte ich für ein wirklich halsbrecherisches Beispiel von Coding. Ich frage mich, ob das vorher vom Justiziar und vom CTO abgesegnet wurde; so eine Entscheidung ist wirklich karrieregefährdend.
    • Ich war schockiert, wie viele Ordner und Dateien es dort gibt. Großartige Satire.
  • LLMs neigen dazu, mehr Defensivcode zu erzeugen als nötig. Sie prüfen denselben Wert mehrfach auf null/None/undefined, wodurch der Code schwer lesbar wird und am Ende selbst für das LLM schwer zu interpretieren ist. Das RL-Ziel scheint Exceptions stark zu bestrafen, gibt aber für Kürze oder Lesbarkeit von Code kaum Punkte.
    • Ich habe eine 40-zeilige Funktion, die Zeichen und Zahlen für Major System vergleicht, und es nervt mich extrem, dass Copilot unbedingt zusätzliche „Guardrails“ einbauen will, weil es sich ausmalt, dass in Zukunft noch mehr Zahlen oder Zeichen hinzukommen könnten.
  • Ich stimme zu, dass LLMs dazu neigen, sich zu sehr am Abfangen von Fehlern festzubeißen.
    Andererseits denke ich aber auch, dass gewöhnliche menschliche Programmierer in der Praxis tatsächlich mehr try/catch-Blöcke schreiben sollten. Es gibt viele Situationen, in denen eine Exception in einem Teilbereich — selbst wenn sie selten ist — nicht die gesamte Ausführung stoppen sollte. Natürlich gibt es auch Fälle, in denen ein Stop richtig ist; das hängt vom Einzelfall ab.
  • So programmieren Expert-Anfänger. Ich nenne das „What if driven development“. Viel Code wird von solchen Expert-Anfängern in diesem Stil geschrieben, und nach vielen Kennzahlen sind sie enorm produktiv. Selbst SOTA-Agenten für Go schreiben bei Concurrency-Bugs wahnsinnig defensiv, vermutlich als Folge dieser Entwicklerkultur und der Flut an Beiträgen, die vor Concurrency-Bugs warnen.
  • Auch logisch ist vieles daran seltsam: Division by zero ist nur bei b=0 möglich, aber genau das wurde zuvor bereits mit abs(b) < sys.float_info.epsilon geprüft. Außerdem wird im Pre-Check ein NaN-Rückgabewert zugelassen, während ein NaN, das bei der tatsächlichen Berechnung entsteht, in None umgewandelt wird. Aus Sicht des API-Designs ist dieses Verhalten völlig unbegründet.
  • Der Code hat mehrere Probleme, aber mich persönlich stört am meisten die Tendenz, import-Anweisungen innerhalb von Funktionen zu platzieren. Vermutlich ist das ein künstlicher Nebeneffekt davon, nur minimale Änderungen einarbeiten zu wollen, aber ich würde ein besseres Ergebnis erwarten.
    • Ich denke, das hängt mit dem RoPE-Attention-Mechanismus zusammen, bei dem physische Nähe im Code als Signal für Wichtigkeit verwendet wird.
    • Das Ziel ist, import lazy zu machen, um in Startup-Bedingungen Probleme mit langsamen Imports zu lösen.
    • In wirklich sehr großen Projekten ist lazy initialization unverzichtbar, weil sie enorme Auswirkungen auf die Startup-Zeit hat.
  • Das Schließen der Pop-ups hat länger gedauert als das Lesen dieses Posts; ich hasse Twitter-Links wirklich.