Engineering · transparent

Methodik

Wie OpenCaseLaw Schweizer Gerichtsentscheide findet, gewichtet und verifiziert — durchgängig, mit jeder Gewichtung und jedem Schwellenwert offengelegt. Diese Seite ist die massgebliche Referenz; was Sie anderswo lesen, sollte mit dem hier Festgehaltenen übereinstimmen — andernfalls gilt der Code.

1. Korpus & Aktualisierung

Das Korpus umfasst 1’050’000+ publizierte Schweizer Entscheide aus 118 Gerichten, in drei Sprachen (DE 499’642; FR 459’825; IT 90’776), mit einem Zeitraum von 1875 – 2026. Acht Bundesgerichte (BGer 192’049; BVGer 108’135; BGE 50’459; dazu BStGer, BPatGer, MKG und weitere), 26 kantonale Gerichtsbarkeiten sowie EMRK-Schweiz (~2’800 Entscheide aus BGE-Übersetzungen, HUDOC, Kammer/Grosse Kammer/Ausschuss).

Jeder Entscheid wird von seiner Primärquelle bezogen — wo verfügbar vom eigenen Publikationsportal des Gerichts (alle 26 Kantone direkt abgerufen über LexWork / SIL / ZH OpenData / TI RL, mit LexFind-PDF-Rückfalloption, die in 4 Kantonen fehlende Erlasse ergänzt), für Bundesaktualisierungen vom offiziellen Such-Back-End des BGer. 40 von 51 entscheidsuche.ch-Shards werden durch unsere eigenen direkten Scraper gespiegelt; entscheidsuche-Daten setzen sich bei der Deduplikation nur dort durch, wo wir kein eigenes Live-Äquivalent haben. Die verbleibenden sieben entscheidsuche-exklusiven Shards (≈142’000 Datensätze: vd_findinfo, vd_omni, ch_vb, sg_gerichte, be_bvd, be_weitere, be_steuerrekurs) sind eingefrorene historische Archive — ihre vorgelagerten Portale wurden stillgelegt, ersetzt oder vorübergehend getrennt. Wir lesen entscheidsuche wöchentlich als Vollständigkeits-Absicherung neu ein; die letzten sechs Wochenläufe ergaben null neue Entscheide. Siehe Abdeckung → ergänzende Archive für die vollständige Aufschlüsselung. Die Pipeline aktualisiert sich nach drei Zeitplänen:

  • Alle 15 Minuten werktags von 05:00–16:00 UTC — der BGer-Poller publiziert neue Bundesentscheide inkrementell in die Live-Datenbank, innerhalb weniger Minuten nach ihrer gerichtsseitigen Freigabe.
  • Täglich 01:00 UTC — jeder aktive kantonale Scraper läuft; eine Soft-Fail-Politik knüpft an die 5 kritischen Bundes-Scraper und einen Fehlerquoten-Schwellenwert von 15 % über die übrigen an.
  • Täglich 03:30 UTC — vollständiger FTS5-Neuaufbau, Neuaufbau des Zitationsgraphen, Qualitäts-Gate, Statistik-Aktualisierung, atomarer Austausch ohne Ausfallzeit. Die Worker bedienen weiterhin die bisherige Datenbank, bis die neue integritätsgeprüft ist.

Das vollständige Korpus wird zudem als Parquet auf Hugging Face publiziert (voilaj/swiss-caselaw) unter CC0; das tägliche Delta wird automatisch angehängt.

2. Volltextindex

SQLite FTS5 mit dem Tokenizer unicode61 remove_diacritics 2. Die Entscheidtabelle speist den Index über diese Spalten, mit spaltenweisen BM25-Gewichten, die empirisch gegen ein Golden Set mit 100 Anfragen abgestimmt wurden:

SpalteBM25-GewichtBegründung
title6.0Höchstes Signal — knapp, bewusst.
regeste5.5Thematische Zusammenfassung des Gerichts selbst.
docket_number2.0Für die exakte Wiederauffindung über die Aktennummer.
full_text1.2Lang, verrauscht — Anker, nicht Treiber.
court / canton / language / decision_id0.8Metadaten, kein Inhalt.

