"@edwinfom/resume-intel est une infrastructure d'extraction de CV par LLM — agnostique au modèle, extraction spatiale, fallback OCR, redaction PII, streaming, et sortie JSON Resume v1."

@edwinfom/resume-intel

Infrastructure d'extraction de CV par LLM. Agnostique au modèle · Extraction spatiale · Fallback OCR · Redaction PII · Streaming · Compatible JSON Resume

npm version license typescript

Nouveautés de la v0.2.1

  • Option redactPii — masque les emails, téléphones, adresses et URLs avant l'envoi au LLM. Les vraies valeurs sont réinjectées après l'extraction. Compatible RGPD.
  • confidenceScore dans sectionResults — score de fiabilité par section (0.0–1.0) basé sur le nombre de retries et la complétude des champs.
  • Exports redactPii, reinjectPii, describePiiRedaction — fonctions utilitaires pour les pipelines de redaction personnalisés.

Voir le Changelog complet pour les détails.

Le problème

Extraire des données structurées depuis des CVs PDF est plus difficile qu'il n'y paraît. La plupart des outils utilisent des regex fragiles qui cassent sur les designs modernes, ou ils s'appuient sur un seul fournisseur d'IA et vous enferment dans un écosystème.

Ce qui se passe réellement en production :

  • Mises en page multi-colonnes — les colonnes s'entremêlent. Les dates se mélangent aux descriptions de poste. Le LLM reçoit du chaos sémantique et hallucine.
  • DeepSeek et les modèles similaires ne lisent pas les PDFs bruts — ce sont des modèles texte uniquement. Il faut extraire et nettoyer le texte en amont.
  • Les LLMs produisent du JSON cassé — accolades manquantes, virgules en trop, JSON enveloppé dans des balises markdown. Sans couche de réparation, le pipeline plante.
  • Verrouillage fournisseur — si votre parser ne fonctionne qu'avec Claude ou GPT-4, vous ne pouvez pas passer à un modèle moins cher sans tout réécrire.
  • PDFs scannés — aucune couche de texte. Un extracteur basique retourne une chaîne vide sans explication.
  • Confidentialité des données — envoyer des CVs bruts avec emails et numéros de téléphone à des APIs LLM tierces peut violer le RGPD ou les politiques internes.

resume-intel est un pipeline en quatre couches qui résout tout cela :

import { parseResume } from '@edwinfom/resume-intel'
import { createDeepSeek } from '@ai-sdk/deepseek'
import { readFileSync } from 'node:fs'
 
const result = await parseResume(readFileSync('./cv.pdf'), {
  model: createDeepSeek({ apiKey: process.env.DEEPSEEK_API_KEY })('deepseek-chat'),
  redactPii: true, // RGPD : le LLM ne voit jamais les données personnelles brutes
})
 
console.log(result.data.basics?.name)    // "Jean Dupont"
console.log(result.data.work?.length)    // 3
console.log(result.meta.ocrFallback)     // true si PDF scanné
console.log(result.meta.sectionResults) // diagnostics par section avec scores de confiance

Fonctionnement

1 — Détection de scan

Avant toute extraction, le package vérifie si le PDF contient une couche de texte intégrée. Si la densité de texte est insuffisante, le PDF est classifié comme scanné et le pipeline OCR se déclenche automatiquement.

2a — Extraction spatiale (PDFs natifs)

Les extracteurs standard lisent le texte dans l'ordre de rendu, pas dans l'ordre de lecture. Pour un CV à deux colonnes, cela produit :

2020 Ingénieur Senior TypeScript Node.js
2018 Ingénieur Junior React PostgreSQL

resume-intel extrait les coordonnées des boîtes englobantes, détecte les limites de colonnes par analyse des espaces, trie les blocs par position verticale dans chaque colonne, et concatène les colonnes de gauche à droite. Le LLM reçoit un texte propre et ordonné.

2b — Fallback OCR (PDFs scannés)

Quand un PDF scanné est détecté :

  1. Rastérisation de chaque page en PNG via pdfjs-dist + @napi-rs/canvas à 150 DPI
  2. Exécution de Tesseract.js (WASM) localement sur chaque image
  3. Nettoyage des artefacts OCR (barres de progression, séparateurs, numéros de page)

Aucun service OCR externe. Aucun appel réseau. Tout s'exécute localement.

2c — Redaction PII (optionnel)

Avec redactPii: true, les données personnelles sont remplacées par des placeholders déterministes avant l'appel LLM :

john.doe@gmail.com  →  __PII_EMAIL_0__
+33 6 12 34 56 78   →  __PII_PHONE_1__
https://johndoe.dev →  __PII_URL_2__

Après l'extraction, les vraies valeurs sont réinjectées. Le résultat final est identique à une extraction sans redaction.

3 — Décomposition de tâches

Au lieu d'un seul appel LLM monolithique, resume-intel exécute des extractions parallèles et ciblées par section — chacune avec son propre prompt, schéma, limite maxTokens et boucle de retry. Cela réduit les hallucinations et isole les échecs.

4 — Réparation et validation JSON

  1. Réparation — supprime les balises markdown, corrige les virgules en trop, les accolades manquantes via jsonrepair
  2. Validation — application du schéma Zod
  3. Auto-correction — les erreurs Zod sont renvoyées au LLM pour correction ciblée (jusqu'à maxRetries fois)

Fonctionnalités

Fonctionnalité Description
Extraction spatiale Algorithme de boîtes englobantes pour reconstruire l'ordre de lecture multi-colonnes
Fallback OCR Tesseract.js + @napi-rs/canvas pour les PDFs scannés, entièrement local
Redaction PII Masque emails, téléphones, adresses, URLs avant le LLM — réinjecte après
Agnostique au modèle Vercel AI SDK — fonctionne avec DeepSeek, OpenAI, Anthropic, Gemini, Ollama
JSON Resume v1 Sortie conforme au standard ouvert utilisé par des centaines d'outils
15 sections basics, work, education, skills, languages, projects, awards, certificates, publications, volunteer, interests, references
Sections personnalisées Option sections — extrayez uniquement ce dont vous avez besoin
Schéma personnalisé Option outputSchema — remplacez JSON Resume par votre propre schéma Zod
Validation Zod Application complète du schéma avec boucle de retry auto-correctrice
Réparation JSON jsonrepair gère les balises markdown, virgules en trop, réponses tronquées
Décomposition de tâches Extraction parallèle par section avec retry indépendant
Scores de confiance Signal de fiabilité par section dans sectionResults
Streaming streamResume() — AsyncGenerator pour les mises à jour UI progressives
CLI resume-intel parse <fichier.pdf> — extraction depuis le terminal
Prêt pour le serverless Worker via MessageChannel — fonctionne sur Vercel et AWS Lambda
TypeScript first Typage complet, build dual ESM + CJS