JevCoreML
Core ML · Swift · macOS

Entscheidungen in Millisekunden, direkt auf dem Mac.

Zwei Entscheidungsmodelle, JevCoreML und laya, als fertige Core-ML-Pakete. Ein Text geht hinein, eine kalibrierte Entscheidung kommt heraus: Auswahl, Stufe oder Ja/Nein, mit Wahrscheinlichkeiten. Gerechnet auf der eigenen GPU, ohne Python, ohne Server, ohne Netz.

9,0 mseine Frage an laya, englisch
6–12×schneller als laya in PyTorch
1000/1000gleiche Antworten auf AG News
0 Byteverlassen den Rechner
Die Demo-App: ein deutsches Support-Ticket, fünf Fragen der Triage, beantwortet vom mehrsprachigen laya-Checkpoint in 27 Millisekunden
Die Demo-App im Repo: ein Support-Ticket, fünf Fragen, 27 ms. Der Router hat Deutsch erkannt und den mehrsprachigen Checkpoint genommen.

Drei Fragetypen, ein Aufruf

Jede Antwort ist eine Verteilung, keine Textgenerierung. Die Konfidenz ist kalibriert, also taugt sie als Schwelle: sicher genug, um zu handeln, oder an einen Menschen weitergeben. Die Balken unten sind echte Antworten von laya auf das Ticket aus dem Bild, in einem Aufruf, 27 ms.

Auswahl

An welches Team geht das Ticket?

Bis 256 Optionen bei JevCoreML, bei laya so viele, wie in die Sequenz passen.

billing
100 %
sales
0 %
tech
0 %
Stufe

Wie verärgert klingt der Kunde?

Geordnete Stufen, die Antwort ist der Erwartungswert, hier 1,74 von 0 bis 3.

verärgert
42 %
besorgt
35 %
wütend
18 %
Ja/Nein

Will der Kunde Geld zurück?

Eine Wahrscheinlichkeit für ja, bei laya dazu, ob eine Handlung angebracht ist.

ja
68 %
nein
32 %
JevCoreML, die Empfehlung

Mehrere Fragen, ein Durchlauf, ein Paket

Ein Decoder mit Pointer-Kopf (Gewichte: kev-0.6b auf Qwen3-0.6B-Base), der bis zu acht Fragen zum selben Text in einem Durchlauf beantwortet, mit bis zu 256 Optionen je Frage und Zuständen bis 3072 Token. Ein Paket für alle Fälle, die Laufzeit wählt die Länge selbst. Der HTTP-Server spricht das Format der TypeSafe-API; bestehende Clients zeigen einfach auf localhost.

laya

Über 100 Sprachen, mit Router

Ein Encoder in drei Checkpoints: englisch, mehrsprachig und einer für vier feste Abläufe. Der Router liest Schrift und Sprache des Textes und wählt den passenden, genau wie das Original. Eine Frage je Durchlauf, dafür klein (0,6 bis 0,8 GB je Checkpoint) und mit fertigen Fragensätzen für Support, E-Mail, Guardrails, Moderation und Modellwahl.

Welches nehmen?

JevCoreML zuerst. Es ist ein Paket statt drei, beantwortet mehrere Fragen in einem Durchlauf, nimmt lange Zustände und viele Optionen, und sein Server versteht bestehende Jev-Clients. laya lohnt sich, wenn die Texte in vielen Sprachen kommen (der mehrsprachige Checkpoint ist über 100 Sprachen gemessen, JevCoreML ist auf englischen Daten trainiert und auf Deutsch nicht vermessen), wenn eine App klein bleiben muss (JevCoreML belegt geladen bis zu 18 GB im Temp-Verzeichnis, laya unter einem), oder wenn es um eine einzelne Klassifikationsfrage mit hoher Trefferquote geht (AG News 92,9 %). Beide liefern dieselbe Antwortform, ein Wechsel kostet eine Zeile.

Gleich wie das Original, nur schneller

Gemessen auf einem M5 Max, dieselben Anfragen auf beiden Seiten, Median. laya im Original läuft als PyTorch auf der CPU, so wie es sich selbst misst.

FallOriginalJevCoreMLFaktor
laya, 1 Frage, englisch112,9 ms9,0 ms12,5×
laya, 4 Fragen, englisch314,8 ms33,6 ms9,4×
laya, 10 Fragen, englisch709,2 ms83,4 ms8,5×
laya, 1 Frage, deutsch37,4 ms6,0 ms6,2×
JevCoreML, ganze Suite über HTTP, 1468 Fragen59 ms19 ms3,1×

Gegen den Cloud-Dienst Jev 1.13, der auf kev beruht: dieselbe Trefferquote auf Banking77 mit 77 Kategorien, 78,8 %, in 70 statt 320 ms und ohne Kosten je Aufruf.

Prüfung gegen das OriginalErgebnis
laya, 15 Referenzanfragen je Checkpoint15/15 auf allen drei
laya, AG News, 1000 Zeilen1000/1000, Trefferquote 92,9 % auf beiden Seiten
laya, DAIR Emotion, 1000 Zeilen999/1000, die eine ein Gleichstand bei 0,4978 gegen 0,4977
laya über HTTP gegen Router.predict26/26 Entscheidungen, Antwort Feld für Feld gleich
JevCoreML gegen kev in PyTorch, ganze Entwicklungssuite, 1468 Fragen2 abweichende Antworten, 80,79 % gegen 80,93 %

Einbinden

Ein Swift-Paket, eine Kommandozeile, ein HTTP-Server. Alles aus demselben Repo.

// Package.swift
.package(url: "https://github.com/GodModeAI2025/JevCoreML", from: "1.0.0")

import JevDecisionKit