Der Index wird atomar neu aufgebaut: build_fts5.py schreibt nach decisions.db.tmp und ersetzt die Datei dann per os.replace(). Worker, die den SQLite-URI ?immutable=1 verwenden, behalten ihre offenen Datei-Handles auf dem alten Inode, bis sie sich erneut verbinden — der Austausch bleibt für aktive Leser unsichtbar.

build_fts5.py · BM25-Gewichte konfiguriert in mcp_server.py um die Zeilen 431–442 · diakritischer Tokenizer in decision_structure.db für die absatzweise Suche gespiegelt.

3. Anfrageverständnis

Eine natürlichsprachliche Anfrage erreicht FTS5 nie unbearbeitet. Zuerst durchläuft sie eine Bereinigung (_sanitize_fts5): Apostrophe, Bindestriche und Punkte ohne Wortzeichen werden zu Leerzeichen reduziert; reservierte Tokens (AND, OR, NOT, NEAR) bleiben nur erhalten, wenn sie auf beiden Seiten Operanden haben; das einzelne schweizerisch-juristische Token „OR“ (Abkürzung für Obligationenrecht) wird stets erzwungen in Anführungszeichen gesetzt, da es sonst als Boolescher Operator interpretiert würde.

Parallel dazu wird die Anfrage an Claude Haiku 4.5 geleitet, für eine strukturierte 2-Sekunden-Analyse: Gesetzesverweise, Lehrbegriffe in DE/FR/IT, Erwähnungen massgebender BGE, Synonyme und der Rechtsbereich werden als deterministisches JSON extrahiert. Die Ausgabe wird nach der kleingeschriebenen Anfrage für die Dauer der Sitzung zwischengespeichert.

Drei Normalisierungen machen das schweizerische Rechtsvokabular über seine stilistischen, orthografischen und sprachübergreifenden Varianten hinweg durchsuchbar:

  • Diakritik-unempfindliche Tokenisierung. Der FTS5-Tokenizer unicode61 remove_diacritics 2 entfernt Diakritika auf der Index- wie auf der Anfrageseite — so treffen „Prüfung“, „PRÜFUNG“ und eine Anfrage nach „Prufung“ alle dieselbe Trefferliste.
  • Umlaut-Schreibweisen-Zusammenführung. Die diakritiklose Schreibweise ae/oe/ue (verbreitet in älteren Urteilen und in jeder Vor-Unicode-Umgebung) wird zu a/o/u reduziert, was der Tokenizer dann mit den diakritikbefreiten ä/ö/ü vereinheitlicht. So findet „Pruefung“ auch „Prüfung“.
  • LLM-Synonymerweiterung. Die strukturierte Analyse von Claude Haiku erzeugt 2–4 alternative Rechtsbegriffe in DE/FR/IT pro Anfrage, spontan — nicht aus einer statischen Tabelle. So wird „qualité pour recourir“ mit „Beschwerdebefugnis“ / „Beschwerdelegitimation“ / „legittimazione“ verknüpft, selbst wenn Ihre Anfrage nur einen davon enthielt.

4. Abruf & Fusion

Die Anfrage fächert sich in 10–12 Strategien auf, die als unabhängige FTS5-/Graph-Abfragen laufen. Jede Strategie trägt ein Strategiegewicht; der Rang-1-Treffer einer Strategie und der Rang-1-Treffer einer anderen werden mittels Reciprocal Rank Fusion fusioniert (RRF-Rangkonstante = 60).

StrategieGewichtWirkung
nl_and1.8Natürlichsprachliches AND über die Begriffe.
raw1.5Anfrage wortwörtlich.
regeste_focus1.4Beschränkt auf die Regeste-Spalte.
nl_or1.2OR-Rückfalloption (kostenbewusster früher Abbruch).
structured_doctrine1.1–3.5Lehrbegriffe aus der Haiku-Analyse.
quoted_explicit1.1Phrasentreffer, wenn Anführungszeichen erkannt werden.
nl_or_expanded1.0OR + Synonym-/Umlaut-/Kompositum-Erweiterung.
title_focus0.95Auf die Titelspalte beschränkter Treffer.
doctrine_regeste / doctrine_title2.5 / 1.6Strategien zur Begriffsübersetzung.

