ai_sections.html pastes into the no-AI dashboard.html; ai_bridge.py adds one ai_request slot that hands every AI contract request (incl. GET /roi) to the review backend's dispatch(). Desktop page check reruns the web review and cost cases plus a tampered-page gate case. Eval fixture e-pyqt-ai added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
32 lines
996 B
Python
32 lines
996 B
Python
"""Invoice intake bot: picks up scanned invoices and extracts their fields with an LLM.
|
|
Start it with: python -m bot"""
|
|
import time
|
|
from pathlib import Path
|
|
|
|
INBOX = Path(__file__).with_name("inbox")
|
|
|
|
|
|
def say(line):
|
|
print(line, flush=True)
|
|
time.sleep(0.2)
|
|
|
|
|
|
def main():
|
|
say("[step 1] Initializing")
|
|
docs = sorted(INBOX.glob("*.pdf"))
|
|
say(f"[inbox] {len(docs)} invoices waiting")
|
|
say("[step 2] Extracting fields")
|
|
for i, doc in enumerate(docs, 1):
|
|
try:
|
|
from extractor import extract_invoice # the LLM call
|
|
rows = extract_invoice(doc.read_bytes(), "application/pdf")
|
|
say(f"[extract] {doc.name}: {len(rows)} fields ({i}/{len(docs)})")
|
|
except Exception as e: # one bad document must not stop the batch
|
|
say(f"ERROR: extraction failed for {doc.name}: {type(e).__name__}")
|
|
say("[step 3] Queueing for review")
|
|
say(f"[all done] {len(docs)} invoices processed")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|