let laya = try LayaRouted.bundled()   // Modelle als Ressourcen im App-Target
let result = try await laya.answer(
    state: .object([("message", .string(ticketText))]),
    questions: [
        ("team", .choice(instructions: "An welches Team geht das Ticket?", criteria: [
            (name: "billing", description: "Rechnungen, Zahlungen"),
            (name: "tech", description: "Fehler, Ausfälle"),
        ])),
        ("dringend", .noul(instructions: "Ist das dringend?")),
    ])

for (id, answer) in result.answers {
    print(id, answer.answer, answer.confidence)
}

In vier Schritten zur ersten Entscheidung

  1. Repo klonen. Voraussetzung ist ein Mac mit Apple Silicon, macOS 15 und Xcode 16. Das Swift-Paket baut auch für iOS 18 und läuft im iPhone-Simulator, dort ohne GPU: JevCoreML trifft dieselben Entscheidungen wie PyTorch, die Wahrscheinlichkeiten liegen bis 0,01 daneben, beim gepackten Mehrfragenlauf bis 0,034; laya weicht bis 0,04 ab. Auf einem echten iPhone ist nichts gemessen.
  2. scripts/fetch-models.sh lädt die Core-ML-Pakete aus dem Release und prüft die Prüfsummen.
  3. Demo/JevDemo.xcodeproj öffnen und starten, oder swift build für die Kommandozeile.
  4. In der eigenen App das Paket einbinden und die Modelle als Ressourcen ins Target legen.

Die Modelle

Jedes Paket nimmt mehrere Eingabelängen an, und eine Anfrage läuft in der kürzesten, in die sie passt. So rechnet auch laya im Original. Die Pakete liegen als ZIP im Release models-v2, jede Zeile unten hat ihren Download; scripts/fetch-models.sh holt und prüft sie in einem Schritt.

PaketWofürLängenFragenOptionenGrößeDownload
JevCoreMLein Paket für alle Anwendungsfälle, Gewichte kev-0.6b128–307282561,1 GiBZIP, 1,05 GB
Laya-EN-L512-K512-fp16englischer Text128–5121512805 MiBZIP, 778 MB
Laya-ML-L1024-K1024-fp16alle anderen Sprachen128–102411024615 MiBZIP, 594 MB
Laya-TD-L1024-K1024-fp16vier feste Abläufe, auf Wunsch128–102411024805 MiBZIP, 778 MB
tokenizers.zipdie drei Tokenizer, gehören zu jedem Paket dazu8 MBZIP, 8 MB

Prüfsummen: SHA256SUMS. Entpackt liegt jedes Paket als .mlpackage vor, das Xcode beim Bauen übersetzt.

JevCoreML: ein Paket für alles

JevCoreML ist ein Decoder mit Pointer-Kopf, die Gewichte sind kev-0.6b auf Qwen3-0.6B-Base, nach Core ML übertragen, fp16, 1,1 GB. Früher gab es davon drei Zuschnitte für drei Längen, und man musste wissen, welcher zur Anfrage passt. Jetzt trägt ein Paket alle sechs Längen als aufgezählte Eingabeformen, und die Laufzeit rechnet jede Anfrage in der kürzesten, in die sie passt. Eine kurze Frage kostet 7,5 ms, ein langer Zustand mit 3000 Token 270 ms, ohne dass jemand etwas einstellt.

Was drin ist

Sechs Eingabelängen, 128 bis 3072 Token. Bis zu acht Fragen zum selben Text in einem Durchlauf, jede mit bis zu 256 Optionen. Fragen und Optionen wirken nur im Pointer-Kopf, deshalb kosten sie nichts: über kevs Entwicklungssuite liegt der Median bei 19 ms, mit den drei getrennten Zuschnitten waren es 22,7 ms, bei denselben 1468 Antworten. Je Länge gegen PyTorch geprüft, keine einzige gekippte Entscheidung; bei 512 Token sind die Logits auf der GPU bitgleich mit dem alten festen Export.

Was man wissen sollte

Die GPU bereitet jede Länge einmal vor, der Warmlauf dauert deshalb rund 13 Sekunden nach 4 Sekunden Laden; warmUp() beim Start erledigt das im Hintergrund. Wer nur kurze Anfragen sieht, gibt sequenceLengths: [128, 256, 512] an. Die Laufzeit legt das Paket auf die GPU, auch wenn .all gewählt ist, weil der Planer von Core ML es sonst auf die CPU legte. Herkunft und Lizenz der Gewichte stehen in NOTICE und in den Metadaten des Pakets.

Nach dem Entpacken: JevCoreML.mlpackage und tokenizer.json nebeneinander ablegen, dann SystemOne(modelURL:tokenizerURL:). Oder im geklonten Repo scripts/fetch-models.sh kev, das lädt, prüft und entpackt.

Wie geprüft wurde

Jede Stufe einzeln gegen das Original, weil ein Fehler auf jeder Stufe lautlos bleibt: plausible Antworten, nur manchmal andere.

  • Tokenizer. 31 238 Fälle bei laya, 15 032 bei JevCoreML, byte-identisch, dazu jeder Unicode-Codepunkt einzeln.
  • Encoder. Die Sequenz Token für Token gegen die des Originals, samt Kürzungsregeln.
  • Modell. Logits gegen PyTorch auf Referenzanfragen und zwei öffentlichen Datensätzen.
  • Router. 116 Entscheidungen über Schrift, Sprache und Vorrang, alle gleich.
  • HTTP. Antworten Feld für Feld neben die von Router.predict gelegt.
  • Befunde. Neural Engine, NaN in fp16, Unicode-Versionen, Positionswinkel in fp16: alles gefunden, gemessen, behoben.

Die ausführlichen Berichte: laya-Port · Benchmark-Bericht · Rohdaten