Über FTS5 hinaus erhält derselbe RRF-Pool auch:

  • Kandidaten aus dem Gesetzesgraphen — Entscheide, die mit den aus der Anfrage geparsten Gesetzesartikeln verknüpft sind, eingespeist als parallele Rangliste.
  • Direkte BGE-Nachschlagungen — wenn die Anfrage (oder ihre Analyse) einen bestimmten BGE-Verweis nennt, wird dieser Entscheid fest an die Spitze gesetzt.
  • Aktennummer-Treffer — Zeichenketten wie 6B_1234/2025 werden an eine exakte Aktennummer-Nachschlagung geleitet, was den Grossteil der Pipeline überspringt.

Der fusionierte Kandidatenpool wird dynamisch dimensioniert (standardmässig ~300–400 für eine Top-50-Anfrage) und vor Beginn der Neugewichtung auf 2’500 Zeilen begrenzt.

5. Neugewichtung

Jeder Kandidat erhält einen Vektor von Signalen; der Endwert ist eine lineare Kombination, abgestimmt gegen das Golden Set. Signalgewichte (_rerank_rows):

SignalGewichtObergrenzen / Anmerkungen
RRF-Wert32.0Aggregat aller Strategie-Ränge.
Aktennummer exakt / partiell6.0 / 2.0Treffer auf Zeichenketten-Ebene der Aktennummer.
Titelabdeckung3.0Anteil der Anliegen-Tokens im Titel.
Regeste-Abdeckung3.0Dasselbe, gegen die Regeste.
Gesetzeserwähnungen3.5 · 0.5 · 2.0Verknüpfungen von Entscheid zu Artikel.
Zitationstreffer2.4 · 0.30 · 1.2Ergebnisübergreifende Zitationsnachweise.
Autorität (eingehende Zitationen)0.03 · 1.0Warum ein Leitentscheid aufsteigt.
Sprachübereinstimmung+2.0Wenn die Sprache des Ergebnisses der Anfrage entspricht.
Erweiterte Abdeckung1.5 / 0.8Gutschrift für Synonym- + Kompositum-Treffer.
Gerichtsbereichs-Heuristiken±0.2 – +1.7BVGer-Asyl- + BGer-Höchstgerichts-Gewichtung bei passender Absicht.

Nach dem linearen Scorer wird bei Bedarf ein LLM-Neugewichtungsdurchlauf ausgelöst:

  • Modell: Claude Haiku 4.5; Top-N: 15; Timeout: 3 s; Gewicht: 3.0 mit linearem Abfall w × max(0, 1 − Rang/15).
  • Ein Konfidenz-Gate überspringt den Aufruf vollständig, wenn der lexikalische Top-1-Wert bereits ≥ 2× dem Top-2-Wert entspricht (die Antwort ist eindeutig; die Neugewichtung ist reiner Kostenaufwand).
  • Der Durchlauf wird zudem bei Aktennummer-Anfragen übersprungen (ein exakter Treffer braucht kein LLM).
Gemessene Wirkung. Auf dem eingefrorenen Golden Set mit 100 Anfragen (74 DE, 16 FR, 7 IT) gegen 1’078’177 Entscheide liefert lexikalisch+RRF allein MRR@10 = 0.470, Hit@1 = 0.33, Recall@10 = 0.496. Mit aktivierter Haiku-Neugewichtung bewegt sich derselbe Online-Benchmark auf MRR@10 ≈ 0.647 und Hit@1 ≈ 0.57 — eine Steigerung um +37 % / +73 %, zum Preis eines zusätzlichen Haiku-Aufrufs bei Anfragen, die das Konfidenz-Gate nicht erfüllen.

