Famulus-Referenz
Belege mit Adresse, Zitat und Herkunft
Eine Famulus-Referenz ist eine Referenzdatenquelle, die Famulus Proof als Grundlage für Belege braucht: Jedes Item einer Collection hat eine fr:-Adresse, ein Zitat aus erfassten bibliographischen Daten, eine Herkunftskette und Prüfvermerke, und alles steht in einem DuckLake zu einem benannten Snapshot.
Was eine Famulus-Referenz ist
Eine Collection von PDAI-1 wird zur Famulus-Referenz, wenn jedes ihrer Items (Dokument, Seite, Segment) vier Dinge hat:
| Bestandteil | Inhalt | Tabelle |
|---|---|---|
| fr:-Adresse | stabile Adresse des Items | fr_document, fr_page, fr_segment |
| Zitat | BibTeX, CSL-JSON, Textzitat, Fundstelle; nur aus biblio.xml oder dem Deskriptor |
fr_citation |
| Herkunft | Schritt, Werkzeug, Modell, Anweisung, sha256 von Eingabe und Ausgabe | fr_provenance, fr_source |
| Prüfvermerk | Prüfung, Grad DOCUMENTED / INFERRED / HYPOTHESIS / GAP, Zertifikat | fr_validation |
Das Paket famulus-reference (pdai/famulus-reference) baut daraus je Collection ein Sammlungsschema im DuckLake pdai-collections/_lake/famulus.ducklake nach dem Schema famulus-reference/1. Die Sidecars einer Collection (*_fql, *_stanza) stehen als Kopie im Schema legacy_<coll>; die Kopie ist bei der Migration auf Gleichheit mit dem Original geprüft (fr_migration_log). Geschrieben wird der DuckLake nur auf mac-studio; alle anderen Rechner lesen ihn schreibgeschützt.
Famulus Proof verwendet die Famulus-Referenz an zwei Stellen: als Quelle der Tabellen, auf die FQL und Zielentfaltung ihre Anfragen stellen (Lake-Modus), und als Auflösung der Adresse eines Belegs (famulus_proof.lake.resolve_fr).
Die fr:-Adresse
fr:<collection>/<doc>[/<pidx:04d>[/<segment>]]
| Teil | Bedeutung | Beispiel |
|---|---|---|
<collection> |
Name der Collection, zugleich ihr Sammlungsschema | hartmann |
<doc> |
Ordner des Dokuments | bsb00028171 |
<pidx> |
Seitenindex, vierstellig | 0137 |
<segment> |
Bezeichner des Segments oder s und 8 Hexziffern eines Inhaltshashs |
print1 |
fr:hartmann/bsb00028171/0137/print1 bezeichnet das Segment print1 auf Seite 137 des Dokuments bsb00028171 der Collection hartmann. Kürzere Adressen bezeichnen die Seite, das Dokument oder die Collection. Globale Kennungen (URN, ARK, DOI, GND, Signatur, IIIF) stehen nicht in der Adresse, sondern in fr_identifier.
Die Adresse als Clause.address
Eine Klausel der Grundresolution (famulus_proof.resolution.Clause) trägt ihre Fundstelle im Feld address. Für einen Beleg aus einer Famulus-Referenz ist das die fr:-Adresse, unverändert. lake.beleg(adresse) liefert die Felder dafür: label ist das Zitat (oder die Adresse, wenn es keines gibt), excerpt die ersten 400 Zeichen der ersten Textschicht.
from famulus_proof import lake
from famulus_proof.resolution import Clause
b = lake.beleg("fr:hartmann/bsb00028171/0137/print1")
k = Clause(frozenset({(True, "Druck(fr:hartmann/bsb00028171/0137/print1)")}),
kind="beleg", label=b["label"], address=b["address"], excerpt=b["excerpt"])beleg() gibt außerdem found und snapshot zurück. Ist found falsch, ist die Klausel kein Beleg; der Aufrufer nimmt sie nicht in die Klauselmenge auf und vermerkt eine Lücke.
Was resolve_fr zurückgibt
famulus_proof.lake.resolve_fr(adresse) liest das Item aus dem DuckLake:
| Schlüssel | Inhalt |
|---|---|
adresse |
die angefragte fr:-Adresse |
found |
true, wenn der DuckLake das Item oder einen Text dazu hat |
item |
die Zeile aus fr_segment, fr_page oder fr_document, je nach Länge der Adresse |
texte |
Textschichten (ocr, diplomatic, normalised, translation), je mit text und sha256 |
zitat, bibtex |
Textzitat und BibTeX des Items oder des nächsten Vorfahren mit erfasstem Zitat |
zitiert_als |
die Adresse, deren Zitat verwendet ist: das Item selbst, wenn es ein eigenes Zitat hat, sonst der nächste Vorfahr mit erfasstem Zitat |
luecken |
Felder, die in den bibliographischen Daten fehlen; ["citation"], wenn kein Zitat erfasst ist |
herkunft |
Schritte der Herkunftskette: Schritt, Werkzeug, Modell, sha256, Datei |
snapshot |
Nummer des DuckLake-Snapshots, zu dem gelesen wurde |
Eine unbekannte Adresse ergibt {"found": false, "luecke": …} mit dem Grund (Collection nicht im DuckLake oder Adresse nicht im DuckLake), nie eine leere Antwort, die als Beleg gelesen werden könnte. Eine Zeichenkette, die keine fr:-Adresse ist, ergibt einen ValueError.
Lake-Modus: FAMULUS_LAKE=1
Ohne die Umgebungsvariable lesen alle Verbindungen die Sidecar-Datei wie bisher. Mit FAMULUS_LAKE=1 gilt:
| Funktion | Verhalten im Lake-Modus |
|---|---|
famulus_proof.fql.engine.connect(collection, stanza=…) |
liest aus dem DuckLake, wenn er eine Kopie der Collection hält |
famulus_proof.entfaltung.evidence.connect(collection, stanza=…) |
ebenso, die Stanza-Tabellen unter stz |
famulus_proof.fql.engine.has_sidecar(collection) |
wahr, wenn Sidecar-Datei oder Kopie im DuckLake vorhanden ist |
Die Verbindung ist eine DuckDB im Arbeitsspeicher, an die der DuckLake schreibgeschützt als lk angehängt ist. Die Tabellen fql__<t> und stanza__<t> des Schemas legacy_<coll> erscheinen als Sichten unter ihren ursprünglichen Namen (fq_documents, stz.stz_tokens …). Jede bestehende SQL-Anweisung läuft daher unverändert.
Hält der DuckLake keine Kopie der Collection, oder fehlt der Katalog, verwenden beide connect()-Funktionen die Sidecar-Datei.
Primärer Katalog und Lese-Replik
Der primäre Katalog ist FAMULUS_LAKE_CATALOG oder <collections_root>/_lake/famulus.ducklake. famulus_proof.lake.catalog_path() liest jedoch die Lese-Replik daneben (pdai-collections/_lake/famulus.read.ducklake), wenn sie vorhanden ist. Grund: Eine DuckDB-Katalogdatei ist während eines Schreiblaufs (Export, Migration, Wartung auf mac-studio) für andere Prozesse gesperrt. Jeder Schreiblauf veröffentlicht an seinem Ende eine Kopie des Katalogs als Lese-Replik, durch atomares Umbenennen. Leser werden dadurch nie blockiert und sehen den neuen Stand, sobald der Schreiblauf abgeschlossen ist; bis dahin lesen sie den Stand des vorigen Schreiblaufs.
| Lage | gelesener Katalog |
|---|---|
| Lese-Replik vorhanden | famulus.read.ducklake |
| keine Lese-Replik | famulus.ducklake |
FAMULUS_LAKE_PRIMARY gesetzt (etwa =1) |
famulus.ducklake, auch wenn eine Lese-Replik vorhanden ist |
Die Lese-Replik liegt immer neben dem primären Katalog; ein mit FAMULUS_LAKE_CATALOG gesetzter Katalog x.ducklake hat die Lese-Replik x.read.ducklake.
Die Volltextindizes (fts_main_*) sind nicht Teil des DuckLake. FQL-Formen, die match_bm25 aufrufen, brauchen weiter die Sidecar-Datei.
Zitate werden nicht zusammengesetzt
Ein Zitat stammt nur aus erfassten bibliographischen Daten (biblio.xml oder Deskriptor der Collection). Hat ein Item kein eigenes Zitat, gilt das des nächsten Vorfahren (Seite, Dokument, Collection), und die fr:-Adresse des Items ist die Fundstelle; zitiert_als nennt den Vorfahren. Hat auch kein Vorfahr ein Zitat, setzt weder resolve_fr noch der MCP-Server eines aus Titel, Autor oder Dateinamen zusammen: Das Ergebnis ist eine Lücke (luecken: ["citation"], beim MCP-Server status: "gap"). Einzelne fehlende Felder eines erfassten Zitats stehen ebenso in luecken und werden nicht ergänzt.
Reproduzierbarkeit über den Snapshot
Jede Antwort von resolve_fr, beleg und den Werkzeugen des MCP-Servers nennt den Snapshot des DuckLake, zu dem gelesen wurde. Ein Beleg ist damit relativ zu diesem Snapshot bestimmt: Wer die Begründung später prüft, liest die Tabellen zu demselben Snapshot. Die Wartung (famulus-reference maintain) lässt Snapshots nach sieben Tagen verfallen, ausgenommen die in fr_release festgehaltenen und alle Snapshots, die fr_cite oder fr_bibtex ausgegeben haben.
MCP-Werkzeuge für Begründungsanfragen
Der MCP-Server famulus-reference läuft auf mac-studio, Port 5135. Für die Begründung einer Antwort dienen drei Werkzeuge:
| Werkzeug | Eingabe | Antwort |
|---|---|---|
fr_cite |
fr:-Adresse, Stil (all, bibtex, csl, text) |
Zitat, cited_as, Fundstelle, Lücken, Snapshot; status ist ok, ancestor oder gap |
fr_trace |
fr:-Adresse | Item, sha256 der Textschichten, Herkunft, Prüfvermerke, Belegqualität (evidence_grade), Zitat, Kennungen, Snapshot |
fr_trace_run |
run_id |
die gelesenen Items, der Snapshot und die SQL-Anweisungen eines früheren Laufs |
fr_cite, fr_bibtex, fr_trace, fr_ground und fr_sql zeichnen jeden Aufruf als Lauf auf (fr_run, fr_run_step) und geben dessen run_id zurück. Eine Begründungsanfrage zu einer früheren Antwort wird mit fr_trace_run(run_id) beantwortet: Sie nennt, welche Items mit welchem Snapshot gelesen wurden. Mit fr_trace auf jedes dieser Items folgt die Herkunft und der Prüfvermerk jedes Belegs.
Weitere Werkzeuge (fr_describe_collection, fr_get_item, fr_get_provenance, fr_ground, fr_sql, fr_snapshot_info …) und die Ernte-Endpunkte (/oai, /jsonld, /iiif, /peers) beschreibt pdai/famulus-reference/README.md. Die Einordnung in die Schichten zeigt die Landkarte.