278 lines
11 KiB
Markdown
278 lines
11 KiB
Markdown
|
|
# Bedienungsanleitung — Open Notebook (lokales Deployment)
|
|||
|
|
|
|||
|
|
Diese Anleitung deckt die **tägliche Benutzung** ab. Installation/Neuaufbau:
|
|||
|
|
siehe [`README.md`](README.md). Technische Hintergründe und Architektur:
|
|||
|
|
siehe [`CLAUDE.md`](CLAUDE.md).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Inhalt
|
|||
|
|
|
|||
|
|
1. [Zugriff](#1-zugriff)
|
|||
|
|
2. [Notebooks und Quellen](#2-notebooks-und-quellen)
|
|||
|
|
3. [Chat: die drei Kontext-Modi](#3-chat-die-drei-kontext-modi)
|
|||
|
|
4. [Podcasts erzeugen](#4-podcasts-erzeugen)
|
|||
|
|
5. [Stimmklonung](#5-stimmklonung)
|
|||
|
|
6. [Modelle und Provider verwalten](#6-modelle-und-provider-verwalten)
|
|||
|
|
7. [Dienste starten/stoppen](#7-dienste-startenstoppen)
|
|||
|
|
8. [Troubleshooting](#8-troubleshooting)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. Zugriff
|
|||
|
|
|
|||
|
|
- **Web-Oberfläche:** `http://localhost:8502`
|
|||
|
|
- **REST-API** (für Automatisierung/Skripte): `http://localhost:5055`, Doku unter
|
|||
|
|
`http://localhost:5055/docs`
|
|||
|
|
|
|||
|
|
Beide sind nur von diesem Rechner aus erreichbar (`127.0.0.1`), nicht aus dem Netzwerk.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Notebooks und Quellen
|
|||
|
|
|
|||
|
|
Ein **Notebook** bündelt Quellen, Notizen, Chats und Podcasts zu einem Thema. Neues Notebook
|
|||
|
|
über „+ New Notebook" in der UI anlegen.
|
|||
|
|
|
|||
|
|
### Quellen hinzufügen
|
|||
|
|
|
|||
|
|
Unterstützt: hochgeladene Dateien (PDF, EPUB, TXT, DOCX, …), URLs, eingefügter Text.
|
|||
|
|
|
|||
|
|
**Wie lang darf eine Datei sein?** Es gibt kein hartes Limit für Upload/Verarbeitung — auch
|
|||
|
|
sehr große PDFs/EPUBs werden vollständig extrahiert und in Textabschnitte („Chunks")
|
|||
|
|
zerlegt, die für die Suche eingebettet werden. Eine Längenbegrenzung greift nur, wenn eine
|
|||
|
|
Quelle im **„Volltext"-Kontextmodus** (siehe Abschnitt 3) oder für eine **Transformation**
|
|||
|
|
verwendet wird — dort geht der komplette Text in einem Stück an das Sprachmodell. Praktischer
|
|||
|
|
Richtwert bei `qwen3.5:27b` (98.304 Tokens Kontext, siehe Abschnitt 6): grob **180–350
|
|||
|
|
Buchseiten**, abhängig von Textdichte. Wichtig: Die **Dateigröße in MB sagt nichts über die
|
|||
|
|
Textmenge aus** — ein gescanntes PDF mit vielen Bildern kann riesig sein, aber nach der
|
|||
|
|
Texterkennung kaum Inhalt liefern.
|
|||
|
|
|
|||
|
|
### Verarbeitungsstatus prüfen
|
|||
|
|
|
|||
|
|
Nach dem Hochladen läuft die Verarbeitung (Extraktion → Chunking → Embedding) im Hintergrund.
|
|||
|
|
Bei großen Dateien kann das ein bis mehrere Minuten dauern. Status ist in der UI an der Quelle
|
|||
|
|
sichtbar; per API: `GET /api/sources/{source_id}/status`.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Chat: die drei Kontext-Modi
|
|||
|
|
|
|||
|
|
Beim Chatten mit einem Notebook lässt sich pro Quelle einstellen, wie viel davon in den
|
|||
|
|
Chat-Kontext einfließt (Buttons/Auswahl in der UI, z. B. als Sammel-Aktion für alle Quellen):
|
|||
|
|
|
|||
|
|
| UI-Option | Bedeutung | Geschwindigkeit |
|
|||
|
|
|---|---|---|
|
|||
|
|
| **Alle aus dem Kontext ausschließen** | Quelle wird ignoriert | – |
|
|||
|
|
| **Alle aufnehmen (nur Erkenntnisse)** | Nutzt die generierten „Insights" (Zusammenfassungen) der Quelle | schnell (Sekunden) |
|
|||
|
|
| **Alle aufnehmen (vollständiger Inhalt)** | Kompletter Text der Quelle geht an das Sprachmodell | langsam bei langen Dokumenten (bis zu einigen Minuten) |
|
|||
|
|
|
|||
|
|
### Wichtig: „nur Erkenntnisse" braucht vorher eine Transformation
|
|||
|
|
|
|||
|
|
Der Modus „nur Erkenntnisse" ist **nur dann nützlich, wenn für die Quelle bereits eine
|
|||
|
|
Zusammenfassung („Insight") erzeugt wurde**. Ohne das liefert er praktisch nichts (nur Titel/
|
|||
|
|
Metadaten). Eine Zusammenfassung erzeugen:
|
|||
|
|
|
|||
|
|
- In der UI: bei der Quelle eine Transformation anwenden, z. B. **„Simple Summary"**
|
|||
|
|
(für die meisten Fälle passend) oder „Dense Summary", „Key Insights", „Table of Contents".
|
|||
|
|
- Per API:
|
|||
|
|
```bash
|
|||
|
|
curl -X POST http://127.0.0.1:5055/api/sources/{source_id}/insights \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-d '{"transformation_id": "<id aus GET /api/transformations>"}'
|
|||
|
|
```
|
|||
|
|
- Bei langen Dokumenten (z. B. ein ganzes Buch) dauert das einmalig **einige Minuten** (die
|
|||
|
|
gesamte Quelle wird einmal durchs Sprachmodell geschickt) — danach ist „nur Erkenntnisse"
|
|||
|
|
aber dauerhaft schnell nutzbar.
|
|||
|
|
|
|||
|
|
### Faustregel
|
|||
|
|
|
|||
|
|
- **Normale Fragen, Überblick, grobe Zusammenhänge** → „nur Erkenntnisse" (nach einmaliger
|
|||
|
|
Zusammenfassung)
|
|||
|
|
- **Sehr spezifische Detailfrage** (z. B. exaktes Zitat aus einem bestimmten Kapitel), die in
|
|||
|
|
der Zusammenfassung fehlen könnte → „vollständiger Inhalt", dafür Geduld bei langen Quellen
|
|||
|
|
- **Quelle für die aktuelle Frage irrelevant** → ausschließen (spart Zeit bei mehreren Quellen)
|
|||
|
|
|
|||
|
|
Für gezielte Detailsuche über viele/lange Quellen gibt es außerdem eine separate
|
|||
|
|
**Such-/Ask-Funktion**, die per Embedding-Ähnlichkeitssuche automatisch nur die relevanten
|
|||
|
|
Textstellen findet, statt ganze Dokumente einzubeziehen — meist die schnellste und treffsicherste
|
|||
|
|
Option für Detailfragen in langen Werken.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Podcasts erzeugen
|
|||
|
|
|
|||
|
|
Open Notebook kann aus Notebook-Inhalten automatisch einen Podcast (Dialog zwischen ein oder
|
|||
|
|
mehreren Sprechern) erzeugen — Text via Sprachmodell, Audio via TTS (hier: lokal, Chatterbox).
|
|||
|
|
|
|||
|
|
1. **Episode-Profil** wählen (bestimmt Sprecherzahl/-rollen, Anzahl Segmente, Textmodell):
|
|||
|
|
`solo_expert` (1 Sprecher), `tech_discussion` (2 Sprecher), `business_analysis` (3 Sprecher).
|
|||
|
|
2. Notebook/Quelle als Grundlage angeben.
|
|||
|
|
3. Generierung starten — läuft asynchron (Outline → Transkript → Sprachsynthese pro Segment).
|
|||
|
|
Bei mehreren Sprechern und langen Transkripten realistisch **mehrere Minuten**, da jedes
|
|||
|
|
Dialogsegment einzeln per TTS synthetisiert wird.
|
|||
|
|
4. Fertige Episode in der UI abspielbar/herunterladbar.
|
|||
|
|
|
|||
|
|
Alle Episode-/Sprecherprofile sind bereits auf lokale Modelle (`qwen3.5:27b` für Text,
|
|||
|
|
Chatterbox für Sprache) umgestellt — keine zusätzlichen Kosten.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. Stimmklonung
|
|||
|
|
|
|||
|
|
Die TTS-Wrapper (`services/tts_server.py`) unterstützt Stimmklonung: Referenz-WAV rein, Stimme
|
|||
|
|
raus. Aktuell hinterlegte Stimmen: `default` (eigene Stimme), `male_thorsten` und
|
|||
|
|
`female_kerstin` (offen lizenzierte, synthetische Piper-Stimmen — bewusst **keine** ungefragt
|
|||
|
|
geklonten echten Personen, siehe [`CLAUDE.md`](CLAUDE.md)).
|
|||
|
|
|
|||
|
|
### Eine weitere Stimme hinzufügen
|
|||
|
|
|
|||
|
|
1. Referenz-Aufnahme besorgen: **10–30 Sekunden**, eine Person, saubere Aufnahme, WAV-Format.
|
|||
|
|
Rechtlich sauber ist entweder eine eigene Aufnahme, eine Aufnahme mit ausdrücklicher
|
|||
|
|
Zustimmung der Person, oder eine offen für diesen Zweck lizenzierte Stimme (z. B. weitere
|
|||
|
|
[Piper-Stimmen](https://huggingface.co/rhasspy/piper-voices)).
|
|||
|
|
2. Datei nach `services/voices/<name>.wav` legen (z. B. `services/voices/elena.wav`).
|
|||
|
|
3. TTS-Server neu starten (Stimmen werden nur beim Start eingelesen):
|
|||
|
|
```bash
|
|||
|
|
pkill -f "python tts_server.py"
|
|||
|
|
./scripts/start_services.sh
|
|||
|
|
```
|
|||
|
|
4. Prüfen: `curl http://127.0.0.1:8901/health` sollte `<name>` in der `voices`-Liste zeigen.
|
|||
|
|
5. In einem Sprecherprofil (Podcast) den betreffenden Sprecher auf `voice_id: "<name>"` setzen,
|
|||
|
|
z. B. per API:
|
|||
|
|
```bash
|
|||
|
|
curl -X PUT http://127.0.0.1:5055/api/speaker-profiles/{id} \
|
|||
|
|
-H "Content-Type: application/json" -d '{... "speakers": [{"name": "Elena", ..., "voice_id": "elena"}], ...}'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Mit Piper lässt sich auch selbst eine Referenz-Stimme synthetisieren (statt eine echte Aufnahme
|
|||
|
|
zu verwenden):
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
echo "Ein Beispielsatz auf Deutsch." | piper --model <stimme>.onnx --output_file services/voices/<name>.wav
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Weitere deutsche Piper-Stimmen: `huggingface.co/rhasspy/piper-voices/tree/main/de/de_DE`
|
|||
|
|
(Lizenz jeweils im `MODEL_CARD` prüfen).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. Modelle und Provider verwalten
|
|||
|
|
|
|||
|
|
Übersicht unter **Settings → AI Providers / Models** in der UI, oder per API:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl http://127.0.0.1:5055/api/models | python3 -m json.tool # alle registrierten Modelle
|
|||
|
|
curl http://127.0.0.1:5055/api/models/defaults | python3 -m json.tool # aktuelle Standardmodelle
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Standardmodelle ändern
|
|||
|
|
|
|||
|
|
Sieben Rollen lassen sich unabhängig belegen: Chat, Transformation, großer Kontext, Embedding,
|
|||
|
|
Tools, Text-to-Speech, Speech-to-Text.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -X PUT http://127.0.0.1:5055/api/models/defaults \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-d '{"default_tools_model": "<model_id>"}'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Der Endpunkt aktualisiert nur die tatsächlich mitgeschickten Felder — nicht angegebene Felder
|
|||
|
|
bleiben unverändert, es muss also nicht der komplette Satz aller sieben Modelle mitgeschickt
|
|||
|
|
werden.
|
|||
|
|
|
|||
|
|
### Kostenübersicht der aktuell registrierten Modelle
|
|||
|
|
|
|||
|
|
| Modell | Provider | Kosten |
|
|||
|
|
|---|---|---|
|
|||
|
|
| `qwen3.5:27b` | Ollama (lokal) | 0 € (Standard für Chat/Tools/großer Kontext) |
|
|||
|
|
| `nomic-embed-text` | Ollama (lokal) | 0 € (Standard-Embedding) |
|
|||
|
|
| `qwen3-coder-30b-128k` | Ollama (lokal) | 0 € (optional, für Coding-Aufgaben) |
|
|||
|
|
| Chatterbox TTS / faster-whisper | lokal | 0 € |
|
|||
|
|
| `anthropic/claude-sonnet-5` | OpenRouter | ~2$/10$ pro Mio. Tokens (Prompt/Antwort) |
|
|||
|
|
| `qwen/qwen3-max` | OpenRouter | ~0,78$/3,90$ pro Mio. Tokens — günstigere Cloud-Alternative |
|
|||
|
|
| `google/gemini-3.5-flash` | OpenRouter | ~1,50$/9$ pro Mio. Tokens — 1M Tokens Kontext |
|
|||
|
|
|
|||
|
|
Weitere OpenRouter-Modelle lassen sich jederzeit über `POST /api/models` registrieren
|
|||
|
|
(`provider: "openrouter"`) — aktuelle Preise: `https://openrouter.ai/api/v1/models`.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Dienste starten/stoppen
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Open Notebook (Docker)
|
|||
|
|
docker compose up -d
|
|||
|
|
docker compose down
|
|||
|
|
|
|||
|
|
# TTS/STT (lokale Hintergrundprozesse, nicht in Docker)
|
|||
|
|
./scripts/start_services.sh
|
|||
|
|
pkill -f "python tts_server.py"
|
|||
|
|
pkill -f "python stt_server.py"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Ollama selbst läuft als systemd-Dienst und muss normalerweise nicht manuell verwaltet werden:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
systemctl status ollama
|
|||
|
|
ollama ps # aktuell geladene Modelle + GPU/CPU-Verteilung
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. Troubleshooting
|
|||
|
|
|
|||
|
|
### „Chat gibt keine Antwort" (leere Antwort, kein Fehler)
|
|||
|
|
|
|||
|
|
Meist ein zu kleiner Kontext (`num_ctx`) am Ollama-Chat-Credential — siehe README, Abschnitt 2.6.
|
|||
|
|
Prüfen:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
curl -s http://127.0.0.1:5055/api/credentials | python3 -c "
|
|||
|
|
import json,sys
|
|||
|
|
for c in json.load(sys.stdin):
|
|||
|
|
if c['provider']=='ollama': print(c['name'], c['num_ctx'])"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Sollte `98304` (oder höher, dann ggf. auf GPU-Auslastung achten) zeigen, nicht `None`/`null`.
|
|||
|
|
|
|||
|
|
### Quelle hängt beim Verarbeiten / Einbetten fest (Endlos-Retry)
|
|||
|
|
|
|||
|
|
Meist Ressourcen-Engpass beim Embedding-Modell (GPU voll, Modell läuft teilweise auf CPU,
|
|||
|
|
Timeout). Prüfen:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
ollama ps # PROCESSOR-Spalte: sollte "100% GPU" zeigen, nicht "xx%/yy% CPU/GPU"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Falls CPU-Anteil: Embedding-Modell ist zu groß für den freien GPU-Speicher. Standardmäßig ist
|
|||
|
|
hier das kleine `nomic-embed-text` (274 MB) konfiguriert, das läuft normalerweise problemlos
|
|||
|
|
komplett auf der GPU.
|
|||
|
|
|
|||
|
|
### Antwort dauert sehr lange (mehrere Minuten)
|
|||
|
|
|
|||
|
|
Meist normal bei „vollständiger Inhalt"-Modus auf langen Dokumenten (siehe Abschnitt 3) — das
|
|||
|
|
Sprachmodell muss den kompletten Text lesen. Für Detailfragen auf lange Sicht besser die
|
|||
|
|
Such-/Ask-Funktion oder „nur Erkenntnisse" nach einer Zusammenfassung nutzen.
|
|||
|
|
|
|||
|
|
### TTS/STT vom Container aus nicht erreichbar
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker compose exec open_notebook curl -sf http://host.docker.internal:8901/health
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Bei Timeout: `ufw`-Regeln fehlen (siehe README 2.4) oder die Server laufen nicht
|
|||
|
|
(`./scripts/start_services.sh`).
|
|||
|
|
|
|||
|
|
### Podcast-Profil zeigt „Einrichtung erforderlich"
|
|||
|
|
|
|||
|
|
Das Episode- oder Sprecherprofil verweist auf ein Modell ohne konfiguriertes Credential
|
|||
|
|
(z. B. nach einem Reset auf die mitgelieferten OpenAI-Standardprofile). Modell-IDs über
|
|||
|
|
`PUT /api/episode-profiles/{id}` (`outline_llm`, `transcript_llm`) bzw.
|
|||
|
|
`PUT /api/speaker-profiles/{id}` (`voice_model`) auf registrierte lokale/OpenRouter-Modelle
|
|||
|
|
umstellen — siehe `scripts/setup_models.sh` für die IDs der Standardmodelle.
|
|||
|
|
|
|||
|
|
### Weitere technische Details
|
|||
|
|
|
|||
|
|
Siehe [`CLAUDE.md`](CLAUDE.md) — dort stehen alle bisher aufgetretenen Probleme mit exakter
|
|||
|
|
Ursache (Codestellen, Bibliotheks-Bugs) dokumentiert.
|