6. Punktgenaue Fundstellen live · Mai 2026

Jedes der fünf besten Suchergebnisse und jedes der drei besten Leitentscheid-Ergebnisse trägt ein pinpoint-Feld, das die für die Anfrage relevanteste Erwägung (Absatz mit der rechtlichen Entscheidung) benennt. Der Resolver läuft über einen entscheidweisen FTS5-Absatzindex in decision_structure.db (≈8,8 Mio. Absätze über 807’000 Entscheide). Das zweistufige Design:

  1. Phrasen-Durchlauf. Das Anliegen wird als exakte FTS5-Phrase ausgeführt — hohe Präzision, wenn die Formulierung des Nutzers jener des Gerichts entspricht.
  2. Bag-of-Words-OR-Durchlauf. Liefert die Phrase nichts, werden dieselben Tokens als OR-Anfrage abgefeuert, für breiteren Abruf.

Ein Konfidenz-Scorer (_score_pinpoint_confidence) kombiniert drei unabhängige Signale, um das Ergebnis zu kennzeichnen:

  • BM25-Abstand. Rang-1-Wert über Rang-2; ein Verhältnis > 1,5 ergibt „hoch“, > 1,2 ergibt „mittel“.
  • Absolute Stärke. Bei Einzelzeilen-Treffern ohne Rang-2 zum Vergleich: absoluter |BM25| > 2,0 für „hoch“, > 1,0 für „mittel“. Eine frühere Version dieses Zweigs verwendete für Einzelzeilen-Treffer einen Sentinel-Wert von 999,0, der dünne Treffer stillschweigend auf „hoch“ hochstufte; das war der im Mai 2026 behobene Fehler der falschen Konfidenz.
  • Token-Abdeckung. Eindeutige Anliegen-Tokens (> 2 Zeichen, mit ~70 herausgefilterten generischen Stoppwörtern des schweizerischen Rechtsdiskurses), die im getroffenen Absatz erscheinen. Mehr-Token-Anliegen mit < 50 % Abdeckung werden gänzlich unterdrückt; < 70 % wird auf „mittel“ begrenzt.

Semantische Rettung Infrastruktur ausgerollt · Korpus ~33 % kodiert greift, wenn der lexikalische Durchlauf nichts liefert. Das Anliegen wird mit sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 kodiert (117 Mio. Parameter, 384-dimensionale normierte Vektoren, mehrsprachig DE/FR/IT/RM plus 47 weitere); die Kosinus-Ähnlichkeit wird über die < 300 Absatz-Einbettungen des Entscheids berechnet; ein Treffer erscheint mit „hoch“, wenn Kosinus ≥ 0,70, mit „mittel“ bei ≥ 0,55, sonst keiner. Ein Hybridmodus, der nach Abschluss der Kodierung aktiviert wird, lässt beide Signale laufen und behandelt Übereinstimmung auf derselben Erwägung als signalübergreifenden Nachweis — die Konfidenz wird auf „hoch“ angehoben, source: "hybrid_agreement".

Die Pinpoint-URL ist so aufgebaut, dass der Browser automatisch zum getroffenen Absatz scrollt und ihn hervorhebt: ?highlight=<wortwörtlicher Satz>&e=2.3#e-2-3. Der Abfrageparameter steuert eine serverseitige Hervorhebung; das Hash-Fragment löst das native Auto-Scrollen des Browsers aus.

7. Zitationsgraph

Der Text jedes Entscheids wird auf Zitationen anderer Entscheide geparst (BGE-Verweise, BGer-Aktennummern, BVGer-Verweise). Die Rohschicht enthält 8,65 Mio. Kanten; der Resolver hebt 8,09 Mio. davon (92,9 %) auf kanonische Entscheid-IDs an. Die verbleibenden 7 % sind reale Entscheide, die wir noch nicht halten (ältere BGE vor 1875, zurückgezogene Gerichtspublikationen, OCR-beschädigte Verweise).

