Add README.md, BEDIENUNGSANLEITUNG.md, and setup/start scripts
README.md gives the precise, reproducible install path (tested the two
scripts against the live instance - both idempotent, correctly detect
already-registered credentials/models). BEDIENUNGSANLEITUNG.md covers daily
usage: notebooks/sources, the three chat context modes (and why "nur
Erkenntnisse" needs a transformation run first), podcasts, voice cloning,
and troubleshooting for the issues actually hit during setup (num_ctx
truncation, embedding GPU contention, ufw).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 23:50:58 +02:00
# 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 )
2026-07-11 00:59:06 +02:00
8. [Suche über Chunks (Search/Ask) ](#8-suche-über-chunks-searchask )
2026-07-11 01:02:17 +02:00
9. [Die API in eigenen Programmen nutzen ](#9-die-api-in-eigenen-programmen-nutzen )
10. [Troubleshooting ](#10-troubleshooting )
Add README.md, BEDIENUNGSANLEITUNG.md, and setup/start scripts
README.md gives the precise, reproducible install path (tested the two
scripts against the live instance - both idempotent, correctly detect
already-registered credentials/models). BEDIENUNGSANLEITUNG.md covers daily
usage: notebooks/sources, the three chat context modes (and why "nur
Erkenntnisse" needs a transformation run first), podcasts, voice cloning,
and troubleshooting for the issues actually hit during setup (num_ctx
truncation, embedding GPU contention, ufw).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 23:50:58 +02:00
---
## 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 **Datei größ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
```
---
2026-07-11 00:59:06 +02:00
## 8. Suche über Chunks (Search/Ask)
Jedes Dokument wird beim Hochladen automatisch in feste, überlappende Textabschnitte
("Chunks", ~400 Tokens) zerlegt und eingebettet — **nicht ** kapitelweise, sondern rein
größenbasiert (siehe Abschnitt 2). Um gezielt in diesen Chunks zu suchen, gibt es zwei
API-Endpunkte (in der UI vermutlich unter einem eigenen Menüpunkt wie „Search"/„Ask" mit
Lupen-Symbol, getrennt von „Mit Notebook chatten" — die genaue Beschriftung war ohne
Browser-Zugriff nicht zu verifizieren):
### Einfache Suche — schnell, liefert Roh-Textstellen
```bash
curl -s -X POST http://127.0.0.1:5055/api/search \
-H "Content-Type: application/json" \
-d '{"query": "Suchbegriff", "type": "vector", "limit": 5}'
```
Liefert die ähnlichsten Chunks per Embedding-Vergleich samt Ähnlichkeits-Score (0– 1), ohne
KI-Interpretation — am schnellsten, aber du musst die Antwort selbst zusammensetzen.
### „Ask" — durchsuchen und direkt beantworten lassen
Die smartere Variante: Die KI zerlegt die Frage selbst in mehrere gezielte Suchanfragen,
durchsucht die Chunks für jede getrennt und fasst alles zu einer einzigen, mit
Quellenverweisen (`[source:...]` ) belegten Antwort zusammen. Getestet mit „Wie kam Wallenstein
ums Leben?" — Ergebnis war eine vollständige, korrekt zitierte Antwort in ca. 3 Minuten
(mehrere LLM-Aufrufe hintereinander: Suchstrategie → Einzelantworten → Zusammenfassung).
```bash
MODEL_ID=$(curl -s http://127.0.0.1:5055/api/models/defaults | python3 -c "import json,sys; print(json.load(sys.stdin)['default_chat_model'])")
curl -N -X POST http://127.0.0.1:5055/api/search/ask \
-H "Content-Type: application/json" \
-d "{\"question\": \"Deine Frage\", \"strategy_model\": \"$MODEL_ID\", \"answer_model\": \"$MODEL_ID\", \"final_answer_model\": \"$MODEL_ID\"}"
```
Antwort kommt als Server-Sent-Events-Stream (`data: {...}` -Zeilen, kein einzelnes JSON-Objekt);
das letzte `"type": "complete"` -Event enthält die finale Antwort im Feld `final_answer` .
**Wann was nutzen:** Für gezielte Detailfragen über lange/viele Quellen ist „Ask" meist
treffsicherer und dabei noch schneller als der „vollständiger Inhalt"-Chat-Modus (Abschnitt 3),
weil nur die relevanten Chunks statt des ganzen Dokuments verarbeitet werden.
---
2026-07-11 01:02:17 +02:00
## 9. Die API in eigenen Programmen nutzen
Die REST-API ist eine ganz normale JSON-über-HTTP-API **ohne Authentifizierung ** — kein API-Key
nötig, da nur `127.0.0.1` gebunden (jeder lokale Prozess auf diesem Rechner hat Zugriff, aber
niemand aus dem Netzwerk). Funktioniert mit jeder Sprache, die HTTP kann.
**Bester Startpunkt:** `http://127.0.0.1:5055/docs` — interaktive Swagger-UI mit allen
Endpunkten, Schemas und einer „Try it out"-Funktion zum direkten Ausprobieren im Browser.
Rohes OpenAPI-Schema: `http://127.0.0.1:5055/openapi.json` .
### Mit curl
```bash
# Notebooks auflisten
curl -s http://127.0.0.1:5055/api/notebooks | python3 -m json.tool
# Neues Notebook anlegen
curl -s -X POST http://127.0.0.1:5055/api/notebooks \
-H "Content-Type: application/json" \
-d '{"name": "Mein Notebook", "description": "..."}'
# Text-Quelle hinzufügen (multipart, nicht JSON)
curl -s -X POST http://127.0.0.1:5055/api/sources \
-F "type=text" -F "notebook_id=notebook:xxx" -F "title=..." \
-F "content=..." -F "embed=true"
# Chat-Session erstellen + Nachricht senden
curl -s -X POST http://127.0.0.1:5055/api/chat/sessions \
-H "Content-Type: application/json" -d '{"notebook_id": "notebook:xxx"}'
curl -s -X POST http://127.0.0.1:5055/api/chat/execute \
-H "Content-Type: application/json" \
-d '{"session_id": "chat_session:xxx", "message": "...", "context": {}}'
```
Weitere Beispiele (Quellen-Insights, Podcast-Generierung, Modell-/Provider-Verwaltung,
Chunk-Suche) stehen bereits in den jeweiligen Abschnitten dieser Anleitung.
### Aus Python
```python
import requests
BASE = "http://127.0.0.1:5055/api"
notebooks = requests.get(f"{BASE}/notebooks").json()
session = requests.post(f"{BASE}/chat/sessions",
json={"notebook_id": notebooks[0]["id"]}).json()
answer = requests.post(f"{BASE}/chat/execute", json={
"session_id": session["id"],
"message": "Wovon handelt das Buch?",
"context": {},
}).json()
print(answer["messages"][-1]["content"])
```
Genauso mit JavaScript (`fetch` ), Go, oder jeder anderen Sprache — nichts Open-Notebook-
Spezifisches nötig, kein SDK erforderlich.
---
## 10. Troubleshooting
Add README.md, BEDIENUNGSANLEITUNG.md, and setup/start scripts
README.md gives the precise, reproducible install path (tested the two
scripts against the live instance - both idempotent, correctly detect
already-registered credentials/models). BEDIENUNGSANLEITUNG.md covers daily
usage: notebooks/sources, the three chat context modes (and why "nur
Erkenntnisse" needs a transformation run first), podcasts, voice cloning,
and troubleshooting for the issues actually hit during setup (num_ctx
truncation, embedding GPU contention, ufw).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 23:50:58 +02:00
### „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.
2026-07-11 00:37:09 +02:00
### Podcast wird auf Englisch statt Deutsch erzeugt
Das verwendete Episode-Profil hat kein `language` -Feld gesetzt — ohne Angabe generiert das
Sprachmodell standardmäßig auf Englisch, unabhängig von der Sprache der Quelle. Prüfen und
korrigieren:
```bash
curl -s http://127.0.0.1:5055/api/episode-profiles | python3 -c \
"import json,sys; [print(p['name'], p['language']) for p in json.load(sys.stdin)]"
```
Fehlt `de` , per `PUT /api/episode-profiles/{id}` (vollständiger Body nötig, siehe oben)
`"language": "de"` ergänzen. Die drei mitgelieferten Profile (`business_analysis` ,
`solo_expert` , `tech_discussion` ) sind bereits korrigiert; bei neu angelegten eigenen Profilen
selbst daran denken.
Add README.md, BEDIENUNGSANLEITUNG.md, and setup/start scripts
README.md gives the precise, reproducible install path (tested the two
scripts against the live instance - both idempotent, correctly detect
already-registered credentials/models). BEDIENUNGSANLEITUNG.md covers daily
usage: notebooks/sources, the three chat context modes (and why "nur
Erkenntnisse" needs a transformation run first), podcasts, voice cloning,
and troubleshooting for the issues actually hit during setup (num_ctx
truncation, embedding GPU contention, ufw).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 23:50:58 +02:00
### Weitere technische Details
Siehe [`CLAUDE.md` ](CLAUDE.md ) — dort stehen alle bisher aufgetretenen Probleme mit exakter
Ursache (Codestellen, Bibliotheks-Bugs) dokumentiert.