Spaces:
Runtime error
Runtime error
Commit History
-
feat(ingestion): le corpus en deux passes reprenables
Passe 1, scripts/extraire_corpus.py : Docling seul, sans base. Le travail se fait dans un processus enfant (spawn) recycle tous les 25 documents ou au-dela de 5 Go : la memoire de Docling grossit au fil des pages. Le superviseur compte une tentative au lot pendant lequel l'enfant meurt, tue un enfant bloque, s'arrete sur une panne generale (initialisation, echecs en serie) ou si .env et les paquets ont change depuis le lancement — sans quoi l'enfant ecrirait dans un autre cache et la boucle ne finirait pas. Arret propre par data/ingestion/STOP ; suivi dans progression.json. Passe 2, scripts/ingest_corpus.py : ne relit que le cache, jamais Docling. Reprend les lois pending, processing et refused ; une panne de base est rejouee avec attente croissante au lieu de compter chaque document en echec. Les PDF identiques sous deux numeros d'acte sont indexes une fois, l'autre signale. Type et date de l'acte relus dans le titre, l'annee controlee par le numero d'acte. Pipeline (process_law) : …1be6163
-
feat: deployment on free tiers, object-storage documents, and email
Enables the project to run on a free hosting tier — ephemeral disk, managed Postgres behind a connection pooler, no outbound SMTP — and adds the password reset flow that was previously a dead end. Two blocking deployment bugs, both reproduced rather than deduced: DATABASE_URL with ?sslmode=require TypeError: connect() got an unexpected keyword argument 'sslmode' SQLAlchemy's asyncpg dialect forwards unknown query parameters straight to asyncpg.connect(), whose signature accepts neither sslmode nor channel_binding and has no **kwargs. The failure surfaces only on the first database access, long after an apparently successful start — and that is exactly the URL the "copy" buttons of managed Postgres providers hand out, and what .env.example recommended. Settings now refuse such a URL at load time, naming PGSSLMODE as the remedy. alembic/env.py, swapping asyncpg for psycopg2 but keeping the query string ProgrammingError: invalid dsn: invalid URI query parameter prepared_s…6429ad3
-
fix(qualite): ruff devient une vraie barriere, et trouve un schema mort et casse
Ruff tournait sans jeu de regles declare : 1332 signalements, dont 98 faux positifs sur le motif `Depends()` de FastAPI et 615 modernisations de style. Un controle que personne ne peut passer n'est pas un controle. Le jeu retenu ne garde que ce qui signale un defaut reel (F, E4, E7, E9, I, RUF100), avec des exceptions nommees la ou l'ordre des imports EST la protection : env.py doit poser sys.path avant d'importer les modeles, conftest doit surcharger DATABASE_URL avant d'importer l'application. Ce que le controle a alors trouve : - UN SCHEMA MORT ET CASSE. `LawDetailResponse` existait deja, exposant `List[ArticleResponse]`. Il n'etait branche sur aucune route, et il etait doublement inutilisable : ArticleResponse porte le CONTENU integral de chaque article — pour le Code Minier, 166 Ko servis deux fois — et son `number` etait plafonne a 20 caracteres alors que la colonne en fait 64 depuis qu'elle accueille « QUATRE-VINGT-DIX-SEPTIEME ». Le plafond du schema est corrige, et…7435134 -
refactor: retirer 165 Mo de dependances mortes et dix scripts a usage unique
DEPENDANCES scikit-learn et joblib : ZERO occurrence dans tout le depot depuis la suppression du classifieur ML. Avec scipy qu'ils entrainent, ils pesaient 165 Mo dans l'image pour rien. Le classement de domaine est fait par des regles depuis legal_domain_classifier.py. SCRIPTS Sept scripts a usage unique, sans argparse, avec `law_id = 1` code en dur et aucun garde `__main__` — donc executables au simple import. Quatre d'entre eux etaient DESTRUCTIFS sans confirmation : force_clean_extract, reextract_ constitution, reextract_pdfplumber effacaient les articles de la loi 1. reprocess_law.py portait en plus un file_id code en dur ; il figurait dans un plan de suppression precedent et n'avait pas ete supprime. Trois scripts de maintenance des categories (add_category_icons, update_category_icons, cleanup_categories) sont perimes par la migration 007, qui possede desormais les 14 domaines avec leurs icones et le verifie par assertion. Les executer se battrait contre elle. reset_databas…d41abd1
-
Etape 11 : authentification reelle branchee (demande n°2)
app/core/auth.py (188 lignes, JWT + bcrypt + roles) etait complet et importe par PERSONNE. Les 9 endpoints d'administration passaient par deux stubs renvoyant {"id": 1, "role": "admin"} : ils etaient ouverts a tous. BUG BLOQUANT decouvert en chemin : passlib 1.7.4 (derniere version, 2020) est incompatible avec bcrypt >= 4.1 — il lit bcrypt.__about__.__version__, supprime depuis. Avec bcrypt 5.x installe, hash_password echouait avec "password cannot be longer than 72 bytes" MEME pour 13 caracteres : l'authentification aurait ete inutilisable telle que declaree. -> bcrypt utilise directement, passlib retire des manifestes. Pre-hachage SHA-256 + base64 avant bcrypt : entree de longueur fixe, donc support des phrases de passe longues sans la troncature silencieuse a 72 octets de bcrypt (deux mots de passe partageant leurs 72 premiers octets etaient equivalents). Ajouts : - app/api/routes/auth.py : POST /login (formulaire OAuth2, l'URL exacte attendue par oauth2_scheme, donc le…da2ad52 -
Etape 9 : chaine d'ingestion — session detachee, echec franc, statuts
Demande n°4 — process_batch recevait la session de la requete Depends(get_db) la ferme des le retour du handler : chaque acces de la tache detachee echouait, et un `except:` nu avalait l'erreur. process_batch ouvre desormais sa propre session, UNE PAR DOCUMENT (le traitement dure plusieurs minutes ; une session pour tout le lot immobiliserait une connexion du pool et un document en echec entrainerait les suivants). Demande n°5 — plus aucun repli degrade Le repli LlamaParse -> Tesseract -> pypdf renvoyait la couche texte deja presente dans les PDF prc.cm : ~20% de rappel, filigrane injecte au milieu des phrases, cachets lus comme du charabia, et 21% des documents sans aucun texte. Le document etait publie avec ce contenu et marque "completed". Desormais : LlamaParse fait ses 4 tentatives, puis on leve. Le document passe en "refused" avec processing_error et reste retraitable. _extract_pdf_ocr_fallback supprimee ; get_llama_parse_service() utilise a la place d'…bde990c
-
feat(migration): Replace Redis/Meilisearch/Celery with 100% native PostgreSQL FTS and FastAPI BackgroundTasks
c77abb9
-
chore: initial standalone backend for JuriX API (Render)
9cf9a2a