DEval ist eine schlanke Weboberfläche vor RAGFlow. Sie macht die in RAGFlow verwalteten Wissensdatenbanken im Browser per RAG chatbar und ergänzt Uploads, Verarbeitungsstatus, GraphRAG und deterministische PDF-Quellen. PyMuPDF extrahiert die Dokumente lokal, SQLite speichert die Provenienz und RAGFlow übernimmt Parsing, Retrieval, GraphRAG und Antwortgenerierung.
Die LLM-Inferenz läuft in diesem Setup nicht lokal über Ollama, sondern über einen in RAGFlow konfigurierten externen/OpenAI-kompatiblen Provider. Nur die Embeddings laufen standardmäßig lokal im offiziellen RAGFlow-TEI-Container.
DEval speichert Chatverläufe nicht serverseitig. Jeder Chat, das ausgewählte Modell und die Nachrichten werden ausschließlich im Browser gespeichert. Für eine neue Antwort übergibt der Browser den bisherigen Verlauf jeweils vollständig an das DEval-Backend; DEval leitet ihn stateless an RAGFlow weiter, ohne eine RAGFlow-Session oder Chat-Historie anzulegen.
RAGFlow benötigt für seinen OpenAI-kompatiblen Endpunkt weiterhin ein technisches Chat-Assistant-Objekt. Dieses enthält nur die Verknüpfung von Wissensdatenbank, Modell und Prompt – nicht den Gesprächsverlauf. Die eigentlichen lokalen Chats bleiben im Browser und können dort getrennt verwaltet werden.
| DEval-Webchat | Eingebettete RAGFlow-Weboberfläche |
|---|---|
![]() |
![]() |
- Docker Desktop mit Docker Compose (mindestens Compose 2.26.1)
- Python 3.9–3.12
- Node.js und
pnpm - macOS/ARM: Docker muss
linux/amd64emulieren können - Für RAGFlow mindestens ca. 4 CPUs, 16 GB RAM und 50 GB freien Speicher
- Auf Linux:
vm.max_map_count >= 262144für Elasticsearch
Der offizielle RAGFlow-Stack ist ressourcenintensiv. Für einen ersten Start sollten keine weiteren großen Docker-Stacks laufen.
Im Repository-Root:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[test]'
cp .env.example .envDanach .env bearbeiten. Die wichtigsten Variablen sind:
# RAGFlow API, ohne /api/v1 – diesen Präfix ergänzt DEval selbst.
RAGFLOW_BASE_URL=http://127.0.0.1:9380
# Separater RAGFlow-API-Key, nicht der Key des externen LLM-Providers.
RAGFLOW_API_KEY=<RAGFLOW_API_KEY>
# Lokaler Scope der CLI und der Provenienz-Registry.
RAGFLOW_DATASET_NAME=deval-poc
# Embeddings: offizieller TEI-CPU-Service aus dem Docker-Stack.
RAGFLOW_EMBEDDING_MODEL=BAAI/bge-small-en-v1.5@Builtin
# Externes Chat-/GraphRAG-Modell. Der Wert muss exakt zu einem
# konfigurierten Chatmodell in RAGFlow passen.
RAGFLOW_LLM_MODEL=gpt-5.6-luna@codex@OpenAIRAGFLOW_API_KEY wird in RAGFlow erzeugt. Niemals einen externen OpenAI-/Anthropic-Key in Git, in die Frontend-Konfiguration oder in den Browser eintragen.
Die übrigen Variablen stehen vollständig in .env.example. Die wichtigsten optionalen Werte sind:
| Variable | Zweck | Standard |
|---|---|---|
RAGFLOW_CHUNK_METHOD |
RAGFlow-Parser | naive |
RAGFLOW_CHUNK_TOKEN_NUM |
Zielgröße der Chunks | 512 |
RAGFLOW_REGISTRY_PATH |
lokale SQLite-Provenienz | .data/registry.sqlite3 |
RAGFLOW_REQUEST_TIMEOUT |
HTTP-Timeout | 30 Sekunden |
RAGFLOW_PARSE_TIMEOUT |
Parsing-Timeout | 1800 Sekunden |
RAGFLOW_UPLOAD_CONCURRENCY |
parallele Dokumentverarbeitung pro Upload | 5 (maximal 5) |
RAGFLOW_GRAPH_TIMEOUT |
GraphRAG-Timeout | 1800 Sekunden |
RAGFLOW_CITATION_THRESHOLD |
Mindestscore für Text-Matching | 0.60 |
DEVAL_RAGFLOW_STATELESS_CHAT |
RAGFlow-Sessions/Verlauf deaktivieren | true |
RUN_LIVE_RAGFLOW_TESTS |
Live-Tests explizit aktivieren | false |
Die Compose-Dateien werden von scripts/ragflow-compose.sh aus dem offiziellen RAGFlow-Repository gestaged. Die erzeugte Docker-.env liegt unter .data/ und bleibt aus Git ausgeschlossen.
./scripts/ragflow-compose.sh verify
./scripts/ragflow-compose.sh up
./scripts/ragflow-compose.sh wait
./scripts/ragflow-compose.sh pswait wartet auf den echten RAGFlow-Readiness-Endpunkt und kann beim ersten Start mehrere Minuten dauern. Die normalen Lifecycle-Befehle sind:
./scripts/ragflow-compose.sh ps
./scripts/ragflow-compose.sh logs ragflow-cpu
./scripts/ragflow-compose.sh downdown entfernt keine persistenten Volumes. Niemals docker compose down -v verwenden, wenn die vorhandenen Dokumente und RAGFlow-Daten erhalten bleiben sollen.
Ollama ist für diesen Ablauf nicht erforderlich und wird nicht gestartet.
- RAGFlow im Browser öffnen: http://127.0.0.1
- Einloggen und Settings → Model providers öffnen.
- Einen externen Provider konfigurieren, zum Beispiel OpenAI:
- Instanzname:
codex - Base URL:
https://api.openai.com/v1oder die URL des eigenen OpenAI-kompatiblen Gateways - API-Key: der Key des externen LLM-Providers
- Chatmodelle: die tatsächlich verfügbaren Modell-IDs, z. B.
gpt-5.6-luna,gpt-5.6-sol,gpt-5.6-terra
- Instanzname:
- Für jedes Modell den Typ Chat aktivieren und die Provider-Konfiguration testen.
- Unter Avatar → API einen RAGFlow-API-Key erzeugen und als
RAGFLOW_API_KEYin der Root-.enveintragen. RAGFLOW_LLM_MODELauf den exakten von RAGFlow gelieferten Modellwert setzen. Dieser Wert wird für CLI und GraphRAG verwendet. Für den Webchat ist keine separate Modellliste nötig: DEval zeigt automatisch alle Chatmodelle an, die der aktuelle RAGFlow-Tenant überGET /api/v1/models?type=chatbereitstellt.
Der Modellwert ist eine RAGFlow-Referenz auf Modell, Provider-Instanz und Factory. Wenn das Gateway einen anderen Instanznamen oder eine andere Factory verwendet, wird das Modell automatisch mit der aktuellen RAGFlow-Konfiguration übernommen. RAGFLOW_API_KEY und der externe Provider-Key sind zwei verschiedene Zugangsdaten.
Der TEI-Service für BAAI/bge-small-en-v1.5 ist Teil des offiziellen Compose-Stacks und stellt nur Embeddings bereit. Er ersetzt keine Chat-/GraphRAG-Inferenz.
In einem zweiten Terminal, ebenfalls im Repository-Root:
. .venv/bin/activate
.venv/bin/deval-webchat --host 127.0.0.1 --port 8790Das Backend spricht mit RAGFlow und stellt die lokale Web-API bereit. Es läuft absichtlich getrennt von RAGFlow.
In einem dritten Terminal:
cd frontend
pnpm install
DEVAL_API_URL=http://127.0.0.1:8790 pnpm dev --host 127.0.0.1Danach im Browser öffnen:
Falls pnpm dev wegen einer lokalen pnpm-Build-Freigabe mit ERR_PNPM_IGNORED_BUILDS abbricht, den Vite-Prozess direkt starten:
cd frontend
DEVAL_API_URL=http://127.0.0.1:8790 ./node_modules/.bin/vite --host 127.0.0.1Die Vite-Variable DEVAL_API_URL ist wichtig, wenn das Backend auf Port 8790 läuft. Ohne sie verwendet der Vite-Proxy den Fallback-Port 8787. Die Ansicht RAGFlow-Backend im oberen Umschalter bindet standardmäßig http://127.0.0.1 ein; eine andere RAGFlow-Weboberfläche lässt sich über VITE_RAGFLOW_WEB_URL setzen.
| Dienst | URL | Verwendung |
|---|---|---|
| DEval-Frontend | http://127.0.0.1:5173 | Browser-Oberfläche |
| DEval-Backend | http://127.0.0.1:8790 | lokale API für das Frontend |
| RAGFlow-Weboberfläche | http://127.0.0.1 | Login, Provider, Dataset-UI |
| RAGFlow-API | http://127.0.0.1:9380 | Adapter und CLI |
| RAGFlow-Admin-Server | http://127.0.0.1:9381 | Admin-/Health-Endpunkte, keine normale UI |
Schnelle Erreichbarkeitstests:
curl -i http://127.0.0.1:9380/api/v1/system/healthz
curl -i http://127.0.0.1:9381/api/v1/admin/ping
curl -i http://127.0.0.1:8790/api/healthFür einen Server mit öffentlichem HTTPS sollten nur Nginx-Ports erreichbar sein. RAGFlow und das DEval-Backend bleiben an 127.0.0.1 gebunden. Der RAGFlow-Stack reserviert standardmäßig Host-Port 80; wenn Nginx selbst Port 80 benötigt, die internen Webports beim Start verschieben:
export RAGFLOW_WEB_HTTP_PORT=127.0.0.1:8080
export RAGFLOW_WEB_HTTPS_PORT=127.0.0.1:8443
./scripts/ragflow-compose.sh verify
./scripts/ragflow-compose.sh up
./scripts/ragflow-compose.sh waitFür einen lokalen Reverse-Proxy-Test ist Nginx bereits als Service im Compose-Overlay enthalten. Dafür die optionalen Portüberschreibungen aus dem Produktionsbeispiel nicht setzen bzw. entfernen; lokal bleibt RAGFlow auf 127.0.0.1:80. Zuerst das Frontend mit der öffentlichen Proxy-URL bauen:
unset RAGFLOW_WEB_HTTP_PORT RAGFLOW_WEB_HTTPS_PORT
cd frontend
pnpm install
VITE_RAGFLOW_WEB_URL=http://ragflow.localhost:8088 pnpm build
cd ..
./scripts/ragflow-compose.sh verify
./scripts/ragflow-compose.sh up
./scripts/ragflow-compose.sh waitDanach http://deval.localhost:8088 öffnen. Das Frontend und der eingebettete RAGFlow-Link laufen dann beide über den Nginx-Container; RAGFlow selbst bleibt intern auf 127.0.0.1:80. Die lokale Nginx-Konfiguration liegt unter deploy/nginx/local.conf.
Für einen Produktivbetrieb wird das Frontend ebenfalls statisch gebaut. DEVAL_API_URL wird dabei nicht benötigt, weil Nginx /api/ unter derselben Origin weiterleitet:
VITE_RAGFLOW_WEB_URL=https://ragflow.example.org pnpm buildEine Vorlage für zwei TLS-Virtual-Hosts liegt unter deploy/nginx/deval-ragflow.conf.example. Sie verwendet deval.example.org für DEval und ragflow.example.org für die eingebettete RAGFlow-Weboberfläche:
server {
listen 443 ssl;
server_name deval.example.org;
# ssl_certificate ...;
# ssl_certificate_key ...;
root /srv/deval/frontend/dist;
index index.html;
client_max_body_size 64m;
location /api/ {
# Kein abschließender Slash: /api/... bleibt beim Backend erhalten.
proxy_pass http://127.0.0.1:8790;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 1800s;
}
location / {
try_files $uri $uri/ /index.html;
}
}
server {
listen 443 ssl;
server_name ragflow.example.org;
# ssl_certificate ...;
# ssl_certificate_key ...;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 1800s;
}
}Danach das DEval-Backend auf 127.0.0.1:8790 starten und https://deval.example.org öffnen. Die Ports 8790, 9380 und 9381 sollten nicht öffentlich exponiert werden. Für eine rein lokale Installation bleiben die oben dokumentierten Ports 5173, 8790 und 9380 ausreichend.
- Frontend unter http://127.0.0.1:5173 öffnen.
- Eine Sammlung anlegen oder auswählen.
- Neben der Sammlung ein oder mehrere PDFs hochladen.
- Warten, bis die Dokumente verarbeitet sind. Der Chat kann danach bereits mit den verarbeiteten Dokumenten verwendet werden; ein laufender GraphRAG-Aufbau läuft unabhängig im Hintergrund.
- Ein konfiguriertes externes Chatmodell auswählen.
- Eine Frage stellen. Die Quellen erscheinen neben den relevanten Aussagen.
- Direkt über dem Eingabefeld einen neuen Chat anlegen oder einen vorhandenen Browser-Chat über Startdatum und erste Frage auswählen. Pro Sammlung bleiben die zehn jüngsten Chats erhalten; der ausgewählte Chat lässt sich über
×löschen. - Dokumente können in der aufklappbaren Sammlung gelöscht werden. Danach wird GraphRAG erneut aktualisiert.
- Eine ganze Sammlung lässt sich über das
×neben ihrem Namen löschen. Dabei werden das RAGFlow-Dataset und die lokale Provenienz nach einer Bestätigung entfernt. - Unter Suche in lassen sich Deutsch und English für die sprachübergreifende RAGFlow-Suche je Browser-Chat an- oder abwählen.
- Über Erweiterte Einstellungen neben dem Eingabefeld lässt sich pro Sammlung das Trefferlimit wählen: 5 bis 20 maximale Dokumentenergebnisse je Frage, in Einerschritten. Der Standard ist 5.
Die Sammlung ist im linken Bereich als Ordner dargestellt. Dokumente bleiben dort sichtbar und auswählbar. Chatverläufe und Modellwahl bleiben je Sammlung/Chat ausschließlich im Browser. Der Dateiname im Quellenbereich öffnet das vollständige PDF in einem neuen Tab; die Seitenvorschau und Provenienz bleiben lokal.
PDF im Browser
-> DEval-Backend
-> lokale PyMuPDF-Extraktion + SHA-256 + SQLite-Provenienz
-> RAGFlow-Dataset und deterministisches Remote-Dokument
-> RAGFlow-Parsing / Chunking
-> GraphRAG-Aufbau nach erfolgreichem Parsing
-> stateless Chatantwort über RAGFlows OpenAI-kompatiblen Endpoint
-> separater Retrieval-Aufruf für deterministische Quellen
Wichtige Eigenschaften:
document_uidist der SHA-256-Hash der PDF-Bytes.- RAGFlow erhält den ursprünglichen Upload-Dateinamen;
version_uidbleibt in den Metadaten die technische Identität für idempotente Wiederholungen. - Die lokale Registry liegt in
.data/registry.sqlite3und enthält Provenienz, Seiten, Absätze, Bboxes und RAGFlow-Mappings. - Uploads laufen asynchron; bis zu
RAGFLOW_UPLOAD_CONCURRENCY(Standard: 5) Dokumente werden pro Job parallel an RAGFlow übergeben. Das Frontend fragt Job- und GraphRAG-Status regelmäßig ab. - Malformed, verschlüsselte, leere und reine Scan-PDFs werden lokal registriert, aber nicht automatisch hochgeladen.
- Mixed-PDFs benötigen im CLI
--allow-mixed; im Webchat wird die Verarbeitung entsprechend angezeigt. - Zitate werden nicht vom LLM geraten: Die Chatantwort und die Quellenauflösung sind getrennt.
CitationResolverordnet RAGFlow-Referenzen deterministisch lokalen Seiten und Absätzen zu. - Der Webchat prüft die GraphRAG-Bereitschaft. Standardmäßig erzeugt er keine RAGFlow-Session und sendet den lokalen Verlauf über
/api/v1/openai/{chat_id}/chat/completions;DEVAL_RAGFLOW_STATELESS_CHAT=falseschaltet testweise auf den alten Session-Flow zurück. Ein technisches RAGFlow-Chat-Assistant-Objekt kann dabei vorhanden sein, enthält aber keine Chat-Nachrichten. - Die normale Quellenauflösung verwendet weiterhin einen separaten Retrieval-Aufruf ohne KG-Nutzung. Im CLI muss KG-Nutzung mit
query --use-kgexplizit angefordert werden. - Das Trefferlimit verändert nur die Anzahl der pro Frage abgerufenen Kontextausschnitte, nicht das RAGFlow-Chunking beim Upload. Mehr Treffer können die Abdeckung verbessern, erhöhen aber Kontextgröße, Latenz und Modellkosten.
Alle CLI-Befehle werden aus dem Repository-Root mit aktivierter virtueller Umgebung ausgeführt:
. .venv/bin/activate
# Konfiguration, RAGFlow-Health und SQLite prüfen
python -m deval_ragflow doctor
# PDF lokal prüfen und Provenienz extrahieren
python -m deval_ragflow extract ./data/input/datei.pdf
# PDF ingestieren, parsen und Status abwarten
python -m deval_ragflow ingest ./data/input/datei.pdf --allow-mixed --timeout 1800
# Parsingstatus einer lokalen Version prüfen
python -m deval_ragflow status VERSION_UID
# Retrieval mit deterministischen Quellen
python -m deval_ragflow query "Welche zentralen Ergebnisse nennt die Studie?"
# Retrieval mit expliziter GraphRAG/KG-Nutzung
python -m deval_ragflow query "Welche Entitäten hängen zusammen?" --use-kg
# Chatantwort über den externen RAGFlow-LLM-Provider
python -m deval_ragflow ask "Welche zentralen Ergebnisse nennt die Studie?" --timeout 360
# Antwort maschinenlesbar ausgeben
python -m deval_ragflow ask "Welche zentralen Ergebnisse nennt die Studie?" --timeout 360 --json
# GraphRAG manuell starten bzw. inspizieren
python -m deval_ragflow graph --timeout 3600
# Laufende Verarbeitung abbrechen
python -m deval_ragflow cancel VERSION_UIDDie beiden Beispiel-PDFs liegen in data/input/. Bei den mitgelieferten Summary-PDFs ist --allow-mixed erforderlich.
Es gibt zwei verschiedene .env-Dateien:
- Root
.env: DEval-Konfiguration, RAGFlow-URL, RAGFlow-API-Key und Modellreferenzen. .data/ragflow-v0.27.2/docker/.env: automatisch erzeugte Docker-Runtime-Werte für MySQL, Elasticsearch, MinIO, Redis usw. Diese Datei ist ignoriert und darf nicht committed werden.
Persistente RAGFlow-Daten liegen in Docker-Volumes, unter anderem für MySQL, Elasticsearch, MinIO und Redis. Die Compose-Hülle entfernt diese Volumes nicht.
Ein explizit von diesem PoC besessenes Test-Dataset kann geschützt gelöscht werden:
python -m deval_ragflow reset-test-data \
--dataset-id REMOTE_DATASET_ID \
--confirm 'DELETE DEVAL TEST DATA'Die lokale Registry wird erst nach erfolgreicher Remote-Löschung bereinigt. Beliebige Dataset-IDs werden abgewiesen.
Bei einem MySQL-Fehler Access denied for user 'root' liegt fast immer ein Passwortunterschied zwischen dem bereits initialisierten Docker-Volume und der aktuellen Docker-.env vor. Nicht down -v ausführen. Erst ./scripts/ragflow-compose.sh verify prüfen; die Hülle stellt sicher, dass MYSQL_PASSWORD und MYSQL_ROOT_PASSWORD bei neuen Installationen gleich erzeugt werden.
. .venv/bin/activate
python -m compileall -q src tests
python -m pytest -q
# Live-Test nur explizit aktivieren; er verwendet echte PDFs und RAGFlow.
RUN_LIVE_RAGFLOW_TESTS=true python -m pytest -q -rs tests/test_live_ragflow.pyDer Live-Test benötigt einen gültigen RAGFLOW_API_KEY, ein konfiguriertes Embedding-Modell und ein konfiguriertes externes RAGFLOW_LLM_MODEL. Er kann echte Remote-Dokumente anlegen und Provider-/Docker-Ressourcen verbrauchen.
- ARCHITECTURE.md – technische Grenzen und Datenfluss
- docs/REPRODUKTION.md – ältere ausführliche Reproduktionsnotizen
- docs/DECISIONS.md – API-/Release-Entscheidungen
- TESTPLAN.md – Testumfang und Live-Test-Regeln
- frontend/README.md – kurzer Frontend-Hinweis

