SPID — SEC Project Intelligence Database
Reconstructs the strategic project portfolio of public companies directly from raw SEC filings and makes those projects searchable, analyzable, and investable — a home-grown analogue of a Capital IQ / PitchBook / Gartner-style intelligence layer, but project-centric.
Instead of treating 10-K / 10-Q / 8-K filings as financial documents, SPID treats them as a massive source of project intelligence: new products, R&D programs, AI initiatives, manufacturing/plant expansions, data centers, cloud/ERP migrations, M&A integrations, capex programs, geographic expansions, partnerships, energy-transition and sustainability programs, drug pipelines, automation, and more.
Why this repo is small but the database is large
It is built on top of the existing UQO EDGAR Research DB corpus that already lives in
../data:
| Asset | Size | Used by SPID |
|---|---|---|
data/raw/sec/ |
88 GB, 500 companies | raw 10-K HTML (ingested on demand) |
data/parquet/filings/ |
134,124 filings | filing metadata (cik, ticker, dates, form) |
data/parquet/filing_sections/ |
127,800 sections (10-Q + 8-K) | pre-segmented section text |
data/parquet/companies/ |
company metadata | sector / SIC / state enrichment |
SPID adds the project layer: extraction → resolution → timelines → knowledge graph →
embeddings → search → analytics, persisted in a single DuckDB file (data/db/spid.duckdb).
Note: the upstream corpus only sectioned 10-Q and 8-K filings. SPID's
ingestcommand cleans and sections the raw 10-K HTML (Items 1, 1A, 2, 7, 7A) so 10-Ks flow through the same pipeline.
Architecture
┌──────────────────────────────────────────────┐
raw 10-K HTML ───────► │ ingest.py (clean + section Items 1/1A/2/7) │
(data/raw/sec) └──────────────────────────────────────────────┘
│
filing_sections.parquet ───────────────┼──────────► v_sections (unified feed)
(10-Q / 8-K, pre-parsed) │
▼
┌──────────────────────────────────────────────┐
│ EXTRACT (pluggable backend) │
│ • rules — deterministic, zero-cost │
│ • llm — gpt-4o-mini, JSON mode (default) │
└──────────────────────────────────────────────┘
│ project_mentions
▼
┌──────────────────────────────────────────────┐
│ RESOLVE — merge mentions across filings/years│
│ into projects + timelines │
└──────────────────────────────────────────────┘
│ projects, project_timeline
┌───────────────┼────────────────┐
▼ ▼ ▼
knowledge graph embeddings analytics
(nodes/edges, (MiniLM 384-d, (type/sector/
Cypher export) semantic search) geo/tech/AI)Project schema (per mention)
{
"project_name": "", "project_type": "", "description": "", "objective": "",
"status": "planned|in_progress|completed|mentioned",
"amount_usd": 0, "locations": [], "technologies": [], "partners": [],
"benefits": [], "risks": [], "years": [], "confidence": 0.0
}project_type is drawn from a controlled vocabulary of 21 categories
(see spid/taxonomy.py): manufacturing_expansion, plant_construction, data_center, cloud_migration, ai_initiative, digital_transformation, erp_implementation, rd_program, product_launch, drug_pipeline, ma_integration, geographic_expansion, capex_program, supply_chain, automation, sustainability, energy_transition, infrastructure, cost_reduction, partnership, technology_deployment.
Quick start
cd project-db
PY=../.venv/bin/python # repo virtualenv (duckdb, httpx, sentence-transformers …)
# 1. (optional) section raw 10-Ks for the companies you care about
PYTHONPATH=. $PY -m spid ingest --tickers NVDA,AAPL,MSFT,CAT,XOM
# 2. extract projects with gpt-4o-mini (default backend)
PYTHONPATH=. $PY -m spid extract --tickers NVDA,AAPL,MSFT --forms 10-K,10-Q,8-K --workers 12
# …or the zero-cost deterministic baseline
PYTHONPATH=. $PY -m spid extract --backend rules --sample 50
# 3. resolve mentions → projects + timelines, build graph + embeddings
PYTHONPATH=. $PY -m spid resolve
PYTHONPATH=. $PY -m spid graph
PYTHONPATH=. $PY -m spid embed
# 4. explore
PYTHONPATH=. $PY -m spid analytics
PYTHONPATH=. $PY -m spid search "data center" --type data_center --min-amount 5e8
PYTHONPATH=. $PY -m spid semantic "AI projects launched by banks"
PYTHONPATH=. $PY -m spid project <project_id>
PYTHONPATH=. $PY -m spid statsspid all [extraction flags] runs extract → resolve → graph → embed → analytics in one shot.
Optional HTTP API
PYTHONPATH=. ../.venv/bin/uvicorn spid.api:app --port 8088
# GET /projects?type=data_center&min_amount=5e8 GET /semantic?q=... GET /analyticsExtraction backends
| Backend | Cost | Quality | Use |
|---|---|---|---|
rules |
free, fast | high-precision signals, generic names | bulk first-pass / offline |
llm (gpt-4o-mini) |
~$0.0008 / section | named projects, amounts, status, objectives | production extraction |
Configured in .env (gitignored):
OPENAI_API_KEY=sk-...
SPID_LLM_BASE_URL=https://api.openai.com/v1
SPID_LLM_MODEL=gpt-4o-mini
SPID_BACKEND=llmThe LLM client is OpenAI-compatible, so the same code targets the MacLustr cluster gateway
(https://llm.maclustr.io/v1, maclustr-general) or any local model by changing two env vars.
Scaling to the full corpus
The pipeline is incremental (INSERT OR REPLACE on stable mention IDs) and resumable.
- Cost control: the LLM extractor sends only project-relevant windows of each section
(
_focus), so per-call cost is bounded regardless of section size. - Throughput: LLM calls are threaded (
--workers); resolution/graph/analytics are pure DuckDB SQL and scale to millions of mentions. - Full run estimate: ~127,800 pre-parsed sections + ~7,655 10-Ks ≈ $100–130 of
gpt-4o-mini at current pricing. Run per-sector or per-cohort with
--tickers/--ciks.
Roadmap hooks already in place
- Add forms (S-1, DEF 14A, 20-F, 6-K, transcripts, press releases) → extend
ingest.py+ theformsfilter; everything downstream is form-agnostic. - Swap embeddings to pgvector / Qdrant / Weaviate → the
project_embeddingsvector column is the only touch point (embed.py). - Load the knowledge graph into Neo4j →
data/exports/kg_import.cypheris generated byspid graph.
Module map
| File | Responsibility |
|---|---|
spid/config.py |
paths, settings, .env loader |
spid/taxonomy.py |
project-type vocabulary, tech/status/geo/money extractors |
spid/store.py |
DuckDB schema + read-only views over the source parquet |
spid/ingest.py |
raw 10-K HTML → sectioned spid_sections |
spid/extract/rules.py |
deterministic extractor |
spid/extract/llm.py |
gpt-4o-mini extractor (JSON mode) |
spid/pipeline.py |
threaded extraction engine |
spid/resolve.py |
mentions → projects + timelines (SQL) |
spid/graph.py |
knowledge graph + Cypher/parquet export |
spid/embed.py |
embeddings + semantic search |
spid/search.py |
structured / keyword search |
spid/analytics.py |
dashboards |
spid/api.py |
optional FastAPI service |
spid/__main__.py |
CLI (python -m spid …) |
Built on the UQO EDGAR Research DB. Academic / research use.