Die Auflösung läuft als vier kaskadierte Durchläufe:

  1. Standard-Aktennummer-Join. Normalisierte Aktennummer der Zitation = normalisierte Aktennummer des Ziels. Bewältigt über 80 % der Kanten.
  2. BGE-Präfix bidirektional. Findet Treffer, unabhängig davon, ob die Zitation das Präfix BGE enthält oder nicht, wobei das Ziel in beiderlei Form gespeichert sein kann. Diese eine Korrektur im März 2026 verdreifachte die BGE-Auflösung nahezu.
  3. Blosse BGE-Aktennummern. Ziele, die Band Abteilung Seite entsprechen, werden als blosse BGE-Verweise behandelt und mit BGE versehen.
  4. Pin-Cite-Auflösung. Enthält eine Zitation eine Seitenzahl, die in unseren Zielen nicht vorhanden ist (z. B. BGE 125 V 352, wo die erste Seite 351 ist), suchen wir die grösste erste Seite ≤ 352 innerhalb derselben (Band, Abteilung) und innerhalb von 30 Seiten. Die Konfidenz wird um 0,10 herabgesetzt, um die Schlussfolgerung widerzuspiegeln.

Meistzitierte Autorität (live aus reference_graph.db am 2026-05-11 berechnet): BGE 125 V 351 mit 85’108 eingehenden Zitationen, gefolgt von BGE 134 V 231 und BGE 122 V 157, jeweils in der Grössenordnung von Zehntausenden. Diese Zählwerte fliessen als Autoritäts-Signal in die Such-Neugewichtung zurück (Gewicht 0,03 pro Zitation, begrenzt auf 1,0) — weshalb klassische Leitentscheide nach oben steigen, selbst wenn ihre sprachlichen Treffer nicht stärker sind als die anderer Kandidaten.

8. Qualitätssicherung

Jede nächtliche Veröffentlichung wird durch ein 4-schichtiges QS-Rahmenwerk abgesichert. L4 (das Veröffentlichungs-Gate, das die KRITISCHE Teilmenge von L1 ausführt) ist die harte Sperre: schlägt es fehl, wird der Austausch verweigert und die Nutzer behalten das Korpus von gestern, bis das Problem untersucht ist. Die anderen Schichten sind kontinuierliche Absicherungen — L2 läuft bei jedem Commit in CI, L3 alle 5 Minuten auf dem Live-Server.

  • L1 — Datensatzprüfungen (63 über 20 Module). Drift pro Gericht, Duplikaterkennung, Kurztext-/OCR-Erkennung, Auflösungsrate des Zitationsgraphen, Abdeckung der Gesetzesverknüpfungen, Datum-/Aktennummer-Plausibilität, Zählung fehlender Felder sowie LLM-Stichprobenprüfung an einer rotierenden Auswahl.
  • L2 — pytest-Suite (derzeit 516 bestanden). Unit-Tests decken jedes Parsing-, Dedup- und Ranking-Primitiv ab; neue Regressionen landen als neue Tests nach dem Muster „Vorfall → Regressionstest“.
  • L3 — Smoke-Test (alle 5 Minuten). Produktions-Gesundheitssonde: /health, eine Anker-Entscheidseite und die PDF-Export-Pipeline. Drei aufeinanderfolgende Fehlschläge eskalieren zu einem INVESTIGATE-Alarm.
  • L4 — Veröffentlichungs-Gate. Von den L1-Prüfungen müssen die als KRITISCH gekennzeichneten bestehen, bevor das neue Korpus committet und gepusht wird; schlägt eine fehl, verweigert die Veröffentlichung den Austausch und die Daten von gestern bleiben live. Das Dashboard unter /quality.html zeigt den letzten Status und den Verlauf jeder Prüfung.

Über die QS hinaus durchlaufen entscheidzitierende LLM-Workflows ein fünfgleisiges Abschluss-Audit (attest_response), das vier Halluzinationsklassen abfängt — erfundene Zitation, erfundenes Zitat, erfundener Gesetzestext, erfundenes Datum — sowie einen optionalen fünften Grounding-Richter, der prüft, ob die Aussage, die das LLM einem zitierten Absatz zugeordnet hat, durch den Text dieses Absatzes tatsächlich gestützt wird.

