Compare commits
2
Commits
7cecc5c0cd
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62e1923a72 | ||
|
|
c18e94e61e |
@@ -346,16 +346,24 @@ Entwicklungsmaschine (Fedora, Python 3.14) — `neu 0, geändert 0, unverändert
|
|||||||
|
|
||||||
### Betrieb
|
### Betrieb
|
||||||
|
|
||||||
`deploy/` enthält `wurzelwerk-p2.service` und `.timer` als Vorlage. Kein
|
`deploy/` enthält `wurzelwerk-p2.container` und `.timer` als Vorlage,
|
||||||
Quadlet: Phase 2 ist kein Dienst, der läuft, sondern ein Auftrag, der fällig
|
dazu `INBETRIEBNAHME.md` mit der Reihenfolge. Quadlet, wie Phase 1 — aber
|
||||||
wird. Der Timer feuert versetzt zum 15-Minuten-Raster von Phase 1
|
mit `Type=oneshot` und ohne `RemainAfterExit`: Phase 2 ist kein Dienst, der
|
||||||
|
läuft, sondern ein Auftrag, der fällig wird und danach verschwindet. Mit
|
||||||
|
`RemainAfterExit=yes` bliebe die Unit im Zustand „started" stehen, und der
|
||||||
|
Timer könnte sie nie wieder auslösen.
|
||||||
|
|
||||||
|
Der Timer feuert versetzt zum 15-Minuten-Raster von Phase 1
|
||||||
(`*:03,18,33,48`), damit der Slot vollständig in `raw_items` steht, bevor
|
(`*:03,18,33,48`), damit der Slot vollständig in `raw_items` steht, bevor
|
||||||
daraus kodiert wird. `phase2.py --aufholen` arbeitet alle Slots nach, denen
|
daraus kodiert wird. `phase2.py --aufholen` arbeitet alle Slots nach, denen
|
||||||
eine Kodierung fehlt — ein ausgefallener Lauf holt sich beim nächsten Mal
|
eine Kodierung fehlt — ein ausgefallener Lauf holt sich beim nächsten Mal
|
||||||
selbst ein.
|
selbst ein.
|
||||||
|
|
||||||
Zugangsdaten stehen in `~/.config/wurzelwerk/p2.env` (chmod 600), nicht im
|
Zugangsdaten stehen in `~/.config/wurzelwerk/database.env` und
|
||||||
Repo und nicht in der Unit. Vorlage: `deploy/p2.env.beispiel`.
|
`p2.env` (chmod 600), nicht im Repo und nicht in der Unit. Vorlage:
|
||||||
|
`deploy/p2.env.beispiel`. Beide gehen als `--env-file` an podman, nicht über
|
||||||
|
systemds `EnvironmentFile=` im Abschnitt `[Service]` — podman entfernt keine
|
||||||
|
Anführungszeichen um Werte, systemd schon.
|
||||||
|
|
||||||
## Modul 5: Embeddings
|
## Modul 5: Embeddings
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ JSON-Dateien. Ohne diesen Schritt läuft Modul 4 durch und löst nichts auf,
|
|||||||
**ohne zu scheitern** — der teuerste stille Fehler der ganzen Einrichtung.
|
**ohne zu scheitern** — der teuerste stille Fehler der ganzen Einrichtung.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
podman run --rm --network=pasta \
|
podman run --rm --network=bebop-net \
|
||||||
--env-file ~/.config/wurzelwerk/database.env \
|
--env-file ~/.config/wurzelwerk/database.env \
|
||||||
localhost/wurzelwerk-p2 lexikon.py --laden
|
localhost/wurzelwerk-p2 lexikon.py --laden
|
||||||
```
|
```
|
||||||
@@ -48,10 +48,10 @@ Erwartet: `person 5631`, `organisation 2319`, `partei 682`, `staat 195`,
|
|||||||
`amt 29`, `amtsinhaber 418`. Die `Ueberschneidung:`-Zeilen sind die
|
`amt 29`, `amtsinhaber 418`. Die `Ueberschneidung:`-Zeilen sind die
|
||||||
Betriebssicht auf Doppelspitzen und Bremer Bürgermeister, kein Fehler.
|
Betriebssicht auf Doppelspitzen und Bremer Bürgermeister, kein Fehler.
|
||||||
|
|
||||||
Läuft der Container hier in einen Verbindungsfehler, zeigt `DATABASE_URL`
|
Das Netz ist nicht schmückend: `DATABASE_URL` zeigt auf den Rechnernamen
|
||||||
vermutlich auf `127.0.0.1`. Aus dem Container heraus ist das der Container
|
`postgres`, und den löst nur Podmans DNS innerhalb von `bebop-net` auf.
|
||||||
selbst; nötig ist `host.containers.internal`. Dann in `p2.env` überschreiben
|
Ohne `--network=bebop-net` scheitert die Namensauflösung, nicht die
|
||||||
(Schritt 4), statt `database.env` anzufassen — die gehört Phase 1 mit.
|
Anmeldung — die Fehlermeldung nennt dann den Namen, nicht das Passwort.
|
||||||
|
|
||||||
## 3. Modell-Volume anlegen und einmal füllen
|
## 3. Modell-Volume anlegen und einmal füllen
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ nicht aus dem Timer: der Erstbestand über den gesamten Korpus dauert etwa
|
|||||||
17 Minuten je 5000 Items, und `TimeoutStartSec=1800` ist dafür knapp.
|
17 Minuten je 5000 Items, und `TimeoutStartSec=1800` ist dafür knapp.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
podman run --rm --network=pasta --memory=8g --shm-size=1g \
|
podman run --rm --network=bebop-net --memory=8g --shm-size=1g \
|
||||||
--volume wurzelwerk-modelle:/cache:U \
|
--volume wurzelwerk-modelle:/cache:U \
|
||||||
--env-file ~/.config/wurzelwerk/database.env \
|
--env-file ~/.config/wurzelwerk/database.env \
|
||||||
--env OMP_NUM_THREADS=4 --env HF_HUB_OFFLINE=0 \
|
--env OMP_NUM_THREADS=4 --env HF_HUB_OFFLINE=0 \
|
||||||
@@ -97,8 +97,12 @@ das Modell nie wieder ins Netz und lädt in zwei Sekunden aus dem Volume.
|
|||||||
## 5. Units einhängen
|
## 5. Units einhängen
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cp deploy/wurzelwerk-p2.{service,timer} ~/.config/systemd/user/
|
cp deploy/wurzelwerk-p2.container ~/.config/containers/systemd/
|
||||||
|
cp deploy/wurzelwerk-p2.timer ~/.config/systemd/user/
|
||||||
systemctl --user daemon-reload
|
systemctl --user daemon-reload
|
||||||
|
|
||||||
|
# Was Quadlet daraus erzeugt hat, vor dem ersten Start ansehen:
|
||||||
|
/usr/lib/systemd/user-generators/podman-user-generator --dryrun
|
||||||
systemctl --user start wurzelwerk-p2.service # ein Lauf von Hand
|
systemctl --user start wurzelwerk-p2.service # ein Lauf von Hand
|
||||||
journalctl --user -u wurzelwerk-p2 -n 40
|
journalctl --user -u wurzelwerk-p2 -n 40
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
# Nach ~/.config/wurzelwerk/p2.env kopieren und ausfuellen. chmod 600.
|
# Nach ~/.config/wurzelwerk/p2.env kopieren und ausfuellen. chmod 600.
|
||||||
# Enthaelt Zugangsdaten und gehoert nicht ins Repo.
|
# Enthaelt Zugangsdaten und gehoert nicht ins Repo.
|
||||||
|
|
||||||
|
# Das Netz steht in der Quadlet-Unit (Network=bebop-net), nicht hier.
|
||||||
|
#
|
||||||
# Die Datenbankverbindung steht auf Prod bereits in
|
# Die Datenbankverbindung steht auf Prod bereits in
|
||||||
# ~/.config/wurzelwerk/database.env; die Unit liest beide Dateien. Hier nur
|
# ~/.config/wurzelwerk/database.env; die Unit liest beide Dateien. Hier nur
|
||||||
# setzen, wenn Phase 2 eine andere braucht - etwa weil database.env auf
|
# setzen, wenn Phase 2 eine andere braucht.
|
||||||
# 127.0.0.1 zeigt, was aus dem Container heraus ins Leere laeuft.
|
|
||||||
#
|
#
|
||||||
# DATABASE_URL=postgresql://wurzelwerk:PASSWORT@host.containers.internal:5432/wurzelwerk
|
# Anfuehrungszeichen um den Wert weglassen: podman --env-file entfernt sie
|
||||||
|
# nicht, anders als systemd.
|
||||||
|
#
|
||||||
|
# DATABASE_URL=postgresql://wurzelwerk:PASSWORT@postgres:5432/wurzelwerk
|
||||||
|
|
||||||
# Threadzahl. Geht in die coder_version ein - eine Aenderung erzeugt einen
|
# Threadzahl. Geht in die coder_version ein - eine Aenderung erzeugt einen
|
||||||
# neuen Vektorbestand. Prod hat 16 Threads, 4 laeuft ueberall.
|
# neuen Vektorbestand. Prod hat 16 Threads, 4 laeuft ueberall.
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# Phase 2 als Quadlet, neben wurzelwerk-ingest.container.
|
||||||
|
#
|
||||||
|
# cp deploy/wurzelwerk-p2.container ~/.config/containers/systemd/
|
||||||
|
# cp deploy/wurzelwerk-p2.timer ~/.config/systemd/user/
|
||||||
|
# systemctl --user daemon-reload
|
||||||
|
#
|
||||||
|
# Quadlet erzeugt daraus wurzelwerk-p2.service; der Timer traegt denselben
|
||||||
|
# Namen und findet sie deshalb ohne Unit=-Zeile.
|
||||||
|
#
|
||||||
|
# Kein [Install]: die Unit soll nicht beim Anmelden starten, sondern nur,
|
||||||
|
# wenn der Timer sie faellig macht.
|
||||||
|
|
||||||
|
[Unit]
|
||||||
|
Description=Wurzelwerk Phase 2 (Aufbereitung)
|
||||||
|
# Nicht Requires: laeuft Postgres gerade nicht, soll der Slot ausfallen und
|
||||||
|
# beim naechsten Mal ueber --aufholen nachgeholt werden, nicht die
|
||||||
|
# Abhaengigkeit neu starten.
|
||||||
|
After=postgres.service
|
||||||
|
|
||||||
|
[Container]
|
||||||
|
Image=localhost/wurzelwerk-p2
|
||||||
|
# Das Abbild hat ENTRYPOINT python3; Exec= liefert nur das Argument.
|
||||||
|
Exec=phase2.py --aufholen
|
||||||
|
|
||||||
|
# Ohne dieses Netz loest der Rechnername "postgres" aus DATABASE_URL nicht
|
||||||
|
# auf. Der Fehler waere dann eine Namensaufloesung, keine Anmeldung.
|
||||||
|
Network=bebop-net
|
||||||
|
|
||||||
|
# Zwei Dateien, in dieser Reihenfolge - die spaetere gewinnt bei gleichem
|
||||||
|
# Schluessel. database.env haelt die Datenbankverbindung und gehoert Phase 1
|
||||||
|
# mit; sie wird hier nur gelesen, nicht angefasst. p2.env traegt, was nur
|
||||||
|
# Phase 2 angeht.
|
||||||
|
#
|
||||||
|
# Achtung, anderer Mechanismus als bei EnvironmentFile= im Abschnitt
|
||||||
|
# [Service]: Quadlet reicht diese Dateien als "podman run --env-file" weiter.
|
||||||
|
# Podman entfernt keine Anfuehrungszeichen. Steht in database.env
|
||||||
|
# DATABASE_URL="postgresql://..." mit Anfuehrungszeichen, landen sie im Wert
|
||||||
|
# und die Verbindung scheitert. systemd wuerde sie entfernen, podman nicht.
|
||||||
|
EnvironmentFile=%h/.config/wurzelwerk/database.env
|
||||||
|
EnvironmentFile=%h/.config/wurzelwerk/p2.env
|
||||||
|
|
||||||
|
# 2,2 GB Modellgewichte. Muessen ein Volume sein, sonst waeren sie bei jedem
|
||||||
|
# Neubau des Abbilds weg.
|
||||||
|
Volume=wurzelwerk-modelle:/cache:U
|
||||||
|
|
||||||
|
Memory=8g
|
||||||
|
ShmSize=1g
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
# Der Container laeuft und ist fertig; nichts bleibt stehen. Ohne diese Zeile
|
||||||
|
# setzt Quadlet Type=notify, und die Unit gaelte als gestartet, sobald der
|
||||||
|
# Container laeuft - nicht, wenn er durch ist.
|
||||||
|
#
|
||||||
|
# Kein RemainAfterExit=yes, obwohl das Handbuch es fuer oneshot sonst
|
||||||
|
# empfiehlt: bei Timer-Aktivierung bliebe der Auftrag im Zustand "started"
|
||||||
|
# stehen und der Timer koennte ihn nie wieder ausloesen.
|
||||||
|
#
|
||||||
|
# Type=oneshot schaltet die Startzeitgrenze ab. Der Erstbestand ueber den
|
||||||
|
# gesamten Korpus - rund 17 Minuten je 5000 Items - liefe hier also nicht in
|
||||||
|
# TimeoutStartSec. Trotzdem gehoert er von Hand gefahren, siehe
|
||||||
|
# INBETRIEBNAHME.md: beim ersten Lauf werden 2,2 GB Modellgewichte geladen,
|
||||||
|
# und das will man sehen, nicht im Journal nachlesen.
|
||||||
|
Type=oneshot
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# Phase 2 fuer den juengsten Slot. Nach ~/.config/systemd/user/ legen.
|
|
||||||
#
|
|
||||||
# systemctl --user daemon-reload
|
|
||||||
# systemctl --user enable --now wurzelwerk-p2.timer
|
|
||||||
#
|
|
||||||
# Kein Quadlet: das hier ist kein Dienst, der laeuft, sondern ein Auftrag, der
|
|
||||||
# faellig wird. Quadlet-Units sind fuer Container gedacht, die stehen bleiben.
|
|
||||||
|
|
||||||
[Unit]
|
|
||||||
Description=Wurzelwerk Phase 2 (Aufbereitung)
|
|
||||||
# Nicht Requires: laeuft Postgres gerade nicht, soll der Slot ausfallen und
|
|
||||||
# beim naechsten Mal ueber --aufholen nachgeholt werden, nicht die
|
|
||||||
# Abhaengigkeit neu starten.
|
|
||||||
After=postgres.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=oneshot
|
|
||||||
# Zwei Dateien, in dieser Reihenfolge. database.env haelt die
|
|
||||||
# Datenbankverbindung und gehoert nicht Phase 2 allein - sie steht auf Prod
|
|
||||||
# schon da und wird hier nur mitgelesen, nicht angefasst. p2.env traegt, was
|
|
||||||
# nur Phase 2 angeht; wird dort DATABASE_URL noch einmal gesetzt, gewinnt sie,
|
|
||||||
# weil systemd spaetere Dateien spaeter liest.
|
|
||||||
#
|
|
||||||
# Beide muessen aus dem Container heraus aufloesbar sein: der Rechnername in
|
|
||||||
# DATABASE_URL darf nicht 127.0.0.1 sein, sondern host.containers.internal.
|
|
||||||
EnvironmentFile=%h/.config/wurzelwerk/database.env
|
|
||||||
EnvironmentFile=-%h/.config/wurzelwerk/p2.env
|
|
||||||
TimeoutStartSec=1800
|
|
||||||
ExecStart=/usr/bin/podman run --rm \
|
|
||||||
--name wurzelwerk-p2-lauf \
|
|
||||||
--network=pasta \
|
|
||||||
--memory=8g --shm-size=1g \
|
|
||||||
--volume wurzelwerk-modelle:/cache:U \
|
|
||||||
--env DATABASE_URL \
|
|
||||||
--env OMP_NUM_THREADS \
|
|
||||||
--env HF_HUB_OFFLINE \
|
|
||||||
localhost/wurzelwerk-p2 phase2.py --aufholen
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
||||||
Reference in New Issue
Block a user