An AI-drafted investment memo where every number shows its working.
AI writes a plausible investment memo in seconds. The problem is the next hour, where an associate re-checks every figure against the data room because nobody can tell which numbers came from the accounts and which the model invented. That verification cost is why most AI drafting tools quietly stop being used after week three.
This tool inverts it. It drafts from source documents only, cites the exact page behind every figure, and then grades its own output:
traceable figures : 24/26 (92%)
invalid citations : 0
unsupported claims: 2
- EBITDA margin of 18% is expected to hold through FY26.
- Management estimates a further £400k of synergies.
Two uncited claims, surfaced by name. That is the whole point: you check two sentences instead of twenty-six.
- Extract: every page of every PDF in a folder becomes a numbered passage tagged with its document and page number.
- Draft: the model writes the memo from those passages only, and must
follow each figure with the citation it came from, like
[3]. - Verify: this is the part that matters, and it runs offline with no API key. It finds every figure in the draft, checks whether the sentence containing it cites a real passage, and reports coverage.
Verification catches three separate failures: a number with no citation, a citation pointing at a passage that does not exist, and a claim asserted without evidence.
pip install -r requirements.txt
# extract, draft, verify, write a Word file
export ANTHROPIC_API_KEY=...
python cited_memo.py draft ./filings --out memo.docx
# verify a draft that already exists, no API key needed
python cited_memo.py check memo.md --sources ./filings--out memo.md writes markdown instead. Both formats append a Sources table
mapping every citation to its document and page, plus the provenance report.
check exits non-zero if any citation points at a passage that does not exist,
so it drops into CI or a pre-send hook.
python test_cited_memo.pyFive assertions covering the cases that matter: cited figures counted, uncited figures flagged, citations to non-existent passages rejected, prose without figures ignored, and multiples/percentages recognised as figures.
Page-level citations, not span-level. A page is small enough to check a number against in a few seconds and large enough to survive imperfect PDF text extraction. Span-level citation looks more precise and breaks more often.
Attribution is sentence-scoped. A figure counts as traceable if its sentence cites a real passage. That is good enough to catch an uncited number, which is the actual failure mode. Marked in the source where it would need to change.
Coverage is a number, not a claim. "AI-assisted, human-verified" means nothing. 92% traceable, with the other 8% named, means something.
Python, pypdf for extraction, the Anthropic API for drafting, python-docx
for Word output. No framework.
I write investment memos and run buy-side diligence for PE funds. The bottleneck was never the writing.