Auf dieser Seite
Architektureigenschaft
COADF P-1 legt das Minimum fest: Eine probabilistische Komponente liefert einen Wert zusammen mit einer Konfidenz und der Methode, mit der der Wert gewonnen wurde, nie einen nackten Wert, und sie erreicht nie unmittelbar eine Ausgabe. Dieses Muster handelt von der zweiten Hälfte, und genau diese Hälfte geht in Implementierungen verloren. Die Antwort eines Modells darf in das System gelangen. Was sie nicht darf, ist, auf irgendeinem Weg zu dem zu werden, was das System als feststehend behandelt.
Drei Dinge müssen gleichzeitig gelten:
- Die Ausgabe hat einen eigenen Typ. Ein Vorschlag und ein maßgeblicher Datensatz sind verschiedene Typen, verschiedene Tabellen oder verschiedene Nachrichten. Code, der das eine hält, kann es nicht dort übergeben, wo das andere erwartet wird, ohne einen expliziten Schritt, den jemand prüfen kann.
- Die Grenze validiert zur Laufzeit. Der Vertrag wird geprüft, wenn die Antwort eintrifft, in dem Prozess, der sie empfängt, gleichgültig, was der Absender nach eigener Aussage geprüft hat.
- Die Herkunft reist mit dem Wert. Die Methode, das Modell und seine Revision, die Prompt-Revision und die Fundstelle in der Quelle bleiben über jeden Schritt hinweg angehängt, die Serialisierung eingeschlossen. Ohne sie kann P-4 nichts rekonstruieren und P-5 nichts offenlegen.
P-1 lässt die Komponente außerdem eine Konfidenz melden. Wie Konfidenz ausgedrückt, vergeben und verwendet wird, gehört zu P-2, das COADF nur als Prinzip veröffentlicht. Dieser Companion beschreibt es nicht, und nichts im Folgenden hängt davon ab.
Warum sie wichtig ist
Die Ausgabe eines Modells entsteht in einem Prozess, der sich nicht so aus seinen Eingaben reproduzieren lässt wie die Ausgabe eines Parsers: Sampling, Modellaktualisierungen und Prompt-Änderungen verschieben sie. Für einen Vorschlag ist das hinnehmbar, für eine Tatsache nicht. Das Risiko ist nicht, dass ein Modell manchmal falschliegt; alles liegt manchmal falsch. Das Risiko ist, die Fähigkeit zu verlieren, zu sagen, welche Werte woher stammen, denn jede spätere Kontrolle hängt davon ab. Ein Tor stoppt nur, was es sehen kann, eine Offenlegung benennt nur, was gekennzeichnet ist, und eine prüfende Person prüft nur, was noch auf seine Quelle verweist.
Der Verlust ist selten eine Entscheidung. Er geschieht in einer gewöhnlichen Codezeile: eine ORM-Entität, die aus dem JSON des Modells befüllt wird, weil die Feldnamen zufällig passten, ein Antwortmodell, das die Herkunft weglässt, weil niemand sie ergänzt hat, ein Batch-Import, der das Formular umgeht, in dem die Validierung lag. Das Muster existiert, damit sich diese Zeile nicht schreiben lässt, ohne dass es auffällt.
Zulässige Umsetzungsstrategien
Isolation ist architektonisch, nicht zwingend physisch
Microservices sind nicht erforderlich. Die Eigenschaft gilt, wenn kein Codepfad der probabilistischen Seite erlaubt, ein maßgebliches Objekt zu erzeugen, und ein einzelner Prozess kann sie ebenso gut einhalten wie ein Netzwerk. Die Topologie wird aus eigenen Gründen gewählt (eine Inferenzlast getrennt skalieren, die Client-Bibliothek eines Anbieters isolieren, unabhängig deployen), und dann wird die Grenze in der gewählten Form gebaut. Die vier Abbildungen unten halten dieselbe Eigenschaft in vier Formen ein.
Beispielarchitektur · Nicht normativ
Modularer Monolith
- Datenfluss in diesem Beispiel
- Optional: kann nicht verfügbar sein
Textbeschreibung. Innerhalb eines Prozesses gibt ein als probabilistisch gekennzeichneter Modell-Client seine Rohantwort an ein Grenzmodul weiter, das ein Proposal an den Domänenkern weitergibt. Ein Klassifikationsadapter, ebenfalls innerhalb des Prozesses, kann eine Anreicherung an den Domänenkern weitergeben und fragt einen externen Klassifikationsdienst außerhalb des Prozesses ab. Der Domänenkern schreibt Einträge in die Prüfspur, eine separate Datenbank. Der einzige Weg vom Modell-Client zum Domänenkern führt über die Grenze.
Beispielarchitektur · Nicht normativ
Serviceorientiert
- Datenfluss in diesem Beispiel
- Optional: kann nicht verfügbar sein
Textbeschreibung. Ein Inferenzdienst enthält einen als probabilistisch gekennzeichneten Modell-Client und eine Grenze, die validiert, was sie sendet. Er sendet über HTTP, unter einem JSON-Vertrag, an einen Domänendienst, dessen eigene Grenze validiert, was sie empfängt, und ein Proposal an den Domänenkern weitergibt. Der Domänendienst enthält außerdem einen Klassifikationsadapter, der einen externen Dienst abfragt und eine Anreicherung an den Domänenkern weitergeben kann, sowie die Prüfspur, in die der Domänenkern Einträge schreibt. Der Inferenzdienst hat keine Verbindung zur Prüfspur.
Beispielarchitektur · Nicht normativ
Ereignisgesteuert
- Datenfluss in diesem Beispiel
Textbeschreibung. Ein Inferenz-Worker enthält einen als probabilistisch gekennzeichneten Modell-Client und eine Grenze. Er publiziert eine Nachricht in ein Topic für Vorschläge. Der Nachrichtenrumpf trägt die trace_id der Prüfspur; die Header der Nachricht tragen den Ausführungskontext als W3C-traceparent. Ein Domänen-Consumer liest das Topic, validiert jede Nachricht beim Empfang und gibt ein Proposal an den Domänenkern weiter, der Einträge in die Prüfspur schreibt.
Beispielarchitektur · Nicht normativ
Cloud-natives Deployment
- Datenfluss in diesem Beispiel
Textbeschreibung. Im Namespace inference führt ein Inferenz-Pod den Modell-Client und seine Grenze aus. Er darf an den Modell-Endpunkt im Namespace model-serving senden und an die Vorschlagsannahme im Namespace records, dort nur an deren API-Port. Die Vorschlagsannahme validiert, was sie empfängt, und gibt ein Proposal an den Domänenkern weiter, der in die Prüfspur und die Datenbank der Datensätze schreibt. Eine Notiz hält fest, dass der Namespace inference weder eine Route noch Zugangsdaten zu dieser Datenbank hat.
Dieselben vier Elemente in jeder Topologie
- Unterschiedliche Typen. Die probabilistische Seite kann einen Vorschlag konstruieren und sonst nichts. Der maßgebliche Datensatz wird nur von Domänencode gebaut, aus einem Vorschlag und etwas, das die probabilistische Seite nicht erzeugen kann.
- Laufzeitvalidierung auf jeder empfangenden Seite. Ein striktes Schema: nicht deklarierte Felder werden abgelehnt, keine Typumwandlung, geschlossene Vokabulare für kategoriale Werte, begrenzte Längen. In einer verteilten Topologie validiert jeder Empfänger, auch die Domänenseite, wenn der Absender der eigene Dienst ist: „Wir haben vor dem Senden validiert“ ist eine Aussage über ein anderes Deployable, womöglich über eine ältere Version davon.
- Herkunft im Vertrag. Deklariert, verpflichtend und von jedem Mapper und Serialisierer auf dem Weg nach außen erhalten.
- Ein expliziter Übernahmeschritt. Der einzige Weg vom Vorschlag zum maßgeblichen Datensatz ist eine Funktion, ein Endpunkt oder ein Befehl, der verlangt, was die probabilistische Seite nicht liefern kann. Für Werte, die ein Sprachmodell abgeleitet hat, verlangt der öffentliche Fence F-03 von COADF eine menschliche Prüfung, bevor sie eine veröffentlichte Ausgabe erreichen. Die Übernahme selbst wird in der Prüfspur festgehalten.
Deterministische Validierung um stochastische Ausgaben
Prüfungen, die nur den Wert lesen (seine Form, sein Vokabular, seine Einheit, die Bereiche, die die Domäne selbst festlegt), laufen, bevor ein Mensch ihn ansieht. Sie machen einen Wert nicht wahr. Sie machen einen unmöglichen Wert unmöglich, und zwar jedes Mal auf dieselbe Weise, worauf sich ein Mensch, der den Wert prüft, verlassen kann.
Durchsetzungsmöglichkeiten, von der schwächsten zur stärksten
| Mechanismus | Stoppt | Stoppt nicht |
|---|---|---|
| Typtrennung | Versehentliche Übernahme in Code, der die Typprüfung besteht | Casts, dynamische Typisierung, Reflection |
| Schemavalidierung zur Laufzeit | Fehlerhafte oder zu viel beanspruchende Antworten | Einen wohlgeformten Wert, der falsch ist |
| Architekturtest auf Importe | Dass das probabilistische Modul Code importiert, der Datensätze schreibt | Importe, die zur Laufzeit über den Namen erfolgen; Datenpfade, die keine Importe sind |
| Datenbankrechte pro Komponente | Dass eine Komponente in den maßgeblichen Speicher schreibt | Komponenten, die sich Zugangsdaten teilen |
| Getrenntes Deployment und Netzwerk-Policy | Dass eine getrennt deployte Komponente den Speicher überhaupt erreicht | Alles innerhalb eines Prozesses; Cluster, deren Netzwerk-Plugin die Policy nicht durchsetzt |
Die meisten Systeme brauchen die ersten drei immer und die letzten beiden, wenn die probabilistische Komponente eigenständig deployt wird. Das Profil für Python und FastAPI setzt die ersten drei um; das Cloud-native-Profil ergänzt die letzten beiden.
Fehlermuster
Modellausgabe direkt in den maßgeblichen Speicher geschrieben
Die Antwort wird in die Entität geparst, die der Rest des Systems als Tatsache liest, weil die Felder passten. Keine einzelne Zeile ist falsch. Die Grenze existiert schlicht nicht.
Vorschläge nicht von verifizierten Daten zu unterscheiden
Eine Tabelle, ein Typ und ein Flag, das sagt, was was ist. Das Flag steht standardmäßig auf dem bequemen Wert, oder das JSON des Modells selbst kann es setzen.
Herkunft geht auf dem Weg nach außen verloren
Ein Mapper, ein Antwortmodell oder ein Export lässt die Methode und die Quelle weg. Frameworks, die Ausgaben auf ein deklariertes Schema filtern, tun das lautlos: FastAPI filtert eine Antwort auf ihr Antwortmodell, und der Serialisierer von Fastify lässt Eigenschaften weg, die ein Antwortschema nicht aufführt, sofern das Schema keine zusätzlichen Eigenschaften zulässt.
Validierung nur in der Benutzeroberfläche
Das Formular validiert. Der Batch-Import, das Administrationsskript und der zweite Client tun es nicht.
Nachgelagerte Systeme können Abgeleitetes nicht von Verifiziertem unterscheiden
Das Exportformat hat kein Feld für die Methode, also erhält das nächste System einen Wert und sonst nichts, und jede seiner Kontrollen ist für den Unterschied blind.
Der rohen Antwort ohne Laufzeitvalidierung vertraut
Ein Cast in TypeScript, ein Dictionary in Python, ein nachsichtiger Mapper in Java: Der Vertrag existiert in den Typen des Codes und nirgends in seinem Verhalten. Die Typannotationen von TypeScript werden beim Kompilieren entfernt, und seine Standard-Typdefinitionen deklarieren das Ergebnis von
JSON.parsealsany.Typumwandlung verdeckt den Fehler des Modells
Nachsichtiges Parsen macht aus
"12"eine12und aus"true"einTrue. Die Zahl sieht richtig aus und war nie eine Zahl. Der Strict Mode von Pydantic verweigert diese Umwandlung; die Standardkonfiguration des Validators von Fastify aktiviert die Typumwandlung. Es gilt zu wissen, welches von beiden läuft.Stille Reparatur
Die Antwort besteht die Validierung nicht, also wird der Aufruf wiederholt, bis eine Antwort besteht, und nur die letzte bleibt erhalten. Die Fehlschläge waren Belege über das Modell, und sie sind verschwunden.
Validierung der Geschwindigkeit wegen umgangen
Eine Optimierung, die Objekte ohne Validierung konstruiert, wird zum bequemsten Weg und dann zur Umgehung.
model_constructvon Pydantic erzeugt ein Modell, ohne es zu validieren, genau wie dokumentiert.
Verifikation
Unit-Test
Bestanden, wenn: Jede fehlerhafte Antwort wird abgelehnt: ein nicht deklariertes Feld, ein umwandelbarer Typ, eine fehlende Herkunft, ein Attribut, nach dem niemand gefragt hat.
Zahnbeweis: In einer Arbeitskopie eine Einschränkung löschen (etwa die Regel, die nicht deklarierte Felder ablehnt): Der zugehörige Test muss fehlschlagen.
Architekturtest
Bestanden, wenn: Das probabilistische Modul hat keinen Importpfad zu dem Code, der maßgebliche Datensätze schreibt.
Zahnbeweis: In einer Arbeitskopie den verbotenen Import hinzufügen: Der Vertrag schlägt fehl, und der Build stoppt.
Vertragstest
Bestanden, wenn: Produzent und Konsument stimmen im Vorschlagsschema überein, mit den Herkunftsfeldern als Pflichtfeldern.
Zahnbeweis: Ein Herkunftsfeld aus dem Schema des Produzenten entfernen: Der Vertragstest des Konsumenten schlägt fehl.
Integrationstest
Bestanden, wenn: Wird die probabilistische Komponente eigenständig deployt, können ihre Zugangsdaten nicht in den maßgeblichen Speicher schreiben.
Zahnbeweis: Den Schreibzugriff mit diesen Zugangsdaten versuchen: Die Datenbank verweigert ihn.
End-to-End-Test
Bestanden, wenn: Eine Ausgabe, deren Attribut aus einem Vorschlag stammt, den niemand verifiziert hat, kann nicht veröffentlicht werden.
Zahnbeweis: Einen unverifizierten Vorschlag einschleusen und die Veröffentlichung anfordern: abgelehnt, und die Ablehnung steht in der Prüfspur.
Alternative Umsetzungen
- Oberflächen, die nur Vorschläge zeigen. Die Modellausgabe wird einem Menschen als Vorschlag angezeigt und nie als Wert gespeichert. Einfach und stark; die Nachvollziehbarkeit dessen, was vorgeschlagen wurde, geht verloren, es sei denn, auch die Vorschläge werden festgehalten.
- Ein gemeinsamer, sprachneutraler Vertrag (JSON Schema, Protocol Buffers) statt sprachnativer Modelle. Besser über Sprachgrenzen hinweg; die Frage der Strenge wandert ins Schema, wo über zusätzliche Eigenschaften und Formate ausdrücklich entschieden werden muss.
- Modi für strukturierte Ausgaben in Modell-APIs. Sie verringern fehlerhafte Antworten beim Produzenten. Sie entbinden den Konsumenten nicht von der Validierung, denn der Konsument kann nicht verifizieren, wie der Produzent konfiguriert war.
- Getrennte Speicherung für Vorschläge und Datensätze, zwei Tabellen oder zwei Speicher statt einer Tabelle mit Status. Aufwendiger, und die Trennung wird in jeder Abfrage sichtbar, die irgendjemand schreibt.
Grenzen
- Die Grenze steuert, wohin Modellausgaben gelangen können. Sie macht Modellausgaben nicht korrekt, und ein wohlgeformter falscher Wert besteht jede Prüfung in diesem Muster.
- Typtrennung stoppt Versehen, keine Absicht. Wer Schreibzugriff auf die Domäne hat, kann ein maßgebliches Objekt von Hand konstruieren; sichtbar wird das durch Code-Review und die Prüfspur.
- Dieses Muster sagt nicht, wann ein Vorschlag einen Menschen braucht oder wie Konfidenz ausgedrückt wird. Das gehört zu P-2 und P-3, die COADF nur als Prinzipien veröffentlicht.
- Validierung ist nur so gut wie der Vertrag. Ein freizügiges Schema, streng validiert, bleibt freizügig.
Quellen
- FastAPI: Response model: return type and data filtering · offizielle Dokumentation · FastAPI 0.141 · Geprüft am 2026-09-11
- Fastify: fast-json-stringify: additionalProperties · Projekt-Repository · Geprüft am 2026-09-11
- TypeScript: The Basics: erased types · offizielle Dokumentation · Geprüft am 2026-09-11
- TypeScript: lib.es5.d.ts: JSON.parse · Projekt-Repository · Geprüft am 2026-09-11
- Pydantic: Strict mode · offizielle Dokumentation · Pydantic 2.13 · Geprüft am 2026-09-11
- Fastify: Validation and serialization · offizielle Dokumentation · Fastify 5.12 · Geprüft am 2026-09-11
- Pydantic: Models: creating models without validation · offizielle Dokumentation · Pydantic 2.13 · Geprüft am 2026-09-11
