feat(generate-song): add ACE-Step download script, remove legacy effi-ocr

- Add download-ace-step-full.sh script for easier model downloads
- Remove effi-ocr (migrated to effi-kreuzberg for OCR functionality)
- Generate Song v0.5.4 now fully functional with JK-AceStep-Nodes
This commit is contained in:
Folzo
2026-04-11 12:27:20 +02:00
parent 2ab1efd7e4
commit e501213959
8 changed files with 72 additions and 748 deletions
+72
View File
@@ -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 "===================================================="
-20
View File
@@ -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"]
-232
View File
@@ -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
-181
View File
@@ -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*
-80
View File
@@ -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*
-22
View File
@@ -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
-208
View File
@@ -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)
-5
View File
@@ -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