fix(effi-ocr): update tool for port 8301 and correct file paths
- Change OCR_URL to port 8301 - Add uploads directory paths for finding files - Add list_recent_files function
This commit is contained in:
+104
-124
@@ -1,49 +1,45 @@
|
|||||||
# Tool OCR pour OpenWebUI
|
# Tool OCR effi-ocr pour OpenWebUI
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Dans OpenWebUI (http://192.168.1.27:3000) :
|
Dans OpenWebUI (http://192.168.1.27:3000) :
|
||||||
|
|
||||||
1. **Aller dans** : Admin → Tools → Create Tool
|
1. **Aller dans** : Admin → Tools → Create Tool
|
||||||
2. **Nom** : OCR Extracteur de Texte
|
2. **Nom** : effi-ocr
|
||||||
3. **ID** : ocr_extractor
|
3. **Description** : Extrait le texte des images avec Tesseract OCR (précision française)
|
||||||
4. **Description** : Extrait le texte des images pour les livres et documents
|
4. **Coller le code ci-dessous**
|
||||||
|
5. **Save and Activate**
|
||||||
|
|
||||||
## Code du Tool
|
## Code du Tool
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from typing import Optional
|
|
||||||
import requests
|
|
||||||
import base64
|
|
||||||
import os
|
import os
|
||||||
|
import glob
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
class Tools:
|
class Tools:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initialize OCR Tool"""
|
self.ocr_url = os.getenv("OCR_URL", "http://192.168.1.11:8301")
|
||||||
self.ocr_url = os.getenv("OCR_URL", "http://192.168.1.11:8300")
|
self.uploads_dir = "/app/backend/data/uploads"
|
||||||
|
self.host_uploads_dir = "/home/effi/effi/data/uploads"
|
||||||
|
|
||||||
def extract_text_from_image(self, image_path: str, language: str = "fra") -> str:
|
def extract_text_from_image(self, image_path, language="fra"):
|
||||||
"""
|
|
||||||
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:
|
try:
|
||||||
# Read image file
|
file_path = self._find_file(image_path)
|
||||||
with open(image_path, 'rb') as f:
|
|
||||||
|
if not file_path:
|
||||||
|
return "[ERROR] File not found: " + image_path + ". Use list_recent_files() to see available files."
|
||||||
|
|
||||||
|
with open(file_path, 'rb') as f:
|
||||||
files = {'file': f}
|
files = {'file': f}
|
||||||
data = {'lang': language}
|
data = {'lang': language, 'preprocess': 'true'}
|
||||||
|
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
f"{self.ocr_url}/ocr",
|
self.ocr_url + "/ocr",
|
||||||
files=files,
|
files=files,
|
||||||
data=data,
|
data=data,
|
||||||
timeout=30
|
timeout=60
|
||||||
)
|
)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
@@ -52,130 +48,114 @@ class Tools:
|
|||||||
text = result.get('text', '')
|
text = result.get('text', '')
|
||||||
char_count = result.get('characters_count', 0)
|
char_count = result.get('characters_count', 0)
|
||||||
word_count = result.get('words_count', 0)
|
word_count = result.get('words_count', 0)
|
||||||
return f"Texte extrait ({char_count} caractères, {word_count} mots):\n\n{text}"
|
if text:
|
||||||
|
return "OCR effi-ocr (" + str(char_count) + " chars, " + str(word_count) + " words):\n\n" + text
|
||||||
else:
|
else:
|
||||||
return f"Erreur OCR: {result.get('error', 'Unknown error')}"
|
return "[WARNING] No text extracted from " + os.path.basename(file_path)
|
||||||
else:
|
else:
|
||||||
return f"Erreur HTTP {response.status_code}: {response.text}"
|
return "[ERROR] OCR failed: " + str(result.get('error', 'Unknown error'))
|
||||||
|
else:
|
||||||
|
return "[ERROR] HTTP " + str(response.status_code) + ": " + response.text[:200]
|
||||||
|
|
||||||
except FileNotFoundError:
|
except requests.Timeout:
|
||||||
return f"Erreur: Fichier non trouvé: {image_path}"
|
return "[ERROR] Timeout - file is too large"
|
||||||
|
except requests.ConnectionError:
|
||||||
|
return "[ERROR] Cannot connect to effi-ocr at " + self.ocr_url
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"Erreur lors de l'OCR: {str(e)}"
|
return "[ERROR] " + str(e)
|
||||||
|
|
||||||
def extract_text_from_base64(self, image_base64: str, language: str = "fra") -> str:
|
def list_recent_files(self, count=10):
|
||||||
"""
|
|
||||||
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:
|
try:
|
||||||
response = requests.post(
|
files = glob.glob(os.path.join(self.uploads_dir, "*"))
|
||||||
f"{self.ocr_url}/ocr/base64",
|
|
||||||
json={
|
|
||||||
'image_base64': image_base64,
|
|
||||||
'lang': language,
|
|
||||||
'preprocess': True
|
|
||||||
},
|
|
||||||
timeout=30
|
|
||||||
)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
if not files and os.path.exists(self.host_uploads_dir):
|
||||||
result = response.json()
|
files = glob.glob(os.path.join(self.host_uploads_dir, "*"))
|
||||||
if result.get('success'):
|
|
||||||
text = result.get('text', '')
|
files = [f for f in files if os.path.isfile(f)]
|
||||||
char_count = result.get('characters_count', 0)
|
files = sorted(files, key=os.path.getmtime, reverse=True)[:count]
|
||||||
word_count = result.get('words_count', 0)
|
|
||||||
return f"Texte extrait ({char_count} caractères, {word_count} mots):\n\n{text}"
|
if not files:
|
||||||
else:
|
return "[INFO] No files found in uploads directory."
|
||||||
return f"Erreur OCR: extraction échouée"
|
|
||||||
else:
|
result = "[INFO] " + str(len(files)) + " recent files:\n\n"
|
||||||
return f"Erreur HTTP {response.status_code}: {response.text}"
|
for f in files:
|
||||||
|
name = os.path.basename(f)
|
||||||
|
size = os.path.getsize(f)
|
||||||
|
size_str = self._format_size(size)
|
||||||
|
result += "- " + name + " (" + size_str + ")\n"
|
||||||
|
|
||||||
|
result += "\nUse extract_text_from_image(\"filename\", \"fra\") to OCR a file."
|
||||||
|
return result
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return f"Erreur lors de l'OCR: {str(e)}"
|
return "[ERROR] " + str(e)
|
||||||
|
|
||||||
def get_available_languages(self) -> str:
|
def _find_file(self, filename):
|
||||||
"""
|
filename = filename.strip().strip('"').strip("'")
|
||||||
Get list of available OCR languages
|
|
||||||
|
|
||||||
Returns:
|
if os.path.exists(filename):
|
||||||
List of available language codes
|
return filename
|
||||||
"""
|
|
||||||
try:
|
|
||||||
response = requests.get(f"{self.ocr_url}/languages", timeout=10)
|
|
||||||
|
|
||||||
if response.status_code == 200:
|
path = os.path.join(self.uploads_dir, filename)
|
||||||
result = response.json()
|
if os.path.exists(path):
|
||||||
languages = result.get('available_languages', [])
|
return path
|
||||||
return f"Langues disponibles: {', '.join(languages)}"
|
|
||||||
|
path = os.path.join(self.host_uploads_dir, filename)
|
||||||
|
if os.path.exists(path):
|
||||||
|
return path
|
||||||
|
|
||||||
|
for directory in [self.uploads_dir, self.host_uploads_dir]:
|
||||||
|
if not os.path.exists(directory):
|
||||||
|
continue
|
||||||
|
|
||||||
|
pattern = os.path.join(directory, filename + "*")
|
||||||
|
matches = glob.glob(pattern)
|
||||||
|
if matches:
|
||||||
|
return matches[0]
|
||||||
|
|
||||||
|
pattern = os.path.join(directory, "*" + filename + "*")
|
||||||
|
matches = glob.glob(pattern)
|
||||||
|
if matches:
|
||||||
|
for m in matches:
|
||||||
|
if filename in os.path.basename(m):
|
||||||
|
return m
|
||||||
|
return matches[0]
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _format_size(self, size):
|
||||||
|
if size < 1024:
|
||||||
|
return str(size) + " B"
|
||||||
|
elif size < 1024 * 1024:
|
||||||
|
return str(int(size / 1024)) + " KB"
|
||||||
else:
|
else:
|
||||||
return f"Erreur: {response.status_code}"
|
return str(int(size / (1024 * 1024))) + " MB"
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
return f"Erreur: {str(e)}"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Variables d'environnement
|
def extract_text_from_image(image_path, language="fra"):
|
||||||
|
tools = Tools()
|
||||||
|
return tools.extract_text_from_image(image_path, language)
|
||||||
|
|
||||||
Dans les Settings d'OpenWebUI (Admin → Settings → Environment Variables) :
|
def list_recent_files(count=10):
|
||||||
|
tools = Tools()
|
||||||
**Si effi-ocr est sur le MEME serveur (recommandé):**
|
return tools.list_recent_files(count)
|
||||||
```
|
|
||||||
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
|
## 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]
|
extract_text_from_image("photo.jpg", "fra")
|
||||||
→ L'agent utilise automatiquement le Tool OCR
|
extract_text_from_image("9af3d665_document.pdf", "fra")
|
||||||
|
list_recent_files()
|
||||||
```
|
```
|
||||||
|
|
||||||
## Langues disponibles
|
## Variables d'environnement
|
||||||
|
|
||||||
- `fra` - Français
|
Dans OpenWebUI Settings:
|
||||||
- `eng` - Anglais
|
```
|
||||||
- `fra+eng` - Français + Anglais (bilingue)
|
OCR_URL=http://192.168.1.11:8301
|
||||||
- `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*
|
*Updated 11 Avril 2026 - Port 8301*
|
||||||
|
|||||||
Reference in New Issue
Block a user