Files
Effi/DIAGNOSTIC-KREUZBERG.md

11 KiB

Reprise du diagnostique - Intégration Kreuzberg/OpenWebUI

Contexte

Migration de effi-ocr vers Kreuzberg pour l'extraction de documents dans OpenWebUI. Kreuzberg fonctionne, mais OpenWebUI ne l'appelle jamais pour extraire les documents.


Architecture actuelle

FOLZOCORP (192.168.1.11) - AMD Ryzen 7 5800X3D
├── effi-stt:8200 (Whisper STT)
├── openedai-speech:8100 (TTS)
├── comfyui:8188
└── kreuzberg:8300 ← FONCTIONNE

EFFI-SERVER (192.168.1.27) - Intel J5040
├── open-webui:3000 ← BUG ICI
├── qdrant:6333
├── n8n:5678
└── watchtower

Configuration actuelle

Kreuzberg (sur folzocorp) - DOCKER COMPOSE

# /home/folzo/kreuzberg/docker-compose.yml
services:
  kreuzberg:
    image: ghcr.io/kreuzberg-dev/kreuzberg:latest
    container_name: kreuzberg
    restart: unless-stopped
    ports:
      - "8300:8000"
    command: ["serve", "--host", "0.0.0.0", "--port", "8000"]
    environment:
      - KREUZBERG_MAX_UPLOAD_SIZE_MB=100
      - RUST_LOG=info
    volumes:
      - kreuzberg-cache:/app/.kreuzberg
    healthcheck:
      test: ["CMD", "kreuzberg", "version"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

volumes:
  kreuzberg-cache:

Statut: ✓ FONCTIONNE

curl http://192.168.1.11:8300/health
# {"status":"healthy","version":"4.8.2","plugins":{"ocr_backends_count":3,...}}

OpenWebUI (sur effi-server) - DOCKER COMPOSE

# ~/effi/docker-compose.yml
services:
  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    environment:
      - OLLAMA_BASE_URL=http://host.docker.internal:3011
      - WEBUI_SECRET_KEY=${WEBUI_SECRET_KEY}
      - VECTOR_DB=qdrant
      - QDRANT_URI=http://qdrant:6333
      - DEFAULT_LOCALE=fr-FR
      - ENABLE_MEMORIES=true
      - AUDIO_STT_ENGINE=openai
      - AUDIO_STT_OPENAI_API_BASE_URL=http://192.168.1.11:8200/v1
      - AUDIO_STT_OPENAI_API_KEY=anything
      - AUDIO_STT_MODEL=Systran/faster-whisper-large-v3
      # Kreuzberg
      - CONTENT_EXTRACTION_ENGINE=docling
      - DOCLING_SERVER_URL=http://192.168.1.11:8300
      - FETCH_URL_MAX_CONTENT_LENGTH=1000000
      - WEB_FETCH_MAX_CONTENT_LENGTH=1000000
    # ... reste de la config

Problème principal

Bug OpenWebUI v0.8.12

AttributeError: Config key 'FETCH_URL_MAX_CONTENT_LENGTH' not found
POST /api/v1/retrieval/config/update HTTP/1.1" 500

Impact:

  • La configuration Documents dans Admin Panel ne peut PAS être sauvegardée
  • OpenWebUI n'appelle JAMAIS Kreuzberg pour extraire les documents
  • Les PDF sont traités par PyPDF interne (qui ne fait pas d'OCR sur les images)

Preuve:

  • Les logs OpenWebUI ne montrent AUCUNE requête HTTP vers 192.168.1.11:8300
  • Les logs Kreuzberg ne reçoivent AUCUNE requête d'OpenWebUI

Tests effectués

1. Kreuzberg fonctionne

# Sur folzocorp
curl -X POST -F "files=@test.txt" http://localhost:8300/v1/convert/file
# {"document":{"md_content":"Test..."},"status":"success"}

curl -X POST -F "files=@test.txt" http://localhost:8300/extract
# [{"content":"Test...","mime_type":"text/plain",...}]

2. OpenWebUI peut contacter Kreuzberg

# Sur effi-server
docker exec open-webui curl http://192.168.1.11:8300/health
# {"status":"healthy"...}

3. Variables d'environnement présentes

docker exec open-webui env | grep -E "CONTENT|DOCLING|FETCH"
# CONTENT_EXTRACTION_ENGINE=docling
# DOCLING_SERVER_URL=http://192.168.1.11:8300

4. Configuration Admin Panel

Dans Admin Panel → Settings → Documents:

  • Content Extraction Engine: Docling
  • Docling Server URL: http://192.168.1.11:8300

Mais la sauvegarde échoue avec erreur 500.


Fichiers disponibles

PDFs uploadés dans OpenWebUI

/app/backend/data/uploads/9af3d665-998b-4577-b893-340cb1c28385_2018_Poltzer_AlgorithmeIntuition.pdf
/app/backend/data/uploads/a422d6a1-121e-4482-a2b6-0a57435bbd76_2018_Poltzer_AlgorithmeIntuition.pdf
# ... etc

Logs pertinents

OpenWebUI lors d'un upload de document

2026-04-10 19:19:45.222 | INFO | open_webui.config:save - Saving 'CONTENT_EXTRACTION_ENGINE' to the database
2026-04-10 19:19:45.375 | INFO | open_webui.config:save - Saving 'DOCLING_SERVER_URL' to the database
...
2026-04-10 19:19:46.303 | ERROR | AttributeError: Config key 'FETCH_URL_MAX_CONTENT_LENGTH' not found
2026-04-10 19:19:46.303 | POST /api/v1/retrieval/config/update HTTP/1.1" 500

AUCUNE requête vers Kreuzberg n'apparaît dans les logs.

Kreuzberg

# Démarrage OK
[INFO] OCR backends registered: [vlm, tesseract, paddle-ocr]
[INFO] Document extractors registered: 41 extractors

# MAIS AUCUNE REQUÊTE REÇUE D'OPENWEBUI

Tentatives de résolution

  1. Ajout de variables FETCH_URL_MAX_CONTENT_LENGTH → Bug persiste
  2. Mise à jour OpenWebUI (docker compose pull open-webui) → Bug persiste
  3. Tool manuel pour Kreuzberg → Ne peut pas accéder aux fichiers uploadés
  4. Changement d'URL (avec/sans /v1/convert/file) → Même problème

SOLUTION - 10 Avril 2026

Corrections appliquées

Trois patches ont été nécessaires pour faire fonctionner OpenWebUI + Kreuzberg :


Patch 1: Bug FETCH_URL_MAX_CONTENT_LENGTH (v0.8.12)

Fichier: backend/open_webui/routers/retrieval.py

Problème: Le code utilise FETCH_URL_MAX_CONTENT_LENGTH mais la clé correcta est WEB_FETCH_MAX_CONTENT_LENGTH

Correction:

sed -i 's/FETCH_URL_MAX_CONTENT_LENGTH/WEB_FETCH_MAX_CONTENT_LENGTH/g' /app/backend/open_webui/routers/retrieval.py

Patch 2: Mode OCR pour images (retrieval/loaders/main.py)

Fichier: backend/open_webui/retrieval/loaders/main.py

Problème: image_export_mode=placeholder retourne juste des références d'images, pas le texte OCRisé

Correction:

# Avant:
'data={'image_export_mode': 'placeholder', **self.params}'

# Après:
'data={'image_export_mode': 'inline', 'ocr': 'true', **self.params}'

Patch 3: Validation des types MIME (routers/files.py)

Fichier: backend/open_webui/routers/files.py

Problème: Les images ne sont traitées que pour external engine, pas pour docling

Correction:

# Avant:
elif (not content_type.startswith(('image/', 'video/'))) or (
    request.app.state.config.CONTENT_EXTRACTION_ENGINE == 'external'
):

# Après:
elif (not content_type.startswith(('image/', 'video/'))) or (
    request.app.state.config.CONTENT_EXTRACTION_ENGINE in ('external', 'docling')
):

Application des patches

# 1. Patcher retrieval.py (bug typo)
docker exec open-webui sed -i 's/FETCH_URL_MAX_CONTENT_LENGTH/WEB_FETCH_MAX_CONTENT_LENGTH/g' /app/backend/open_webui/routers/retrieval.py

# 2. Patcher main.py (mode OCR)
docker exec open-webui sed -i "s/'image_export_mode': 'placeholder'/'image_export_mode': 'inline', 'ocr': 'true'/" /app/backend/open_webui/retrieval/loaders/main.py

# 3. Patcher files.py (validation MIME)
docker exec open-webui sed -i "s/request.app.state.config.CONTENT_EXTRACTION_ENGINE == 'external'/request.app.state.config.CONTENT_EXTRACTION_ENGINE in ('external', 'docling')/" /app/backend/open_webui/routers/files.py

# 4. Redémarrer
docker restart open-webui

Résultat

  • ✅ Images JPEG/PNG uploadées dans Knowledge Base → OCRisé par Kreuzberg
  • ✅ Texte extrait et indexé dans Qdrant
  • ✅ Modèle LLM peut lire le contenu via RAG

Limitations

  • Les PDFs scannés (images compilées en PDF) ne sont pas encore bien supportés par Kreuzberg
  • Le chat direct avec fichiers joints nécessite un modèle multimodal (vision)

Amélioration qualité OCR (11 Avril 2026)

Problème

La qualité OCR de Kreuzberg était inférieure à l'ancien effi-ocr (Tesseract) car:

  • Kreuzberg ne fait pas de prétraitement d'image
  • effi-ocr convertissait en niveaux de gris + augmentait le contraste (x2)

Solution

Ajout de prétraitement dans le tool OpenWebUI:

def _preprocess_image(self, image: Image.Image) -> Image.Image:
    """Preprocess image for better OCR quality (grayscale + contrast)"""
    if image.mode in ('RGBA', 'LA', 'P'):
        image = image.convert('RGBA').convert('RGB')
    elif image.mode != 'RGB':
        image = image.convert('RGB')
    image = image.convert('L')  # Niveaux de gris
    enhancer = ImageEnhance.Contrast(image)
    image = enhancer.enhance(2.0)  # Contraste x2
    return image

Résultat

  • ✅ Images prétraitées (niveaux de gris + contraste) avant OCR
  • ✅ Meilleure détection du texte, surtout sur documents scannés
  • ✅ Qualité comparable à effi-ocr (Tesseract)

Questions à explorer (OBSOLÈTE)

  1. Ce bug FETCH_URL_MAX_CONTENT_LENGTH est-il connu dans OpenWebUI ? → OUI, bug connu v0.8.12
  2. Existe-t-il une version d'OpenWebUI qui corrige ce bug ? → Fix en cours sur dev branch
  3. Faut-il patcher OpenWebUI manuellement ? → OUI, patches appliqués
  4. Peut-on utiliser un endpoint alternatif (External au lieu de Docling) ? → Docling + Kreuzberg fonctionne
  5. Le Tool manuel peut-il être amélioré pour accéder aux fichiers ? → Plus nécessaire maintenant

Commandes de diagnostic

# Vérifier Kreuzberg
curl http://192.168.1.11:8300/health
docker logs kreuzberg --tail 50

# Vérifier OpenWebUI
docker logs open-webui --tail 100 | grep -i "docling\|kreuzberg\|extract"

# Variables OpenWebUI
docker exec open-webui env | grep -E "CONTENT|DOCLING|FETCH"

# Fichiers uploadés
docker exec open-webui ls /app/backend/data/uploads/*.pdf | head -5

# Test extraction manuel
docker exec open-webui curl -X POST -F "files=@/app/backend/data/uploads/9af3d665-998b-4577-b893-340cb1c28385_2018_Poltzer_AlgorithmeIntuition.pdf" http://192.168.1.11:8300/extract

Objectif

Faire fonctionner l'extraction de documents dans OpenWebUI via Kreuzberg pour que:

  1. L'utilisateur upload un PDF
  2. OpenWebUI appelle automatiquement Kreuzberg
  3. Kreuzberg extrait le texte et les images avec OCR
  4. Le texte est disponible pour le LLM dans le RAG

Informations système

  • OpenWebUI: v0.8.12
  • Kreuzberg: v4.8.2
  • Folzocorp: AMD Ryzen 7 5800X3D (supporte AVX/AVX2)
  • Effi-server: Intel J5040 (SSE4.2 seulement, pas AVX)
  • Réseau: 192.168.1.x LAN

Dossier créé le 10 Avril 2026 pour reprise du diagnostique Solution appliquée le 10 Avril 2026 - Amélioration OCR le 11 Avril 2026 - Status: ✅ RÉSOLU


Configuration OCR - 11 Avril 2026

Changement de backend OCR

Avant: Tesseract (anglais par défaut) Après: PaddleOCR avec français (fra), modèle "server" (meilleure précision)

Fichier de configuration Kreuzberg

/home/folzo/kreuzberg/kreuzberg.toml:

[ocr]
backend = "paddle-ocr"
language = "fra"

[ocr.paddle_ocr_config]
model_tier = "server"

Docker Compose mis à jour

volumes:
  - ./kreuzberg.toml:/app/config/kreuzberg.toml:ro,Z
command: ["serve", "--host", "0.0.0.0", "--port", "8000", "-c", "/app/config/kreuzberg.toml"]