You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When a card is generated for an MP, each donor name that isn't already in the donor_company_links database triggers an individual Claude Haiku call to resolve it:
# _classify_donor() in card.py (simplified)link=db.get_donor_company_link(donor_name) # DB lookup firstifnotlink:
link=resolve_person_to_company(donor_name) # → Claude Haiku call
These calls are made sequentially inside a loop over all donors. An MP with 20 unknown donors makes 20 sequential Haiku calls before the card can render, adding 1–3 s per unknown donor to first-generation latency.
Once resolved, results are saved to donor_company_links permanently — so each donor is only resolved once ever. But for new MPs or newly declared donors, the first card generation can take 20–60 s.
Proposed fix
Option A — Parallelize with ThreadPoolExecutor (quick win)
Run all resolve_person_to_company calls concurrently within generate_card:
This reduces latency from N × 2s to approximately max(individual calls) ≈ 2–5 s regardless of donor count.
Option B — Pre-resolve donors in a background job (thorough)
Add a resolve_donors management command that iterates all known donors in donor_company_links and fills gaps in bulk. Run it after each ingestion pass in paidup-intelligence. Card generation then always hits the DB cache.
Option C — Batch Haiku call (most efficient)
Send all unknown donor names in a single Haiku prompt and parse a structured response. Cuts API calls from N to 1, at the cost of some prompt engineering.
Recommended approach
Start with Option A (parallelization) as a one-line change with immediate impact. Follow with Option B (pre-resolution job) to eliminate the cold path entirely for known MPs.
Notes
resolve_person_to_company lives in card.py
Results are stored in donor_company_links via database.py — the DB write happens inside the function
Parallel writes to donor_company_links should be safe as the table has a unique constraint on donor name and upserts are idempotent
Problem
When a card is generated for an MP, each donor name that isn't already in the
donor_company_linksdatabase triggers an individual Claude Haiku call to resolve it:These calls are made sequentially inside a loop over all donors. An MP with 20 unknown donors makes 20 sequential Haiku calls before the card can render, adding 1–3 s per unknown donor to first-generation latency.
Once resolved, results are saved to
donor_company_linkspermanently — so each donor is only resolved once ever. But for new MPs or newly declared donors, the first card generation can take 20–60 s.Proposed fix
Option A — Parallelize with ThreadPoolExecutor (quick win)
Run all
resolve_person_to_companycalls concurrently withingenerate_card:This reduces latency from
N × 2sto approximatelymax(individual calls)≈ 2–5 s regardless of donor count.Option B — Pre-resolve donors in a background job (thorough)
Add a
resolve_donorsmanagement command that iterates all known donors indonor_company_linksand fills gaps in bulk. Run it after each ingestion pass inpaidup-intelligence. Card generation then always hits the DB cache.Option C — Batch Haiku call (most efficient)
Send all unknown donor names in a single Haiku prompt and parse a structured response. Cuts API calls from N to 1, at the cost of some prompt engineering.
Recommended approach
Start with Option A (parallelization) as a one-line change with immediate impact. Follow with Option B (pre-resolution job) to eliminate the cold path entirely for known MPs.
Notes
resolve_person_to_companylives incard.pydonor_company_linksviadatabase.py— the DB write happens inside the functiondonor_company_linksshould be safe as the table has a unique constraint on donor name and upserts are idempotent