Lire un document (OCR)
kewos/ocr transforme une image en texte. Un module appelle une fonction ; il ne choisit
jamais de moteur, ne nomme jamais de fournisseur, et n’a pas à savoir si l’instance est
connectée à Internet.
L’appel
from kewos.ocr import extract_text
result = extract_text( document, # bytes mime_type="image/jpeg", default=tenant_default, # paramètre ocr.engine du tenant fallback=tenant_fallback, # paramètre ocr.fallback_engine)
result.text # ce qui a été luresult.engine # quel moteur a réponduresult.fell_back # True si le moteur configuré n'a pas pu servirresult.blocks # les positions, quand le moteur les fournitresult.confidence # quand le moteur la fournitresult.engine n’est pas décoratif. Un module qui déduit un montant d’un texte lu doit
pouvoir dire d’où vient ce texte, et un jour quelqu’un le lui demandera.
Les deux moteurs
| Moteur | Où il lit | Coût | Accepte |
|---|---|---|---|
pdf_text | Sur la machine, rien ne sort | Gratuit | |
plain | Sur la machine, rien ne sort | Gratuit | PNG, JPEG, TIFF, BMP, WebP |
ai | Via kewos/ai | Facturé à l’appel | PNG, JPEG, WebP, GIF |
Le PDF, et pourquoi ce n’est pas de l’OCR
La plupart des PDF d’entreprise ne sont pas des scans. Une facture produite par un logiciel de comptabilité, une facture électronique, un relevé exporté : tous portent une vraie couche de texte. La lire est exact, pas probabiliste, ne coûte rien, et ne demande ni chaîne de compilation native ni modèle.
C’est pour cette raison que pdf_text se place devant l’OCR et non à côté : payer un modèle
de vision pour lire un document qui dit déjà ce qu’il contient, c’est dépenser de l’argent pour
obtenir une réponse moins bonne.
result = extract_text(pdf_bytes, mime_type="application/pdf", default="pdf_text")result.text # les pages, séparées par un saut de page (\f)result.confidence # None : une couche de texte n'est pas une suppositionplain s’appuie sur un binaire système que Kewos ne prend pas en dépendance : la plupart
des installations ne feront jamais d’OCR, et leur faire porter une chaîne de compilation native
pour une fonction qu’elles n’utilisent pas est un coût payé par tous au bénéfice de quelques-uns.
Le moteur sonde donc à l’enregistrement. Binaire absent, moteur non enregistré, installation intacte, et la capacité OCR annoncée comme éteinte.
ai passe par la façade IA et n’appelle jamais un fournisseur directement. C’est tout le
dessin : la liste blanche de fournisseurs, le consentement de résidence des données, le quota,
le journal d’audit et le cache existent une fois, dans la façade, et ce moteur en hérite en ne
la contournant pas.
La sélection, et pourquoi elle est stricte
- Un moteur nommé explicitement gagne, ou l’appel échoue. Il n’y a pas de repli : nommer un moteur est un acte délibéré, et en servir un autre en silence répondrait à une question que personne n’a posée.
- Sinon, le moteur configuré du tenant (
ocr.engine). - Si ce moteur est absent ou refuse le type de fichier, le repli (
ocr.fallback_engine), et le résultat portefell_back=True.
Le mode dégradé se voit
from kewos.ocr import ocr_capability
ocr_capability(configured_engine="plain", fallback_engine="ai")# {"enabled": True, "engine": "ai", "degraded": True,# "offline": False, "costly": True, "reason": "configured-engine-missing"}Deux faits comptent pour un exploitant qui décide d’activer l’OCR, et ils sont là : est-ce que ça marche, et est-ce que les documents quittent la machine.
Le cas qui piège tout le monde est celui-ci : le binaire est installé, donc le moteur existe,
mais personne ne l’a sélectionné. La capacité répond alors enabled: false avec
reason: "no-engine-configured", plutôt que d’afficher un bouton qui échouera au premier clic.
Ce que le sous-système ne fait pas
- Il ne stocke rien. Le document reste chez l’appelant.
- Il ne journalise jamais le texte lu, ni un extrait, ni une longueur qui trahirait un contenu. Le journal porte le moteur, le type et le résultat.
- Il n’interprète rien. Trouver un numéro de TVA dans le texte est le travail d’un module.
- Il ne s’exécute pas dans une requête HTTP pour un document réel. Une lecture est lente et, côté IA, sortante : les modules la passent par la file de travaux.
Ajouter un moteur
from kewos.ocr import OcrEngine, register_engine
register_engine( OcrEngine( name="mon_moteur", read=ma_fonction, # (document, mime_type, language) -> OcrResult accepts=("image/png",), offline=True, # le document reste-t-il sur cette machine ? costly=False, # une lecture a-t-elle un prix à l'appel ? ))offline et costly ne sont pas de la documentation : la sélection les lit pour refuser de
choisir toute seule un moteur distant et facturé.