Inspiration

Construction projects rarely lose money in dramatic ways. They lose it quietly, in invoices. A contract sets the rate, a purchase order confirms the order, and an invoice bills for it, yet these three documents almost never live in the same system, and no one checks all three together before a payment goes out. By the time a mismatch is noticed, if it is noticed at all, the money has already left. The scale of this surprised us: close to 39% of invoices contain some form of error, and manual review alone misses 1 to 4% of what is billed. Across a single project, that quietly adds up to thousands of dollars a year. It is a problem that is unglamorous, expensive, and, unlike many "AI for X" ideas, genuinely well suited to being solved with the tools available today. That combination is what drew us to it.

What it does

The system takes in a batch of vendor invoices, in whatever form they arrive, scanned, photographed, or as a PDF, and processes them together rather than one at a time. It identifies which vendor each invoice belongs to, retrieves the matching purchase order and contract, and checks every line item against the terms that were actually approved. Where a mismatch is found, it is flagged with the exact contract clause and the exact financial exposure involved, so nothing about the discrepancy is vague or open to interpretation. The system then goes a step further than most tools in this space: it drafts the resolution message that would actually be sent to the vendor, so there is nothing left for a procurement officer to write by hand.

How we built it

We designed the system as a pipeline, where each stage has one clear responsibility and hands its output to the next. Extraction is handled by a vision language model, since construction invoices are frequently scanned or photographed, and basic OCR tends to fail on tables, stamps, and handwritten annotations. Once an invoice is extracted, its vendor identity is matched against a master list and routed automatically to the correct purchase order and contract. From there, a retrieval step pulls only the contract clauses relevant to that specific vendor and invoice, rather than searching an entire document library. The actual comparison is handled by a separate, rule-based verification engine, deliberately kept outside the language model, so that every flag the system produces is explainable and can be traced back to a specific rule rather than a model's best guess. The final stage uses an AI agent to draft the vendor resolution message, grounded in the specific clause and dollar amount involved, producing something that could genuinely be sent as is, rather than a summary that still needs to be rewritten.

Challenges we ran into

The central design decision was how much of the system should rely on AI judgment versus fixed, deterministic rules. It would have been simpler to let a language model decide whether an invoice matches its contract, but that decision needed to be one a procurement officer could trust and defend later, so we kept that step rule-based by design, even though it meant more upfront work than a purely model-driven approach. Vendor identification at scale was another challenge worth solving properly rather than assuming away: invoices do not always carry a clear purchase order reference, and the same vendor can appear under slightly different names across documents. This meant building in fallback matching based on project and material details rather than depending on a single clean identifier. Working through problems like these, instead of settling for a simpler version of the idea that would not hold up under real use, is what shaped this into a system we believe is genuinely usable rather than only a demo.

Built With

  • agentic-ai
  • anthropic-api
  • asyncio
  • celery
  • chromadb
  • claude
  • document-intelligence
  • fastapi
  • gpt-4-vision
  • javascript
  • langchain
  • llamaindex
  • openai
  • pandas
  • pinecone
  • postgresql
  • pydantic
  • python
  • rag
  • rapidfuzz
  • react
  • sentence-transformers
  • streamlit
  • vector-embeddings
  • voyage-ai
Share this project:

Updates

Submission history