The problem
The client buys multifamily buildings. An offering memo arrives as a designed PDF. The rent roll arrives as a spreadsheet from the seller, sometimes a second PDF. Analysts were reading both and building a list of figures that did not match: unit counts, in-place rent, concessions, occupancy. A first pass took about eleven days, and the list was still incomplete because the memo buries a number in a caption.
The acquisitions lead did not want a generated memo. They wanted the conflicts, each one pointing at the page in the memo and the row in the rent roll. A number with no source was a finding, not something for the model to resolve by averaging.
Why conflicts, not a cleaned memo
The memo is a sales document. Cleaning it into a single 'true' rent figure hides the disagreement the analyst is paid to see. The work product is a list of mismatches and a list of memo figures the rent roll does not support. Someone on the deal decides what to believe.
Architecture
Two extractions, kept separate
We extract memo figures with the page and the caption, and rent-roll rows with the sheet and the cell. We do not merge them into one table and throw away the provenance. The comparison runs after both extractions, on unit or line identifiers the analyst confirmed for that deal.
A missing source is a row, not a blank
If the memo states an occupancy number and no rent-roll cell maps to it, the output says the rent roll does not support that figure. It does not copy the memo number into the roll to make the sheet tidy.
Only the conflicts go to the analyst
Matches are counted and stored. The review screen is the conflicts and the unsupported figures, which is the eleven-day reading the team was actually doing.
The analyst still writes the investment view
Nothing in this workflow drafts the investment memo or the bid. It stops at the fact check.
Challenges and tradeoffs
- Unit identifiers were inconsistent. The memo used a marketing unit label and the roll used a lease id. The first comparison under-matched and flooded the analyst with false conflicts. We added a mapping step the analyst confirms once per deal, and the rest of the check uses that map.
- Captions held the number the table did not. A occupancy figure in a photo caption was missed by a table-only extractor. Page-level extraction, with the caption kept attached to the number, closed that gap on the sample deals.
- Scanned exhibits were not the same problem as digital PDFs. Two seller exhibits were scans. We ran those through the same document path the client already used for leases, and we marked scan confidence on the row so a low-confidence cell is reviewed rather than compared as if it were typed.
Results
On the pilot deals, the first-pass conflict list was ready in two days, against eleven days for the prior process on deals of a similar size. Every figure on the list was tied to a memo page or a rent-roll cell, or marked as unsupported. Analysts still decided which figure the deal used.
The investment memo is still written by the team. The eleven days were never the writing. They were the hunt.
What we'd do differently
We would have asked for the unit-id map before building the comparison. We built it against an assumed shared id, and the first deal did not have one.