151 lines
9.5 KiB
Markdown
151 lines
9.5 KiB
Markdown
# CasaDePrompt
|
||
|
||
Dein privates Zuhause für gute Prompts. Ein Python-Prozess, eine SQLite-Datei, ein Container. Kein PostgreSQL, Redis oder externer Suchdienst. Dunkle, responsive Weboberfläche ohne CDN oder Build-Schritt.
|
||
|
||
Eine optionale Sammlung mit sechs Beispielen liegt in `beispiel-prompts.json` und lässt sich über die Einstellungen importieren. Neue Installationen starten leer.
|
||
|
||
## Was drin ist
|
||
|
||
- Prompt-Bibliothek mit Kategorien, Tags, Favoriten, Papierkorb und Duplikaten.
|
||
- Versionierung des vollständigen Prompts, Versionsvorschau und Wiederherstellung als neue Version. Gleichzeitige Änderungen werden erkannt.
|
||
- Textsuche und Bedeutungssuche mit Embeddings. „Auto“ kombiniert beide; ähnliche Ergebnisse sind Vorschläge, keine garantierten Treffer.
|
||
- OpenAI-kompatible API-Basis-URL, optionaler API-Key, Modellscan über `/models`, getrennte Chat- und Embedding-Modelle. Optional separater Embedding-Endpoint.
|
||
- KI-Vorschläge für Kategorie, Tags und Kurzbeschreibung; vor dem Speichern manuell übernehmen.
|
||
- Zweiter Modellaufruf prüft die Bedeutungstreue. Bei Abweichungen folgen höchstens eine Korrektur und eine erneute Prüfung (2–4 Aufrufe). Befunde und Fehler erscheinen am Entwurf; Modellprüfung ist keine Garantie. Manuelle Änderungen am Vorschlag setzen den Prüfstatus zurück.
|
||
- KI-Überarbeitung als bearbeitbarer Vorschlag neben dem Original. Erst Übernehmen und Speichern ändert den Prompt.
|
||
- Privater MCP-Server über Streamable HTTP, nur lesend: `search_prompts`, `get_prompt`, `list_categories`, `get_prompt_versions`.
|
||
- JSON-Export und Import inklusive Versionen, ohne Modell-API-Keys.
|
||
- Zugangsschlüssel für die Weboberfläche, separater MCP-Schlüssel. Keine Registrierung, keine öffentlichen Profile, keine Telemetrie.
|
||
|
||
## Unraid: normaler Python-Alpine-Container
|
||
|
||
### 1. Dateien auf dem NAS ablegen
|
||
|
||
```text
|
||
/mnt/user/appdata/CasaDePrompt/
|
||
├── bootstrap/
|
||
│ └── Startpunkt.sh
|
||
└── data/ # wird dauerhaft gespeichert
|
||
```
|
||
|
||
`Startpunkt.sh` aus diesem Repository nach `bootstrap/` kopieren. Der Download erfolgt ausschließlich über HTTPS aus dem öffentlich lesbaren Repository. Keine SSH-Keys oder anderen Git-Zugangsdaten mounten oder kopieren.
|
||
|
||
### 2. Unraid-Vorlage einspielen
|
||
|
||
`unraid/CasaDePrompt.xml` nach
|
||
|
||
```text
|
||
/boot/config/plugins/dockerMan/templates-user/my-CasaDePrompt.xml
|
||
```
|
||
|
||
kopieren. In **Docker → Container hinzufügen → Vorlage** `CasaDePrompt` auswählen. Falls die Auswahl noch nicht aktualisiert ist, die Seite neu laden.
|
||
|
||
Vorbelegt sind:
|
||
|
||
| Einstellung | Wert |
|
||
|---|---|
|
||
| Image | `python:3.13-alpine` |
|
||
| Netzwerk | `bridge` (normales Unraid-Netz über Portfreigabe) |
|
||
| Web-Port | Host `8765` → Container `8000` |
|
||
| Repository | `https://git.casaderoll.de/michael/CasaDePrompt.git` |
|
||
| Branch | `main` |
|
||
| Startbefehl / Post Arguments | `/bin/sh /bootstrap/Startpunkt.sh` |
|
||
| App-Benutzer | `99:100` |
|
||
|
||
Beim Start installiert das Skript Git und Python-Pakete, lädt den gewählten Branch bzw. Tag und startet die Anwendung ohne root-Rechte. Dafür benötigt es Zugriff auf dein Git, Alpine-Paketserver und PyPI. Ein Neustart lädt den aktuellen Stand erneut. Bei Download-/Installationsfehlern stoppt es mit einer Meldung, statt eine halb installierte App zu starten. Für reproduzierbare Updates einen Release-Tag in `APP_REF` verwenden.
|
||
|
||
### 3. Anmelden
|
||
|
||
Öffnen: `http://UNRAID-IP:8765`
|
||
|
||
Den automatisch erzeugten Zugangsschlüssel in der Unraid-Konsole auslesen:
|
||
|
||
```sh
|
||
docker exec CasaDePrompt cat /data/admin-token
|
||
```
|
||
|
||
In der Anmeldemaske eingeben. Der Browser erhält ein HttpOnly-Sitzungscookie (24 Stunden). Der Schlüssel wird nicht im Browser-LocalStorage gespeichert. Sitzungen enden auch bei einem Serverneustart.
|
||
|
||
### 4. Modelle verbinden
|
||
|
||
Unter **Einstellungen** beispielsweise `http://192.168.1.20:1234/v1` eintragen. Aus dem Container bedeutet `localhost` der Container selbst; für einen anderen Server dessen LAN-IP verwenden.
|
||
|
||
Optional API-Key eingeben → **Modelle scannen** → Modell-ID auswählen. Alternativ direkt eintippen. Der Scan speichert zunächst die Verbindungsfelder. Leere Schlüssel-Felder behalten gespeicherte Keys; zum Löschen gibt es eine eigene Checkbox.
|
||
|
||
- **Chatmodell:** für „Mit KI verfeinern“, verwendet `/chat/completions`.
|
||
- **Embedding-Modell:** für Bedeutungssuche, verwendet `/embeddings`. Ein Chatmodell kann diese Aufgabe nicht automatisch ersetzen.
|
||
|
||
Danach **Index ergänzen**. Neue/geänderte Prompts werden beim Speichern indexiert. Bei einem Fehler bleibt der Prompt gespeichert und die Oberfläche zeigt einen Hinweis. Nach Wechsel von Embedding-Modell oder URL sind alte Vektoren nicht mehr gültig. Wenn hinter derselben Modell-ID ein anderes Modell läuft, **Komplett neu aufbauen** wählen.
|
||
|
||
Ohne Embeddings funktioniert die Textsuche. Es gibt keine versteckte Behauptung von Bedeutungssuche: Der verwendete Suchmodus und Fehler werden angezeigt. Die Embedding-Suche erfolgt im Python-Prozess, die Vektoren liegen in SQLite; gedacht für ein persönliches Archiv, nicht Millionen Dokumente.
|
||
|
||
## MCP / OpenClaw
|
||
|
||
**Einstellungen → MCP → Verbindungsdaten anzeigen** liefert URL und separaten Bearer-Token.
|
||
|
||
```text
|
||
Transport: Streamable HTTP
|
||
URL: http://UNRAID-IP:8765/mcp/
|
||
Header: Authorization: Bearer DEIN_MCP_TOKEN
|
||
```
|
||
|
||
Diese Angaben in einem MCP-fähigen Client bzw. dessen MCP-Bridge eintragen. Die konkrete OpenClaw-Konfiguration hängt von dessen installierter Version und MCP-Anbindung ab; das angezeigte JSON beschreibt die Verbindung und ist keine zugesicherte OpenClaw-Konfigurationsdatei.
|
||
|
||
Beispielauftrag: „Suche in CasaDePrompt nach einem Prompt, um einem Kunden höflich abzusagen.“
|
||
|
||
`search_prompts` akzeptiert `query`, `limit` und `mode` (`auto`, `text`, `semantic`). Ergebnisse enthalten Titel, vollständigen Prompt, Kategorie, Tags, Version und gegebenenfalls Ähnlichkeit sowie Suchhinweise. `get_prompt` kann gezielt eine frühere Version abrufen. Papierkorb-Inhalte werden nicht über MCP ausgegeben. MCP darf keine Prompts ändern und verwendet weder deinen Web-Zugangsschlüssel noch deinen Modell-API-Key.
|
||
|
||
## Alternative: fest gebautes Image
|
||
|
||
```sh
|
||
docker compose up -d --build
|
||
docker compose exec casadeprompt cat /data/admin-token
|
||
```
|
||
|
||
Das beiliegende Dockerfile nutzt ebenfalls `python:3.13-alpine`; der App-Code wird beim Build eingebaut. Es braucht beim Start keinen Git-Key und keine Paketdownloads. Daten liegen in einem Docker-Volume. Dieser Weg ist unabhängig vom gewünschten Unraid-Bootstrap nutzbar.
|
||
|
||
## Lokal entwickeln
|
||
|
||
Python 3.13 oder neuer:
|
||
|
||
```sh
|
||
python3 -m venv .venv
|
||
. .venv/bin/activate
|
||
pip install -r requirements.txt
|
||
DATA_DIR=./data uvicorn atelier.app:create_app --factory --host 127.0.0.1 --port 8765
|
||
```
|
||
|
||
Tests:
|
||
|
||
```sh
|
||
pip install pytest
|
||
python -m pytest tests -q
|
||
```
|
||
|
||
Der interne Python-Paketname `atelier` ist nur ein Implementierungsdetail.
|
||
|
||
## Daten, Backup und Betrieb
|
||
|
||
- `/data/atelier.sqlite3`: Prompts, Versionen und Vektoren.
|
||
- `/data/settings.json`: Endpoint-Einstellungen und API-Keys. Nur serverseitig; in Exporten nicht enthalten.
|
||
- `/data/admin-token`, `/data/mcp-token`: Zugangsschlüssel.
|
||
- Gesamten Datenordner **bei gestopptem Container** sichern; bei laufender SQLite-WAL-Datenbank nicht nur die Hauptdatei kopieren. JSON-Export ist jederzeit für Prompts/Versionen nutzbar.
|
||
- Import legt neue IDs an, erhält Versionen, löscht nichts. Danach Index ergänzen.
|
||
- API-Keys sind durch Dateirechte geschützt, nicht separat verschlüsselt. Wer Host-/Root-Zugriff hat, kann sie lesen.
|
||
- Für Zugriff außerhalb eines vertrauenswürdigen LANs HTTPS über einen Reverse Proxy nutzen. Bei HTTPS `COOKIE_SECURE=1` setzen. Keine CORS-Freigabe; Weboberfläche und API verwenden denselben Origin.
|
||
- Ein uvicorn-Prozess; keine zusätzlichen Worker verwenden, da Sitzungen im Arbeitsspeicher liegen.
|
||
- `GET /health` ist ein öffentlicher einfacher Healthcheck.
|
||
- Schlüssel rotieren: Container stoppen, entsprechende Token-Datei löschen, starten. Bestehende Clients müssen den neuen Schlüssel erhalten. Alternativ `ADMIN_TOKEN`/`MCP_TOKEN` als Umgebungsvariablen setzen; dann gelten diese statt der Dateien.
|
||
|
||
## Stand und Grenzen
|
||
|
||
Erste eigenständige Version. Die KI-Überarbeitung ist absichtlich ein manueller Entwurf; ein grafischer Wort-für-Wort-Diff ist noch nicht enthalten. Versionsvorschau und Wiederherstellung sind vorhanden. Die Tests nutzen einen simulierten OpenAI-kompatiblen Modellserver; ein konkretes lokales Modell muss beim Einrichten noch geprüft werden. Docker/Unraid wird über die beiliegenden Dateien vorbereitet, ein echter Container-Test muss auf einer Maschine mit Docker erfolgen.
|
||
|
||
## KI-Selbstprüfung und Diagnose
|
||
|
||
Die Prüfung stammt vom selben Modell und ist keine unabhängige Verifikation. Historische Befunde zum ersten Entwurf sind getrennt von Befunden zum aktuellen Vorschlag. Bei Fehlern bleibt der Entwurf erhalten; die Meldung benennt den fehlgeschlagenen Schritt und eine Diagnose-ID. „Aktuellen Vorschlag erneut prüfen“ führt genau einen Prüfanruf ohne automatische Textänderung aus.
|
||
|
||
Zusätzlich vergleicht Code erkennbare `{{Platzhalter}}`, explizite Portangaben und Pfadmuster. Unterschiede sind Hinweise, keine sicheren Fehler: Auch gewünschte Änderungen können markiert werden; nicht jedes mögliche Pfadformat wird erkannt. Ein Bearbeiten der Vergleichstexte setzt die Anzeige auf ungeprüft zurück.
|
||
|
||
Containerlogs enthalten für Modellaufrufe ausschließlich Diagnose-ID, Verarbeitungsschritt, Dauer, HTTP-Status und Fehlerklasse. Prompt-/Antwortinhalte, API-Keys und Endpoint-URLs werden nicht durch diese Diagnose protokolliert. Drittanbieter-HTTP-Info-Logs sind deaktiviert. Der bisherige 90-Sekunden-Timeout bleibt unverändert.
|