diff --git a/comfyui/download-ace-step-full.sh b/comfyui/download-ace-step-full.sh new file mode 100755 index 0000000..39d8259 --- /dev/null +++ b/comfyui/download-ace-step-full.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# Script de téléchargement des modèles ACE-Step 1.5 COMPLETS +# À lancer sur Folzo Corp + +set -e + +BASE_DIR="/home/folzo/Documents/OpenCode/Projets/Effi/comfyui/models" + +echo "🎵 ACE-Step 1.5 - Téléchargement COMPLET des modèles" +echo "====================================================" +echo "" + +# 1. VAE +echo "📦 1/4 - Téléchargement du VAE..." +mkdir -p "$BASE_DIR/vae" +cd "$BASE_DIR/vae" +if [ ! -f "ace_1.5_vae.safetensors" ]; then + wget -q --progress=bar:force "https://huggingface.co/ACE-Step/Ace-Step1.5/resolve/main/vae/diffusion_pytorch_model.safetensors" -O "ace_1.5_vae.safetensors" + echo "✅ VAE téléchargé" +else + echo "✅ VAE déjà présent" +fi +ls -lh "ace_1.5_vae.safetensors" + +echo "" + +# 2. Diffusion Model +echo "📦 2/4 - Téléchargement du modèle de diffusion..." +mkdir -p "$BASE_DIR/diffusion_models" +cd "$BASE_DIR/diffusion_models" +if [ ! -f "acestep_v1.5_turbo.safetensors" ]; then + wget -q --progress=bar:force "https://huggingface.co/ACE-Step/Ace-Step1.5/resolve/main/acestep-v15-turbo/model.safetensors" -O "acestep_v1.5_turbo.safetensors" + echo "✅ Diffusion model téléchargé" +else + echo "✅ Diffusion model déjà présent" +fi +ls -lh "acestep_v1.5_turbo.safetensors" + +echo "" + +# 3. Text Encoder 0.6B +echo "📦 3/4 - Téléchargement du text encoder 0.6B..." +mkdir -p "$BASE_DIR/text_encoders" +cd "$BASE_DIR/text_encoders" +if [ ! -f "qwen_0.6b_ace15.safetensors" ]; then + wget -q --progress=bar:force "https://huggingface.co/ACE-Step/Ace-Step1.5/resolve/main/acestep-5Hz-lm-0.6B/model.safetensors" -O "qwen_0.6b_ace15.safetensors" + echo "✅ Text encoder 0.6B téléchargé" +else + echo "✅ Text encoder 0.6B déjà présent" +fi +ls -lh "qwen_0.6b_ace15.safetensors" + +echo "" + +# 4. Text Encoder 4B +echo "📦 4/4 - Téléchargement du text encoder 4B..." +cd "$BASE_DIR/text_encoders" +if [ ! -f "qwen_4b_ace15.safetensors" ]; then + wget -q --progress=bar:force "https://huggingface.co/ACE-Step/Ace-Step1.5/resolve/main/acestep-5Hz-lm-4B/model.safetensors" -O "qwen_4b_ace15.safetensors" + echo "✅ Text encoder 4B téléchargé" +else + echo "✅ Text encoder 4B déjà présent" +fi +ls -lh "qwen_4b_ace15.safetensors" + +echo "" +echo "====================================================" +echo "🎉 Téléchargement terminé !" +echo "" +echo "Prochaine étape : redémarrer ComfyUI" +echo "docker restart comfyui" +echo "====================================================" diff --git a/effi-ocr/Dockerfile b/effi-ocr/Dockerfile deleted file mode 100644 index 6085dc3..0000000 --- a/effi-ocr/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM python:3.11-slim -# Installer Tesseract et les langues -RUN apt-get update && apt-get install -y \ - tesseract-ocr \ - tesseract-ocr-fra \ - tesseract-ocr-eng \ - libtesseract-dev \ - && rm -rf /var/lib/apt/lists/* -# Créer le répertoire de travail -WORKDIR /app -# Copier les dépendances -COPY requirements.txt . -# Installer les dépendances Python -RUN pip install --no-cache-dir -r requirements.txt -# Copier le code -COPY main.py . -# Exposer le port -EXPOSE 8300 -# Lancer l'application -CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8300"] diff --git a/effi-ocr/README.md b/effi-ocr/README.md deleted file mode 100644 index aafc8a4..0000000 --- a/effi-ocr/README.md +++ /dev/null @@ -1,232 +0,0 @@ -# 📝 Effi-OCR - -Service OCR (Optical Character Recognition) pour Effi. Extrait le texte des images et photos de documents. - ---- - -## 🎯 Fonctionnalités - -- Extraction de texte à partir d'images (JPEG, PNG, GIF, BMP, TIFF, WebP) -- Support multilingue (Français, Anglais, Allemand, Espagnol, Italien) -- Prétraitement automatique pour améliorer la qualité -- API REST simple et rapide -- Intégration OpenWebUI via Tool - ---- - -## 🚀 Démarrage rapide - -```bash -# Construire et démarrer -cd ~/Documents/OpenCode/Projets/Effi/effi-ocr -sudo docker compose up -d --build - -# Vérifier le service -curl http://localhost:8300/health -``` - ---- - -## 📡 API Endpoints - -### Health Check -```bash -GET /health -``` - -### OCR - Upload fichier -```bash -POST /ocr -Content-Type: multipart/form-data - -Parameters: - - file: Image à analyser - - lang: Code langue (fra, eng, fra+eng, etc.) - - preprocess: true/false (prétraitement auto) -``` - -Exemple: -```bash -curl -X POST -F "file=@photo.jpg" -F "lang=fra" http://localhost:8300/ocr -``` - -### OCR - Base64 -```bash -POST /ocr/base64 -Content-Type: application/json - -{ - "image_base64": "...", - "lang": "fra", - "preprocess": true -} -``` - -### Langues disponibles -```bash -GET /languages -``` - ---- - -## 🔧 Configuration - -### Variables d'environnement - -| Variable | Défaut | Description | -|----------|--------|-------------| -| `OCR_URL` | `http://192.168.1.11:8300` | URL du service OCR | - -### Langues supportées - -- `fra` - Français -- `eng` - Anglais -- `fra+eng` - Bilingue FR+EN -- `deu` - Allemand -- `spa` - Espagnol -- `ita` - Italien - ---- - -## 🐳 Docker - -### Construction -```bash -sudo docker compose build -``` - -### Démarrage -```bash -sudo docker compose up -d -``` - -### Logs -```bash -sudo docker logs effi-ocr -f -``` - -### Arrêt -```bash -sudo docker compose down -``` - ---- - -## 🔗 Intégration OpenWebUI - -Voir [TOOL-OPENWEBUI.md](TOOL-OPENWEBUI.md) pour la configuration complète du Tool. - -**Résumé rapide:** -1. Admin → Tools → Create Tool -2. Copier le code Python fourni -3. Configurer la variable `OCR_URL` -4. Activer le Tool dans les paramètres de conversation - ---- - -## 🧪 Tests - -### Test de santé -```bash -curl http://localhost:8300/health -``` - -### Test OCR simple -```bash -curl -X POST \ - -F "file=@/chemin/vers/image.jpg" \ - -F "lang=fra" \ - http://localhost:8300/ocr -``` - -### Test avec prétraitement désactivé -```bash -curl -X POST \ - -F "file=@image.png" \ - -F "lang=eng" \ - -F "preprocess=false" \ - http://localhost:8300/ocr -``` - ---- - -## 📊 Performance - -- **Temps de traitement** : ~1-3 secondes par image (dépend de la taille) -- **Formats supportés** : JPEG, PNG, GIF, BMP, TIFF, WebP -- **Taille max recommandée** : 2048x2048 pixels -- **Prétraitement** : Conversion niveaux de gris + contraste (optionnel) - ---- - -## 🐛 Dépannage - -### Service ne répond pas -```bash -# Vérifier si le conteneur tourne -sudo docker ps | grep effi-ocr - -# Redémarrer -sudo docker restart effi-ocr - -# Voir les logs -sudo docker logs effi-ocr -``` - -### Tesseract non trouvé -L'erreur indique que Tesseract n'est pas installé dans le conteneur. Reconstruire: -```bash -sudo docker compose down -sudo docker compose up -d --build -``` - -### OCR de mauvaise qualité -- Utiliser `lang=fra+eng` pour les documents mixtes -- S'assurer que l'image est bien éclairée -- Vérifier la résolution (300 DPI recommandé pour documents) -- Activer le prétraitement (par défaut: true) - ---- - -## 📁 Structure - -``` -effi-ocr/ -├── main.py # API FastAPI -├── Dockerfile # Configuration Docker -├── docker-compose.yml # Orchestration -├── requirements.txt # Dépendances Python -├── README.md # Ce fichier -└── TOOL-OPENWEBUI.md # Guide Tool OpenWebUI -``` - ---- - -## 📝 Dépendances - -- Python 3.11 -- FastAPI -- Pillow (traitement d'images) -- pytesseract (wrapper Tesseract) -- Tesseract OCR 5.x - ---- - -## 🎨 Cas d'usage - -- **Numérisation de livres** : Extraire le texte de photos de pages -- **Factures** : Récupérer les informations de factures scannées -- **Documents** : OCR sur PDF et images de documents -- **Notes manuscrites** : Reconnaissance de texte manuscrit (limitée) - ---- - -## 🔒 Sécurité - -- Le service écoute uniquement sur localhost (127.0.0.1:8300) -- Aucune donnée n'est stockée persistante -- Les images sont traitées en mémoire et supprimées après - ---- - -Créé le 6 Avril 2026 diff --git a/effi-ocr/TOOL-OPENWEBUI.md b/effi-ocr/TOOL-OPENWEBUI.md deleted file mode 100644 index e5decc7..0000000 --- a/effi-ocr/TOOL-OPENWEBUI.md +++ /dev/null @@ -1,181 +0,0 @@ -# Tool OCR pour OpenWebUI - -## Configuration - -Dans OpenWebUI (http://192.168.1.27:3000) : - -1. **Aller dans** : Admin → Tools → Create Tool -2. **Nom** : OCR Extracteur de Texte -3. **ID** : ocr_extractor -4. **Description** : Extrait le texte des images pour les livres et documents - -## Code du Tool - -```python -from typing import Optional -import requests -import base64 -import os - -class Tools: - def __init__(self): - """Initialize OCR Tool""" - self.ocr_url = os.getenv("OCR_URL", "http://192.168.1.11:8300") - - def extract_text_from_image(self, image_path: str, language: str = "fra") -> str: - """ - Extract text from an image file using OCR - - Args: - image_path: Path to the image file (jpg, png, etc.) - language: Language code (fra, eng, fra+eng, etc.) - - Returns: - Extracted text from the image - """ - try: - # Read image file - with open(image_path, 'rb') as f: - files = {'file': f} - data = {'lang': language} - - response = requests.post( - f"{self.ocr_url}/ocr", - files=files, - data=data, - timeout=30 - ) - - if response.status_code == 200: - result = response.json() - if result.get('success'): - text = result.get('text', '') - char_count = result.get('characters_count', 0) - word_count = result.get('words_count', 0) - return f"Texte extrait ({char_count} caractères, {word_count} mots):\n\n{text}" - else: - return f"Erreur OCR: {result.get('error', 'Unknown error')}" - else: - return f"Erreur HTTP {response.status_code}: {response.text}" - - except FileNotFoundError: - return f"Erreur: Fichier non trouvé: {image_path}" - except Exception as e: - return f"Erreur lors de l'OCR: {str(e)}" - - def extract_text_from_base64(self, image_base64: str, language: str = "fra") -> str: - """ - Extract text from a base64 encoded image - - Args: - image_base64: Base64 encoded image string - language: Language code (fra, eng, fra+eng, etc.) - - Returns: - Extracted text from the image - """ - try: - response = requests.post( - f"{self.ocr_url}/ocr/base64", - json={ - 'image_base64': image_base64, - 'lang': language, - 'preprocess': True - }, - timeout=30 - ) - - if response.status_code == 200: - result = response.json() - if result.get('success'): - text = result.get('text', '') - char_count = result.get('characters_count', 0) - word_count = result.get('words_count', 0) - return f"Texte extrait ({char_count} caractères, {word_count} mots):\n\n{text}" - else: - return f"Erreur OCR: extraction échouée" - else: - return f"Erreur HTTP {response.status_code}: {response.text}" - - except Exception as e: - return f"Erreur lors de l'OCR: {str(e)}" - - def get_available_languages(self) -> str: - """ - Get list of available OCR languages - - Returns: - List of available language codes - """ - try: - response = requests.get(f"{self.ocr_url}/languages", timeout=10) - - if response.status_code == 200: - result = response.json() - languages = result.get('available_languages', []) - return f"Langues disponibles: {', '.join(languages)}" - else: - return f"Erreur: {response.status_code}" - - except Exception as e: - return f"Erreur: {str(e)}" -``` - -## Variables d'environnement - -Dans les Settings d'OpenWebUI (Admin → Settings → Environment Variables) : - -**Si effi-ocr est sur le MEME serveur (recommandé):** -``` -OCR_URL=http://host.docker.internal:8300 -``` - -**Si effi-ocr est sur un autre serveur (Fedora 192.168.1.11):** -``` -OCR_URL=http://192.168.1.11:8300 -``` - -## Utilisation - -Une fois le Tool créé, les agents pourront l'utiliser avec ces fonctions : - -- `extract_text_from_image("/chemin/vers/image.jpg", "fra")` - Extraire le texte d'un fichier image -- `extract_text_from_base64("base64encoded...", "fra")` - Extraire d'une image encodée en base64 -- `get_available_languages()` - Lister les langues disponibles - -## Exemple de prompt - -``` -"Effi, lis-moi ce texte" [upload d'image] -→ L'agent utilise automatiquement le Tool OCR -``` - -## Langues disponibles - -- `fra` - Français -- `eng` - Anglais -- `fra+eng` - Français + Anglais (bilingue) -- `deu` - Allemand -- `spa` - Espagnol -- `ita` - Italien - -## Dépannage - -**Erreur de connexion** : -```bash -# Vérifier que le service OCR tourne -curl http://192.168.1.11:8300/health - -# Redémarrer si nécessaire -cd ~/Documents/OpenCode/Projets/Effi/effi-ocr -sudo docker compose restart -``` - -**Texte mal extrait** : -- Essayer `fra+eng` pour les documents bilingues -- Vérifier la qualité de l'image (résolution, contraste) -- L'OCR fonctionne mieux avec des images bien éclairées - ---- - -*Tool créé le 6 Avril 2026* diff --git a/effi-ocr/TROUBLESHOOTING.md b/effi-ocr/TROUBLESHOOTING.md deleted file mode 100644 index a0b34dc..0000000 --- a/effi-ocr/TROUBLESHOOTING.md +++ /dev/null @@ -1,80 +0,0 @@ -# Dépannage effi-OCR - -## Problèmes Connus - -### 1. "Fichier non trouvé" - Erreur Common - -**Symptôme :** -``` -Erreur: Fichier non trouvé pour l'ID: page_image.jpg (cherché dans /app/backend/data/uploads/) -``` - -**Cause :** -effi-ocr est sur une autre machine que OpenWebUI. Les chemins de fichiers ne sont pas partagés. - -**Solution :** -Installer effi-ocr sur le **MÊME serveur** qu'OpenWebUI (effi-server 192.168.1.27) - ---- - -### 2. effi-ocr loop / se bloque - -**Symptôme :** -Le modèle répète "call the tool call the tool..." en boucle. - -**Causes possibles :** -- Tool mal configuré dans OpenWebUI -- URL OCR_URL incorrecte -- Le modèle a un problème avec le tool calling - -**Solutions :** -1. Vérifier que `OCR_URL` pointe vers le bon serveur -2. Recréer le tool OCR dans OpenWebUI -3. Désactiver Sub Agent/Planner Agent temporairement - ---- - -### 3. OCR retourne du texte vide - -**Causes possibles :** -- Image de mauvaise qualité -- Langue incorrecte (utiliser `fra+eng`) -- Prétraitement désactivé - -**Solutions :** -1. Tester avec une image plus claire -2. Utiliser `lang=fra+eng` pour documents mixtes -3. Activer le prétraitement - ---- - -## Checklist Diagnostic - -- [ ] effi-ocr tourne sur le port 8300 -- [ ] OCR_URL est correct dans OpenWebUI -- [ ] effi-ocr est sur le MÊME serveur qu'OpenWebUI -- [ ] Le tool OCR est correctement créé dans Admin → Tools -- [ ] Le fichier uploadé existe dans /app/backend/data/uploads/ - ---- - -## Commandes de Test - -### Vérifier effi-ocr (sur le serveur où il tourne) -```bash -curl http://localhost:8300/health -``` - -### Tester OCR avec une image -```bash -curl -X POST -F "file=@test.jpg" -F "lang=fra" http://localhost:8300/ocr -``` - -### Vérifier les fichiers uploadés (OpenWebUI) -```bash -ls -la /app/backend/data/uploads/ -``` - ---- - -*Dernière mise à jour: Avril 2026* diff --git a/effi-ocr/docker-compose.yml b/effi-ocr/docker-compose.yml deleted file mode 100644 index 432cb98..0000000 --- a/effi-ocr/docker-compose.yml +++ /dev/null @@ -1,22 +0,0 @@ -services: - effi-ocr: - build: . - container_name: effi-ocr - ports: - - "8300:8300" - restart: unless-stopped - environment: - - PYTHONUNBUFFERED=1 - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8300/health"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 10s - networks: - - effi-network - -networks: - effi-network: - external: true - name: effi-network diff --git a/effi-ocr/main.py b/effi-ocr/main.py deleted file mode 100644 index aefba3d..0000000 --- a/effi-ocr/main.py +++ /dev/null @@ -1,208 +0,0 @@ -""" -Effi-OCR : Service OCR pour Effi -API FastAPI qui expose Tesseract via une interface REST -""" - -from fastapi import FastAPI, File, UploadFile, HTTPException -from fastapi.responses import JSONResponse -from PIL import Image -import pytesseract -import io -import logging -from typing import Optional - -# Configuration logging -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) - -app = FastAPI( - title="Effi-OCR", - description="Service OCR pour extraction de texte d'images", - version="1.0.0" -) - - -@app.get("/health") -async def health_check(): - """Endpoint de santé pour monitoring""" - try: - # Vérifier que Tesseract est accessible - import subprocess - result = subprocess.run(['tesseract', '--version'], capture_output=True, text=True) - version_line = result.stdout.split('\n')[0] if result.stdout else "unknown" - tesseract_version = str(version_line) # Forcer en string - except Exception as e: - tesseract_version = f"error: {str(e)}" - - return { - "status": "healthy", - "service": "effi-ocr", - "version": "1.0.0", - "tesseract_version": tesseract_version - } - - -@app.post("/ocr") -async def ocr_image( - file: UploadFile = File(...), - lang: str = "fra", - preprocess: bool = True -): - """ - Extraire le texte d'une image - - Args: - file: Image à analyser (jpg, png, etc.) - lang: Code langue (fra, eng, fra+eng, etc.) - preprocess: Appliquer un prétraitement pour améliorer la qualité - - Returns: - JSON avec le texte extrait et les métadonnées - """ - logger.info(f"OCR demandé - lang: {lang}, fichier: {file.filename}") - - # Vérifier le type de fichier - allowed_types = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/tiff', 'image/webp'] - if file.content_type not in allowed_types: - raise HTTPException( - status_code=400, - detail=f"Type de fichier non supporté: {file.content_type}. Types acceptés: {', '.join(allowed_types)}" - ) - - try: - # Lire l'image - contents = await file.read() - image = Image.open(io.BytesIO(contents)) - - # Convertir en RGB si nécessaire (pour les images avec transparence) - if image.mode in ('RGBA', 'LA', 'P'): - image = image.convert('RGB') - - # Prétraitement optionnel pour améliorer la qualité OCR - if preprocess: - # Convertir en niveaux de gris pour meilleure détection texte - image = image.convert('L') - # Augmenter le contraste - from PIL import ImageEnhance - enhancer = ImageEnhance.Contrast(image) - image = enhancer.enhance(2.0) - - # OCR avec Tesseract - text = pytesseract.image_to_string(image, lang=lang) - - # Nettoyer le texte - text = text.strip() - - # Informations sur l'image - width, height = image.size - - logger.info(f"OCR terminé - {len(text)} caractères extraits") - - return JSONResponse(content={ - "success": True, - "text": text, - "language": lang, - "filename": file.filename, - "image_size": {"width": width, "height": height}, - "characters_count": len(text), - "words_count": len(text.split()) if text else 0 - }) - - except Exception as e: - logger.error(f"Erreur OCR: {str(e)}") - raise HTTPException(status_code=500, detail=f"Erreur lors de l'OCR: {str(e)}") - - -@app.post("/ocr/base64") -async def ocr_base64( - image_base64: str, - lang: str = "fra", - preprocess: bool = True -): - """ - Extraire le texte d'une image en base64 - - Args: - image_base64: Image encodée en base64 - lang: Code langue (fra, eng, fra+eng, etc.) - preprocess: Appliquer un prétraitement - - Returns: - JSON avec le texte extrait - """ - import base64 - - logger.info(f"OCR base64 demandé - lang: {lang}") - - try: - # Décoder le base64 - image_data = base64.b64decode(image_base64) - image = Image.open(io.BytesIO(image_data)) - - # Convertir en RGB si nécessaire - if image.mode in ('RGBA', 'LA', 'P'): - image = image.convert('RGB') - - # Prétraitement - if preprocess: - image = image.convert('L') - from PIL import ImageEnhance - enhancer = ImageEnhance.Contrast(image) - image = enhancer.enhance(2.0) - - # OCR - text = pytesseract.image_to_string(image, lang=lang) - text = text.strip() - - width, height = image.size - - logger.info(f"OCR base64 terminé - {len(text)} caractères") - - return { - "success": True, - "text": text, - "language": lang, - "image_size": {"width": width, "height": height}, - "characters_count": len(text), - "words_count": len(text.split()) if text else 0 - } - - except Exception as e: - logger.error(f"Erreur OCR base64: {str(e)}") - raise HTTPException(status_code=500, detail=f"Erreur lors de l'OCR: {str(e)}") - - -@app.get("/languages") -async def list_languages(): - """Lister les langues disponibles pour l'OCR""" - try: - # Commande tesseract pour lister les langues - import subprocess - result = subprocess.run( - ['tesseract', '--list-langs'], - capture_output=True, - text=True - ) - - # Parser la sortie - lines = result.stdout.strip().split('\n') - # La première ligne est "List of available languages (xxx):" - languages = lines[1:] if len(lines) > 1 else [] - - return { - "available_languages": languages, - "count": len(languages) - } - except Exception as e: - logger.error(f"Erreur listage langues: {str(e)}") - # Fallback avec les langues communes - return { - "available_languages": ["fra", "eng", "fra+eng", "deu", "spa", "ita"], - "count": 6, - "note": "Liste par défaut, erreur lors de la récupération" - } - - -if __name__ == "__main__": - import uvicorn - uvicorn.run(app, host="0.0.0.0", port=8300) diff --git a/effi-ocr/requirements.txt b/effi-ocr/requirements.txt deleted file mode 100644 index 9a579d7..0000000 --- a/effi-ocr/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -fastapi==0.109.0 -uvicorn[standard]==0.27.0 -python-multipart==0.0.6 -pillow==10.2.0 -pytesseract==0.3.10