9. Getestet und verworfen

Technische Entscheidungen werden vertrauenswürdiger, wenn die Sackgassen sichtbar sind. Die folgenden Techniken wurden auf demselben Golden Set gemessen wie der Rest und haben ihren Platz nicht verdient:

  • Cross-Encoder-Neugewichtung (cross-encoder/mmarco-mMiniLMv2-L12-H384-v1 als gegenwärtiger Platzhalter) verworfen Mehrsprachige Cross-Encoder, die auf generischem Web-QA trainiert wurden, liessen sich auf dem Golden Set nicht sauber auf das schweizerische Rechtsvokabular übertragen — sie schadeten dem MRR, statt zu helfen. Der Helfer steckt noch im Code hinter _apply_cross_encoder_boosts für künftige Fine-Tuning-Experimente, wird aber in der Produktion nicht aufgerufen.
  • Vorgefertigte BGE-M3-Dichtevektoren verworfen Das Korpus kodiert, Vektor-RRF als vierte Strategie ergänzt. Keine Verbesserung gegenüber BM25 + RRF + Haiku bei keinerlei Vektorgewicht. Die vectors.db wurde im März 2026 entfernt. Die diese Woche ausgelieferten absatzweisen semantischen Einbettungen sind ein eigener, engerer Eingriff — sie bewerten nur innerhalb der Absätze eines einzelnen Entscheids, wo BM25 wohlbekannte Grenzen hat.
  • Grösseres Haiku-Top-N verworfen Das Neugewichten der Top-30, Top-50 statt der Top-15 brachte keinen MRR-Gewinn und einen linearen Kostenanstieg. Top-15 ist der empirische optimale Punkt für die konfidenzgesteuerte Neugewichtung.
  • Grösserer Kandidatenpool verworfen Die Vergrösserung des Pools über ~400 Kandidaten (bei Standard-Anfragen) bewegte den Recall nicht nennenswert; die Kombination aus FTS5 + RRF bringt die richtigen Kandidaten bereits innerhalb der ersten paar Hundert Treffer zum Vorschein. Die Grenze von 2’500 bleibt als Sicherheitsobergrenze bestehen.

10. Offener Zugang

Das Korpus ist CC0 (Widmung an die Gemeinfreiheit). Der Code steht unter MIT, gehostet auf github.com/jonashertner/opencaselaw — jede Gewichtung, jeder Schwellenwert und jede Heuristik dieser Seite ist im Quellcode überprüfbar. Keine Konten, keine Cookies; was der Server erfasst, einschliesslich Suchanfragen, und wie lange, ist in der Datenschutzerklärung dokumentiert: /datenschutz/.

Programmatischer Zugang:

  • REST-API. mcp.opencaselaw.ch/docs — OpenAPI 3.0.3 mit 47 Endpunkten (Suche, Abruf, Leitentscheide, Trends, Zitationsgraph, Erlasse, Kommentare, Botschaft, Exporte, punktgenaue Fundstellen, Attestierung).
  • MCP-Server. mcp.opencaselaw.ch/sse — Server-Sent-Events-Transport, der 38 Tools bereitstellt. Angebunden von Claude, ChatGPT (OpenAI MCP), Cursor, Microsoft Copilot Studio, Perplexity und weiteren.
  • Hugging-Face-Datensatz. voilaj/swiss-caselaw — Parquet-Shards, täglich als Delta publiziert.
  • Word-Add-in. opencaselaw.ch/word/ — Office-Add-in für Microsoft Word; bietet denselben Such- und Pinpoint-Stack innerhalb des Dokuments.

Diese Seite spiegelt das Live-System wider. Falls Sie eine Abweichung zwischen dem hier Beschriebenen und dem entdecken, was der Quellcode aussagt, gilt der Quellcode — eröffnen Sie ein Issue, und wir korrigieren eines von beiden.