SPB Git
27.5 KB · 609 lines latex
1\documentclass[11pt]{article}2\usepackage[utf8]{inputenc}3\usepackage[T1]{fontenc}4\usepackage[french]{babel}5\usepackage[margin=1in]{geometry}6\usepackage{amsmath,amssymb}7\usepackage{booktabs}8\usepackage{longtable}9\usepackage{array}10\usepackage{xcolor}11\usepackage{graphicx}12\graphicspath{{figures/}}13\usepackage{enumitem}14\usepackage{multicol}15\usepackage{listings}16\usepackage{titlesec}17\usepackage{caption}18\usepackage[hidelinks,colorlinks=true,linkcolor=blue!45!black,urlcolor=blue!45!black]{hyperref}1920\definecolor{codebg}{RGB}{245,246,248}21\definecolor{kw}{RGB}{27,58,91}22\lstset{23  basicstyle=\ttfamily\small,24  backgroundcolor=\color{codebg},25  frame=single, rulecolor=\color{gray!30},26  breaklines=true, columns=fullflexible,27  keywordstyle=\color{kw}\bfseries,28  showstringspaces=false, xleftmargin=4pt, framexleftmargin=4pt,29}30\titleformat{\section}{\large\bfseries\color{kw}}{\thesection}{0.6em}{}31\titleformat{\subsection}{\normalsize\bfseries}{\thesubsection}{0.6em}{}32\setlist{itemsep=2pt,topsep=3pt}33\captionsetup{font=small,labelfont=bf}34\newcommand{\code}[1]{\texttt{\small #1}}3536\title{\bfseries SPID — SEC Project Intelligence Database\\[0.3em]37\large Documentation technique : présentation de la base de données\\38et de sa construction}39\author{%40  Manel Kammoun \quad Djerrycharli Tandjambianda \quad Simon-Pierre Boucher\\[0.3em]41  \small \href{mailto:manel.kammoun@uqo.ca}{manel.kammoun@uqo.ca} \quad42  \href{mailto:djerrycharli.tandjambianda@uqo.ca}{djerrycharli.tandjambianda@uqo.ca} \quad43  \href{mailto:simon-pierre.boucher@uqo.ca}{simon-pierre.boucher@uqo.ca}\\[0.4em]44  \small D\'epartement des sciences administratives, Universit\'e du Qu\'ebec en Outaouais}45\date{\today}4647\begin{document}48\maketitle4950\begin{abstract}51\noindent52Ce document présente \textbf{SPID} (\emph{SEC Project Intelligence Database}),53une base de données qui reconstruit le \emph{portefeuille de projets54stratégiques} des sociétés cotées américaines directement à partir du texte brut55de leurs documents réglementaires déposés auprès de la SEC. À partir de56\textbf{153\,894} sections de filings (formulaires 10-K, 10-Q et 8-K) déposés par57\textbf{500} entreprises entre 2010 et 2026, un extracteur fondé sur un grand58modèle de langage produit \textbf{39\,930} mentions de projets, résolues en59\textbf{19\,227} projets distincts dotés de chronologies, d'un graphe de60connaissances de \textbf{32\,226} n\oe uds et d'embeddings sémantiques. Le61document décrit en détail le corpus source, l'architecture du pipeline, chacune62des cinq étapes de traitement (ingestion, extraction, résolution, graphe,63embeddings), le schéma complet de la base, les statistiques du jeu de données64construit, le coût et le débit du traitement, ainsi que les limites et les65modalités d'utilisation.66\end{abstract}6768\tableofcontents69\clearpage7071% =====================================================================72\section{Vue d'ensemble}73% =====================================================================74La plupart des analyses empiriques traitent les filings de la SEC (10-K, 10-Q,758-K) comme des \emph{documents financiers}. SPID adopte une perspective76différente : il les traite comme une source massive d'\textbf{intelligence sur77les projets d'entreprise} --- nouveaux produits, programmes de R\&D, initiatives78d'intelligence artificielle, expansions d'usines, centres de données, migrations79infonuagiques, intégrations post-acquisition, programmes d'investissement,80expansions géographiques, partenariats, transition énergétique, pipelines de81médicaments, automatisation, etc.8283L'unité d'analyse de SPID n'est ni le document ni l'entreprise, mais le84\textbf{projet}. La base ajoute une « couche projet » par-dessus le corpus EDGAR85existant : extraction $\rightarrow$ résolution $\rightarrow$ chronologies86$\rightarrow$ graphe de connaissances $\rightarrow$ embeddings $\rightarrow$87recherche $\rightarrow$ analytique, le tout persistant dans un unique fichier88DuckDB (\code{data/db/spid.duckdb}).8990\begin{table}[h]91\centering92\caption{Chiffres clés de la base construite (exécution complète, juin 2026).}93\begin{tabular}{lr}94\toprule95Élément & Valeur \\96\midrule97Entreprises couvertes & 500 \\98Sections de filings traitées & 153\,894 \\99Mentions de projets extraites & 39\,930 \\100Projets résolus & 19\,227 \\101Lignes de chronologie (timeline) & 39\,930 \\102N\oe uds du graphe de connaissances & 32\,226 \\103Arêtes du graphe de connaissances & 33\,176 \\104Embeddings de projets (384-d) & 19\,227 \\105Secteurs GICS & 11 \\106Types de projets (taxonomie) & 21 \\107Localisations distinctes & 3\,080 \\108Projets avec montant divulgué & 9\,321 (48{,}5\,\%) \\109Montant médian divulgué & 718 M\$ US \\110\bottomrule111\end{tabular}112\end{table}113114% =====================================================================115\section{Le corpus source}116% =====================================================================117SPID est construit \emph{par-dessus} le corpus EDGAR de l'UQO, qui réside dans118\code{../data} et que SPID consomme en lecture seule.119120\begin{table}[h]121\centering122\caption{Actifs du corpus source utilisés par SPID.}123\small124\begin{tabular}{lll}125\toprule126Actif & Volume & Usage par SPID \\127\midrule128\code{data/raw/sec/} & 88 Go, 500 entreprises & HTML brut des 10-K (sectionné à la demande) \\129\code{parquet/filings/} & 134\,124 filings & métadonnées (cik, ticker, dates, formulaire) \\130\code{parquet/filing\_sections/} & 127\,800 sections & texte pré-segmenté (10-Q + 8-K) \\131\code{parquet/companies/} & métadonnées entreprises & secteur / SIC / état \\132\bottomrule133\end{tabular}134\end{table}135136\paragraph{Point non trivial.} Le pipeline en amont n'avait segmenté que les137formulaires \textbf{10-Q et 8-K}; les 10-K étaient restés en HTML brut. L'étape138d'ingestion de SPID (\S\ref{sec:ingest}) nettoie et segmente le HTML brut des13910-K pour que ces documents circulent dans le même pipeline d'extraction. Les140sections pré-segmentées et les sections 10-K ingérées sont réunies dans une vue141unifiée \code{v\_sections}.142143\begin{table}[h]144\centering145\caption{Décompte des sections éligibles à l'extraction (au moins 30 mots),146par formulaire, après ingestion des 10-K.}147\begin{tabular}{lrr}148\toprule149Formulaire & Sections & Entreprises (CIK) \\150\midrule1518-K  & 103\,926 & 497 \\15210-K & 27\,164  & 497 \\15310-Q & 22\,804  & 84  \\154\midrule155\textbf{Total} & \textbf{153\,894} & 500 \\156\bottomrule157\end{tabular}158\end{table}159160% =====================================================================161\section{Architecture du pipeline}162% =====================================================================163Le traitement s'organise en cinq étapes séquentielles, chacune persistant son164résultat dans DuckDB de manière incrémentale et reprenable.165166\begin{center}167\small168\setlength{\fboxsep}{6pt}169\fbox{\begin{minipage}{0.93\textwidth}170\ttfamily171HTML brut 10-K  ---->  [1. INGEST]  nettoyage + sectionnement (Items 1/1A/2/7) \\172\phantom{xxxxxxxxxxxxxxxxxxxxx} | \\173filing\_sections (10-Q/8-K) --+-->  v\_sections  (flux unifie) \\174\phantom{xxxxxxxxxxxxxxxxxxxxxxxxxx} | \\175\phantom{xx}[2. EXTRACT]  backend enfichable : rules (gratuit) | llm (gpt-4o-mini) \\176\phantom{xxxxxxxxxx} | \ \ -->  project\_mentions \\177\phantom{xxxxxxxxxx} v \\178\phantom{xx}[3. RESOLVE]  fusion des mentions  -->  projects + project\_timeline \\179\phantom{xxxxxxxxxx} +-->  [4. GRAPH]  kg\_nodes / kg\_edges (+ export Cypher/parquet) \\180\phantom{xxxxxxxxxx} +-->  [5. EMBED]  project\_embeddings (MiniLM 384-d) --> recherche semantique181\end{minipage}}182\end{center}183184Les modules correspondants se trouvent dans \code{spid/} :185\code{ingest.py}, \code{extract/} (\code{rules.py}, \code{llm.py}),186\code{pipeline.py}, \code{resolve.py}, \code{graph.py}, \code{embed.py},187\code{search.py}, \code{analytics.py}, \code{store.py}, \code{taxonomy.py},188\code{config.py}, \code{\_\_main\_\_.py} (CLI).189190% =====================================================================191\section{Étape 1 — Ingestion des 10-K}\label{sec:ingest}192% =====================================================================193Module : \code{spid/ingest.py}. Comme le corpus amont ne segmentait pas les 10-K,194cette étape lit le HTML brut de chaque dépôt 10-K195(\code{data/raw/sec/<cik>/10-K/<acc>/}), le nettoie et en extrait les196\emph{Items} les plus denses en projets.197198\paragraph{Procédé.}199\begin{enumerate}200  \item \textbf{Sélection du fichier primaire} : pour chaque accession, on201  retient le plus gros fichier \code{.htm/.html/.txt} du répertoire.202  \item \textbf{Nettoyage HTML} : suppression des balises \code{script},203  \code{style} et \code{table} via BeautifulSoup (\code{lxml}), conversion en204  texte, dé-échappement des entités HTML, normalisation des espaces et des sauts205  de ligne.206  \item \textbf{Découpage en Items} : une expression régulière repère les207  en-têtes « ITEM~n » et conserve uniquement les Items à forte densité de208  projets : \textbf{1 (Business)}, \textbf{1A (Risk Factors)},209  \textbf{2 (Properties)}, \textbf{7/7A (MD\&A)}. Les ébauches de table des210  matières (corps $<$ 400 caractères) sont écartées; pour chaque Item on garde la211  plus longue occurrence (corps réel plutôt que renvoi).212  \item \textbf{Persistance} : les sections obtenues sont écrites dans la table213  \code{spid\_sections} (clé primaire = identifiant aléatoire), avec un compte de214  mots. L'opération est \emph{idempotente} : une accession déjà ingérée est215  sautée.216\end{enumerate}217218\paragraph{Résultat de l'exécution.} \textbf{7\,654} filings 10-K traités219$\rightarrow$ \textbf{27\,164} lignes de sections (contre 2\,126 auparavant,220couvrant désormais l'ensemble des 500 entreprises au lieu de 40).221222% =====================================================================223\section{Étape 2 — Extraction par modèle de langage}\label{sec:extract}224% =====================================================================225Modules : \code{spid/pipeline.py} (moteur) et \code{spid/extract/llm.py}226(extracteur). Le backend par défaut est \textbf{\code{gpt-4o-mini}} d'OpenAI227en mode JSON, mais l'interface est compatible OpenAI : un simple changement de228deux variables d'environnement permet de viser la passerelle de cluster229\code{llm.maclustr.io} ou tout modèle local.230231\subsection{Maîtrise du coût : le « gate » et le « focus »}232Pour borner le coût par appel :233\begin{itemize}234  \item \textbf{Project gate} : avant tout appel, une expression régulière de235  vocabulaire-projet (\code{\_PROJECT\_GATE}) filtre les sections. Une section236  sans signal de projet ne déclenche \emph{aucun} appel API. Le nombre d'appels237  facturés est donc bien inférieur au nombre total de sections.238  \item \textbf{Focus} : pour les sections retenues, seules les \emph{fenêtres}239  de texte autour des signaux de projet sont envoyées (budget $\approx$ 9\,000240  caractères, fenêtres fusionnées), le contenu total étant plafonné à241  $\approx$ 14\,000 caractères par appel quelle que soit la longueur de la242  section.243\end{itemize}244245\subsection{Schéma d'extraction (sortie JSON stricte)}246Le modèle reçoit une consigne système d'analyste financier et renvoie un objet247\code{\{"projects": [...]\}} où chaque projet respecte le schéma suivant :248249\begin{lstlisting}250{251  "project_name": "",        // nom court (officiel si mentionne)252  "project_type": "",        // EXACTEMENT un des 21 types de la taxonomie253  "description":  "",        // 1 phrase, ancree dans le texte (pas de speculation)254  "objective":    "",        // le but / le pourquoi255  "status": "planned | in_progress | completed | mentioned",256  "amount_usd": 0,           // montant USD si indique, sinon null257  "locations":    [], "technologies": [], "partners": [],258  "benefits":     [], "risks":        [], "years":    [],259  "confidence": 0.0          // 0..1 : a quel point c'est un vrai projet concret260}261\end{lstlisting}262263\paragraph{Règles imposées au modèle.} N'extraire que des initiatives réelles264(pas de \emph{boilerplate} de facteurs de risque ni d'hypothèses); ne pas265inventer de faits (montants et lieux doivent apparaître dans le texte);266préférer peu de projets de qualité à beaucoup de projets vagues. La température267est fixée à 0 et le mode JSON est activé. Les appels sont parallélisés268(\code{--workers}); une politique de reprise gère les codes 429 et 5xx.269270\paragraph{Post-traitement.} Chaque projet renvoyé est normalisé : le271\code{project\_type} est ramené à la taxonomie (correspondance exacte puis floue,272défaut \code{technology\_deployment}); le statut est validé; les montants sont273convertis en \code{float}; les listes sont nettoyées et tronquées. Un274identifiant de mention \textbf{stable} est calculé :275\[276\code{mention\_id} = \text{SHA-1}(\;\code{accession} \mid \code{section\_id}277\mid \code{type} \mid \code{anchor}\;)[0{:}20].278\]279Cette stabilité rend tout le pipeline \emph{incrémental et reprenable} :280ré-exécuter une extraction réinsère les mêmes lignes (\code{INSERT OR REPLACE})281sans double comptage. Les mentions de confiance $<$ 0{,}45 sont écartées.282283\paragraph{Résultat de l'exécution.} \textbf{39\,930} mentions extraites sur les284153\,894 sections, traitées en 34 lots d'entreprises (15 CIK par lot) avec285journal de points de reprise (\code{logs/extract\_done\_ciks.txt}).286287% =====================================================================288\section{Étape 3 — Résolution des projets}289% =====================================================================290Module : \code{spid/resolve.py}. Un même projet physique est généralement291mentionné dans plusieurs filings et sur plusieurs années. La résolution292\textbf{fusionne les mentions} (par entreprise, type de projet et ancre293normalisée) en projets uniques, chacun doté :294\begin{itemize}295  \item d'une \textbf{localisation canonique}, d'un \textbf{montant agrégé}, d'un296  \textbf{statut} courant et d'une \textbf{liste de technologies} consolidée;297  \item de dates \textbf{first\_seen / last\_seen} et d'années298  \textbf{first\_year / last\_year};299  \item d'un nombre de mentions et de filings, et d'une confiance moyenne;300  \item d'une \textbf{chronologie} (\code{project\_timeline}) conservant chaque301  mention datée, son formulaire, son statut, son montant et un extrait.302\end{itemize}303304\paragraph{Résultat de l'exécution.} 39\,930 mentions $\rightarrow$305\textbf{19\,227} projets distincts; 39\,930 lignes de chronologie conservées.306307% =====================================================================308\section{Étape 4 — Graphe de connaissances}309% =====================================================================310Module : \code{spid/graph.py}. À partir des projets résolus, on dérive un graphe311orienté de cinq types de n\oe uds et trois types d'arêtes, puis on l'exporte en312parquet et en Cypher (import Neo4j) dans \code{data/exports/}.313314\begin{table}[h]315\centering316\caption{Composition du graphe de connaissances (exécution complète).}317\begin{tabular}{llr}318\toprule319Type de n\oe ud & Préfixe d'identifiant & Nombre \\320\midrule321Project    & \code{P:}  & 19\,227 \\322Partner    & \code{PR:} & 7\,640 \\323Location   & \code{L:}  & 3\,080 \\324Technology & \code{T:}  & 1\,779 \\325Company    & \code{C:}  & 500 \\326\midrule327\textbf{Total n\oe uds} & & \textbf{32\,226} \\328\textbf{Total arêtes}   & & \textbf{33\,176} \\329\bottomrule330\end{tabular}331\end{table}332333Les arêtes relient : \code{Company} $\xrightarrow{\text{owns}}$ \code{Project},334\code{Project} $\xrightarrow{\text{uses}}$ \code{Technology}, et335\code{Project} $\xrightarrow{\text{located\_in}}$ \code{Location}.336337\begin{figure}[h]338\centering339\begin{minipage}{0.46\textwidth}\centering340\includegraphics[width=\textwidth]{fig_degree_dist.pdf}341\end{minipage}\hfill342\begin{minipage}{0.52\textwidth}\centering343\includegraphics[width=\textwidth]{fig_tech_network.pdf}344\end{minipage}345\caption{Le graphe de connaissances. \emph{Gauche} : distribution des degrés346(échelle log-log), à queue lourde, signature d'une structure proche du347« sans échelle ». \emph{Droite} : réseau de co-occurrence des technologies348(deux technologies reliées lorsqu'elles servent dans un même projet); la349détection de communautés révèle quatre écosystèmes technologiques350(modularité 0{,}52), les technologies de la transition énergétique occupant351les positions les plus centrales.}352\label{fig:graph}353\end{figure}354355\paragraph{Note de robustesse.} À l'échelle du corpus complet, la construction356du graphe heurtait une violation de clé primaire (identifiants de partenaires357repliés en minuscules avec étiquettes de casse variable; CIK aux nom/secteur358variables). La correction agrège ces n\oe uds par \code{GROUP BY} avec359\code{any\_value()}.360361% =====================================================================362\section{Étape 5 — Embeddings et recherche sémantique}363% =====================================================================364Module : \code{spid/embed.py}. Le texte de chaque projet (nom + description +365objectif) est encodé en un vecteur de \textbf{384 dimensions} par le modèle366\textbf{\code{all-MiniLM-L6-v2}} (\code{sentence-transformers}, local et367gratuit). Les vecteurs sont stockés dans \code{project\_embeddings} et permettent368la recherche sémantique (\code{spid semantic "AI projects launched by banks"})369par similarité cosinus, ainsi que le regroupement thématique en aval.370371\paragraph{Résultat de l'exécution.} \textbf{19\,227} embeddings (un par projet),372dimension 384.373374\begin{figure}[h]375\centering376\includegraphics[width=0.74\textwidth]{fig_embedding_tsne.pdf}377\caption{Projection t-SNE bidimensionnelle des embeddings de projets378(échantillon stratifié de 5\,000 projets), colorée par thème ($K$-means).379Les thèmes se séparent tout en se chevauchant aux frontières, reflétant380l'espace sémantique continu des initiatives d'entreprise et confirmant que381la structure non supervisée recouvre largement la taxonomie supervisée.}382\label{fig:tsne}383\end{figure}384385% =====================================================================386\section{Schéma de la base de données}387% =====================================================================388La base est un unique fichier DuckDB. SPID expose le corpus source en389\textbf{vues en lecture seule} (\code{src\_filings}, \code{src\_sections},390\code{src\_companies}, \code{v\_sections}) et écrit ses propres tables. Le tableau391ci-dessous récapitule les tables persistées.392393\begin{longtable}{p{3.4cm} r p{8.5cm}}394\toprule395Table & Lignes & Colonnes principales \\396\midrule397\endhead398\code{spid\_sections} & 27\,164 & section\_id (PK), accession\_number, section\_name, item\_number, text, word\_count \\399\addlinespace400\code{project\_mentions} & 39\,930 & mention\_id (PK), accession\_number, cik, section\_id, project\_name, project\_type, description, objective, amount\_usd, amount\_raw, locations[], technologies[], partners[], suppliers[], benefits[], risks[], years[], status, confidence, backend, ticker, company\_name, form\_type, filing\_date, fiscal\_year, sector \\401\addlinespace402\code{projects} & 19\,227 & project\_id (PK), cik, ticker, company\_name, sector, project\_type, project\_name, canonical\_location, technologies[], status, total\_amount\_usd, n\_mentions, n\_filings, first\_seen, last\_seen, first\_year, last\_year, avg\_confidence, description \\403\addlinespace404\code{project\_timeline} & 39\,930 & project\_id, accession\_number, filing\_date, form\_type, status, amount\_usd, confidence, snippet \\405\addlinespace406\code{kg\_nodes} & 32\,226 & node\_id (PK), node\_type, label, props (JSON) \\407\addlinespace408\code{kg\_edges} & 33\,176 & src, rel, dst, props (JSON) \\409\addlinespace410\code{project\_embeddings} & 19\,227 & project\_id (PK), model, dim, vector (FLOAT[]) \\411\bottomrule412\caption{Tables persistées par SPID dans \code{data/db/spid.duckdb}.}413\end{longtable}414415% =====================================================================416\section{Statistiques du jeu de données construit}417% =====================================================================418\begin{figure}[h]419\centering420\includegraphics[width=0.7\textwidth]{fig_mentions_by_year.pdf}421\caption{Mentions de projets extraites par année et par formulaire. Le corpus422est à peu près équilibré dans le temps (environ 2\,000 à 2\,800 mentions par an),423avec une croissance d'environ 2{,}2\,\% par an et un palier après 2020. Les 8-K424et les 10-K fournissent l'essentiel des signaux de projet.}425\label{fig:mentions}426\end{figure}427428\begin{figure}[h]429\centering430\begin{minipage}{0.49\textwidth}\centering431\includegraphics[width=\textwidth]{fig_type_distribution.pdf}432\end{minipage}\hfill433\begin{minipage}{0.49\textwidth}\centering434\includegraphics[width=\textwidth]{fig_sector_type_heatmap.pdf}435\end{minipage}436\caption{\emph{Gauche} : distribution des projets selon les 21 catégories de la437taxonomie (l'intégration post-M\&A domine). \emph{Droite} : composition en types438de projets par secteur GICS (parts normalisées par ligne) --- les secteurs se439spécialisent fortement (énergie/utilities dans la construction, TI dans le440déploiement technologique, santé dans les pipelines).}441\label{fig:typesector}442\end{figure}443444\begin{table}[h]445\centering446\caption{Répartition des projets par type (extrait des principaux types).}447\small448\begin{tabular}{lrr}449\toprule450Type de projet & Projets & Capital annoncé (G\$) \\451\midrule452M\&A integration        & 7\,274 & 14\,864{,}9 \\453Capex program           & 2\,085 & 4\,602{,}6 \\454Plant construction      & 1\,252 & 463{,}0 \\455Partnership             & 1\,239 & 440{,}4 \\456Cost reduction          & 1\,141 & 725{,}7 \\457Geographic expansion    & 1\,031 & 175{,}0 \\458Infrastructure          & 906    & 1\,002{,}3 \\459Product launch          & 819    & 48{,}8 \\460Technology deployment   & 698    & 190{,}4 \\461Manufacturing expansion & 552    & 145{,}6 \\462\bottomrule463\end{tabular}464\end{table}465466\begin{table}[h]467\centering468\caption{Répartition par secteur GICS (projets et capital annoncé).}469\small470\begin{tabular}{lrr}471\toprule472Secteur & Projets & Capital annoncé (G\$) \\473\midrule474Industrials            & 2\,708 & 2\,128{,}6 \\475Health Care            & 2\,475 & 2\,767{,}3 \\476Information Technology  & 2\,225 & 2\,931{,}4 \\477Consumer Discretionary  & 2\,220 & 1\,310{,}8 \\478Utilities              & 1\,956 & 2\,725{,}9 \\479Financials             & 1\,908 & 4\,832{,}3 \\480Consumer Staples       & 1\,483 & 1\,332{,}5 \\481Real Estate            & 1\,400 & 901{,}5 \\482Energy                 & 1\,109 & --- \\483Materials              & 914    & --- \\484Communication Services  & 829    & --- \\485\bottomrule486\end{tabular}487\end{table}488489\paragraph{Note sur les montants.} Le capital « annoncé » est la somme des490montants \emph{divulgués}, auto-déclarés et hétérogènes en portée; il doit se491lire comme un \textbf{ordre de grandeur supérieur} et non comme un total492d'investissement net (un même programme pluriannuel peut être mentionné --- et493compté --- dans plusieurs filings, et les très grandes valeurs d'entreprise de494M\&A dominent la somme).495496% =====================================================================497\section{Coût, débit et reproductibilité}498% =====================================================================499\begin{itemize}500  \item \textbf{Coût marginal} : de l'ordre du dixième de cent US par section501  traitée. L'exécution complète sur les 153\,894 sections est estimée à502  $\approx$ 100--130 \$ US de \code{gpt-4o-mini} aux tarifs courants.503  \item \textbf{Débit} : appels LLM parallélisés (16 \emph{workers});504  résolution, graphe et analytique sont du pur SQL DuckDB et passent à l'échelle505  de millions de mentions.506  \item \textbf{Mémoire bornée} : l'extraction complète est exécutée par lots de507  CIK (15 par lot) afin de ne pas matérialiser les 153\,894 sections d'un seul508  coup (ce qui dépassait la limite de 2 Go des tampons de chaînes Arrow de509  DuckDB; option \code{arrow\_large\_buffer\_size} activée par sécurité).510  \item \textbf{Reprenable} : grâce aux identifiants de mention stables511  (\code{INSERT OR REPLACE}) et à un journal de points de reprise par lot, une512  interruption ne re-facture jamais le travail déjà effectué.513\end{itemize}514515% =====================================================================516\section{Utilisation}517% =====================================================================518Interface en ligne de commande (depuis \code{project-db/}) :519\begin{lstlisting}[language=bash]520PY=../.venv/bin/python521522# 1. Sectionner les 10-K bruts (optionnel : ciblage par tickers/CIK)523PYTHONPATH=. $PY -m spid ingest --tickers NVDA,AAPL,MSFT524525# 2. Extraire les projets (backend LLM par defaut)526PYTHONPATH=. $PY -m spid extract --backend llm --forms 10-K,10-Q,8-K --workers 12527#    ... ou la base deterministe gratuite528PYTHONPATH=. $PY -m spid extract --backend rules --sample 50529530# 3. Resoudre, construire graphe + embeddings531PYTHONPATH=. $PY -m spid resolve532PYTHONPATH=. $PY -m spid graph533PYTHONPATH=. $PY -m spid embed534535# 4. Explorer536PYTHONPATH=. $PY -m spid analytics537PYTHONPATH=. $PY -m spid search "data center" --type data_center --min-amount 5e8538PYTHONPATH=. $PY -m spid semantic "AI projects launched by banks"539PYTHONPATH=. $PY -m spid stats540541# Tout le pipeline en une commande542PYTHONPATH=. $PY -m spid all --backend llm543\end{lstlisting}544545\paragraph{API HTTP optionnelle.} \code{uvicorn spid.api:app --port 8088}546expose \code{/projects}, \code{/semantic} et \code{/analytics}.547548\paragraph{Configuration.} Les secrets et paramètres sont dans549\code{project-db/.env} (non versionné) : \code{OPENAI\_API\_KEY},550\code{SPID\_LLM\_BASE\_URL}, \code{SPID\_LLM\_MODEL} (défaut \code{gpt-4o-mini}),551\code{SPID\_EMBED\_MODEL} (défaut \code{all-MiniLM-L6-v2}), \code{SPID\_BACKEND}.552553% =====================================================================554\section{Limites}555% =====================================================================556\begin{itemize}557  \item SPID mesure la \emph{divulgation} de projets, non les projets eux-mêmes :558  une initiative jamais évoquée dans un filing est invisible, et les incitations559  à divulguer varient selon les firmes et le temps.560  \item Les montants sont auto-déclarés, de portée inconsistante (coût total de561  programme, dépense annuelle, ou valeur de transaction) et souvent absents562  (48{,}5\,\% des projets en portent un).563  \item L'extraction LLM peut produire des faux positifs et des faux négatifs;564  le seuil de confiance et les contraintes d'ancrage les réduisent, mais il565  n'existe pas encore d'échantillon étiqueté manuellement assez grand pour566  estimer précisément précision et rappel.567  \item La résolution fusionne les mentions de façon heuristique : une fusion568  trop agressive sous-estime le nombre de projets, une fusion trop conservatrice569  le surestime.570  \item L'échantillon de 500 entreprises est orienté vers les grandes571  capitalisations américaines matures; la validité externe aux petites firmes ou572  aux firmes privées est limitée.573\end{itemize}574575% =====================================================================576\appendix577\section{Taxonomie complète des types de projets}578% =====================================================================579La taxonomie compte 21 catégories mutuellement exclusives580(voir \code{spid/taxonomy.py}) :581582\begin{multicols}{2}\small583\begin{enumerate}[leftmargin=*]584  \item \code{manufacturing\_expansion}585  \item \code{plant\_construction}586  \item \code{data\_center}587  \item \code{cloud\_migration}588  \item \code{ai\_initiative}589  \item \code{digital\_transformation}590  \item \code{erp\_implementation}591  \item \code{rd\_program}592  \item \code{product\_launch}593  \item \code{drug\_pipeline}594  \item \code{ma\_integration}595  \item \code{geographic\_expansion}596  \item \code{capex\_program}597  \item \code{supply\_chain}598  \item \code{automation}599  \item \code{sustainability}600  \item \code{energy\_transition}601  \item \code{infrastructure}602  \item \code{cost\_reduction}603  \item \code{partnership}604  \item \code{technology\_deployment}605\end{enumerate}606\end{multicols}607608\end{document}609
Files · main
Menu

Theme