- Better file finding (startswith + contains) - Normalize language codes (French->fra, English->eng, etc.) - List all files in directory when searching
167 lines
5.5 KiB
Markdown
167 lines
5.5 KiB
Markdown
# Tool OCR effi-ocr pour OpenWebUI
|
|
|
|
## Configuration
|
|
|
|
Dans OpenWebUI (http://192.168.1.27:3000) :
|
|
|
|
1. **Aller dans** : Admin → Tools → Create Tool
|
|
2. **Nom** : effi-ocr
|
|
3. **Description** : Extrait le texte des images avec Tesseract OCR (précision française)
|
|
4. **Coller le code ci-dessous**
|
|
5. **Save and Activate**
|
|
|
|
## Code du Tool
|
|
|
|
```python
|
|
import os
|
|
import glob
|
|
import requests
|
|
|
|
|
|
class Tools:
|
|
def __init__(self):
|
|
self.ocr_url = os.getenv("OCR_URL", "http://192.168.1.11:8301")
|
|
self.uploads_dir = "/app/backend/data/uploads"
|
|
self.host_uploads_dir = "/home/effi/effi/data/uploads"
|
|
|
|
def _normalize_language(self, lang):
|
|
lang_map = {
|
|
"french": "fra", "francais": "fra", "fr": "fra",
|
|
"english": "eng", "eng": "eng",
|
|
"german": "deu", "de": "deu",
|
|
"spanish": "spa", "es": "spa",
|
|
"italian": "ita", "it": "ita"
|
|
}
|
|
return lang_map.get(lang.lower(), lang)
|
|
|
|
def extract_text_from_image(self, image_path, language="fra"):
|
|
try:
|
|
file_path = self._find_file(image_path)
|
|
|
|
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': (os.path.basename(file_path), f)}
|
|
data = {'lang': self._normalize_language(language), 'preprocess': 'true'}
|
|
|
|
response = requests.post(
|
|
self.ocr_url + "/ocr",
|
|
files=files,
|
|
data=data,
|
|
timeout=60
|
|
)
|
|
|
|
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)
|
|
if text:
|
|
return "OCR effi-ocr (" + str(char_count) + " chars, " + str(word_count) + " words):\n\n" + text
|
|
else:
|
|
return "[WARNING] No text extracted from " + os.path.basename(file_path)
|
|
else:
|
|
return "[ERROR] OCR failed: " + str(result.get('error', 'Unknown error'))
|
|
else:
|
|
return "[ERROR] HTTP " + str(response.status_code) + ": " + response.text[:200]
|
|
|
|
except requests.Timeout:
|
|
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:
|
|
return "[ERROR] " + str(e)
|
|
|
|
def list_recent_files(self, count=10):
|
|
try:
|
|
files = []
|
|
|
|
if os.path.exists(self.uploads_dir):
|
|
files = glob.glob(os.path.join(self.uploads_dir, "*"))
|
|
|
|
if not files and os.path.exists(self.host_uploads_dir):
|
|
files = glob.glob(os.path.join(self.host_uploads_dir, "*"))
|
|
|
|
files = [f for f in files if os.path.isfile(f)]
|
|
files = sorted(files, key=os.path.getmtime, reverse=True)[:count]
|
|
|
|
if not files:
|
|
return "[INFO] No files found in uploads directory."
|
|
|
|
result = "[INFO] " + str(len(files)) + " recent files:\n\n"
|
|
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:
|
|
return "[ERROR] " + str(e)
|
|
|
|
def _find_file(self, filename):
|
|
filename = filename.strip().strip('"').strip("'")
|
|
|
|
if os.path.exists(filename):
|
|
return filename
|
|
|
|
path = os.path.join(self.uploads_dir, filename)
|
|
if os.path.exists(path):
|
|
return path
|
|
|
|
path = os.path.join(self.host_uploads_dir, filename)
|
|
if os.path.exists(path):
|
|
return path
|
|
|
|
search_dirs = [d for d in [self.uploads_dir, self.host_uploads_dir] if os.path.exists(d)]
|
|
|
|
for directory in search_dirs:
|
|
all_files = glob.glob(os.path.join(directory, "*"))
|
|
for f in all_files:
|
|
basename = os.path.basename(f)
|
|
if basename.startswith(filename) or filename in basename:
|
|
return f
|
|
|
|
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:
|
|
return str(int(size / (1024 * 1024))) + " MB"
|
|
|
|
|
|
def extract_text_from_image(image_path, language="fra"):
|
|
tools = Tools()
|
|
return tools.extract_text_from_image(image_path, language)
|
|
|
|
def list_recent_files(count=10):
|
|
tools = Tools()
|
|
return tools.list_recent_files(count)
|
|
```
|
|
|
|
## Utilisation
|
|
|
|
```
|
|
extract_text_from_image("photo.jpg", "fra")
|
|
extract_text_from_image("9af3d665_document.pdf", "fra")
|
|
list_recent_files()
|
|
```
|
|
|
|
## Variables d'environnement
|
|
|
|
Dans OpenWebUI Settings:
|
|
```
|
|
OCR_URL=http://192.168.1.11:8301
|
|
```
|
|
|
|
---
|
|
|
|
*Updated 11 Avril 2026 - Port 8301*
|