Parsing & Document Processor
Parsing & document-processor
Le parsing des documents est délégué au microservice apps/document-processor (FastAPI, Docling). Le serveur l'appelle en HTTP depuis apps/server/src/utils/document-processor-client.ts. Ce service ne stocke rien dans les tables métier : il renvoie les chunks, et c'est le serveur qui les insère.
Ingestion d'un document
processUploadedFile (admin) appelle processRegularFile (utils/regular-processing.ts) :
- Valide le contenu (non vide) et la taille des blocs (
chunkSize > overlap). - Insère une ligne dans
files(type: regular,classification_status: pending). - Soumet un job :
POST /jobssurdocument-processor, avecpipeline: "regular"etextract_tables: true. Le serveur renvoie{ success: true, fileId, jobId }sans attendre le résultat. - En tâche de fond, interroge
GET /jobs/{jobId}toutes les 10 secondes, pendant 30 minutes au maximum. - Si le job est terminé avec des chunks :
- enregistre
files.processing_metadata(format d'origine, taille, parseur, version, nombre de chunks, tables, images) ; - insère chaque chunk dans
chunks, avec le contenu nettoyé, sa catégorie (categorydu parseur, sinondynamic) et sesmetadata; - crée les tags et rôles absents, puis associe les tags aux chunks ;
- passe
classification_statusàcompleted.
- enregistre
- Si le job renvoie zéro chunk ou un échec interne, le fichier est supprimé.
Les procédures getDocumentProcessorJobStatus, getDocumentProcessorJobStatusBatch et cancelDocumentProcessorJob permettent de suivre un job ou de l'annuler.
Points d'attention
- Si le job passe en
failed,waitForJoblève une erreur. Le code de repli passe alorsclassification_statusàcompletedsans supprimer le fichier : un fichier sans chunks peut rester en base. À vérifier avant de compter sur ce statut. - Les tâches de fond ne sont pas reprises après un redémarrage du serveur : l'attente est en mémoire du processus.
- Les paramètres
chunkSizeetoverlapsont validés côté serveur, mais le parseur Docling les ignore : le découpage est fait par tokens (voir plus bas).
Q&A (processUploadedQA)
processQAcsv (utils/qa-processing.ts) suit le même schéma avec pipeline: "qa" et extract_qa_pairs: true. Le fichier est une ligne de files de type qa. Les paires extraites sont insérées dans qa_pair (question, réponse, catégorie reprise du parseur, sinon not categorized). Le statut du fichier est calculé selon le nombre de paires déjà catégorisées.
Microservice document-processor
Lancé par uvicorn src.main:app --port 8001 (port 8001 dans docker-compose).
Endpoints
| Méthode et route | Usage | Réponse |
|---|---|---|
GET /health | Santé | { status: "healthy", timestamp } |
POST /process | Parsing synchrone, utilisé hors des jobs | ProcessingResult (200) ; 400 base64 invalide, 413 fichier trop gros, 415 type non supporté |
POST /jobs | Soumission asynchrone | 202 avec { job_id, status: "pending" } ; 503 si la persistance des jobs n'est pas disponible |
POST /jobs/batch | Soumission de plusieurs fichiers | 202 avec la liste des jobs |
GET /jobs/{job_id} | Statut et résultat | pending, processing, completed ou failed ; 404 si le job a expiré |
DELETE /jobs/{job_id} | Annulation | 204 |
Une erreur interne pendant POST /process renvoie 200 avec success: false et un champ error, et non un code 500.
Requête (ProcessingRequest)
{
file_content: string; // base64, data URL, ou texte brut (text/plain, text/markdown, text/csv, application/json)
file_name: string;
file_type: string; // type MIME ; prioritaire sur l'extension
chunk_size?: number; // défaut 1000 ; ignoré pour Docling
overlap?: number; // défaut 0 ; déprécié
extract_qa_pairs?: boolean; // défaut false
extract_tables?: boolean; // défaut false ; le serveur l'envoie à true pour les documents
extract_images?: boolean; // défaut false
pipeline?: "regular" | "qa";
diagnostic?: boolean; // ajoute les éléments retirés par le nettoyage
}Réponse (ProcessingResult)
{
success: boolean;
chunks: Chunk[];
qa_pairs: QAPair[];
tables: Table[];
images: Image[];
metadata: Record<string, any>;
processing_time_ms?: number;
error?: string;
}
type Chunk = {
rank: number;
content: string;
category?: string; // catégorie posée par le parseur
page_number?: number;
section_title?: string;
section_path?: string[];
token_count?: number;
source_type?: "text" | "table" | "picture" | "heading" | "list" | "ocr";
has_table: boolean;
has_image: boolean;
metadata: Record<string, any>;
tags: string[]; // tags issus des annotations Markdown
roles: string[]; // rôles issus des annotations Markdown
};Voir Rôles & tags pour la syntaxe des annotations.
Formats
Les formats sont listés dans le registre (src/registry.py) et activés par DOCLING_ENABLED_FORMATS. Ils couvrent :
- PDF, Word, PowerPoint, Excel (y compris les formats anciens
.doc,.ppt,.xls) ; - OpenDocument (texte, tableur, présentation) ;
- HTML, XML, AsciiDoc, LaTeX, EPUB, VTT, EML ;
- CSV, Markdown, texte brut ;
- images (PNG, JPEG, TIFF, BMP, WebP), traitées par Docling avec OCR si activé ;
- JSON, traité par un parseur dédié.
Le type MIME est prioritaire sur l'extension.
Découpage
Pour Docling, le découpage utilise HybridChunker avec une limite en tokens (DOCLING_MAX_TOKENS, 512 par défaut). Le tokenizer est DOCLING_TOKENIZER_MODEL, openai-community/gpt2 par défaut dans le code. Un repli sans tokenizer découpe par caractères (max_tokens * 4).
Quand la fusion native de Docling est désactivée, les chunks consécutifs de même section et de mêmes tags ou rôles sont refusionnés, dans la limite de tokens (_tag_aware_merge_chunks).
Configuration
Serveur
| Variable | Rôle |
|---|---|
DOCUMENT_PROCESSOR_URL | URL du microservice (défaut dans le code : http://localhost:8001) |
Microservice
| Variable | Défaut dans le code | Rôle |
|---|---|---|
DATABASE_URL | non défini | Persistance des jobs dans la table processing_jobs (créée au démarrage). Sans elle, POST /jobs renvoie 503. |
MAX_FILE_SIZE_MB | 50 | Taille maximale ; au-delà, 413 |
DOC_PROCESSOR_WORKERS | 2 | Nombre de workers de la file |
JOB_TIMEOUT_SECONDS | 1800 | Durée maximale d'un job |
JOB_RESULT_TTL_HOURS | 24 | Durée de conservation d'un résultat |
DOCLING_MAX_TOKENS | 512 | Taille maximale d'un chunk, en tokens |
DOCLING_TOKENIZER_MODEL | openai-community/gpt2 | Tokenizer du découpage |
DOCLING_ENABLE_OCR | true | Active l'OCR |
DOCLING_OCR_ENGINE | rapidocr | easyocr, rapidocr, tesseract-cli ou tesserocr |
DOCLING_OCR_LANGUAGES | en,fr | Langues OCR (RapidOCR ne garde que la première) |
DOCLING_TABLE_MODE | accurate | fast ou accurate |
DOCLING_LAYOUT_MODEL | heron | heron, egret_large ou egret_xlarge |
DOCLING_DEVICE | auto | auto, cpu ou cuda |
DOCLING_ENABLE_PICTURE_DESCRIPTION | false | Description des images par un modèle de vision (coûteux) |
DOCLING_ENABLED_FORMATS | liste complète | Formats acceptés |
Les enrichissements (code, formules) sont désactivés par défaut. tesseract-cli et tesserocr exigent l'installation de tesseract-ocr sur le système.
Le fichier .env.example à la racine liste ces variables avec des valeurs d'exemple. Certaines valeurs d'exemple diffèrent des défauts du code : par exemple DOCLING_TOKENIZER_MODEL.