跳到正文
GitHub·· 7 天前AI 评分20

InvoiceGuard:面向马来西亚中小企业的 AI 发票录入与 MyInvois 预校验原型

joeriqi/invoiceguard-my

AI 导读

InvoiceGuard 是一个面向马来西亚中小企业的 AI 发票录入与 MyInvois 预提交校验原型,可读取 PDF、扫描件和手机照片,输出结构化 JSON 并按确定性电子发票规则校验,仅将高风险发票转人工。

正文

AI-assisted invoice intake and MyInvois pre-submission validation for Malaysian SMEs. It reads messy supplier invoices (PDF / scan / phone photo), proposes structured JSON, checks it against deterministic e-invoicing rules, and routes only risky invoices to a human.

Prototype on synthetic data. Not tax or legal advice. Regulatory rules are tagged [VERIFY] and must be confirmed against LHDN guidelines and the MyInvois SDK before real use.

Live dashboard: https://joeriqi.github.io/invoiceguard-my/ · Narrative: business problem → current process → bottleneck → AI opportunity → solution → prototype → ROI → roadmap

Results (held-out test split, 250 synthetic invoices)

System Basis Field acc. Critical-field exact STP Wrong auto-approvals
A OCR + regex measured (Tesseract) 78.4% 55.2% 73.6% 101
A+ OCR + regex + rules measured 78.4% 55.2% 39.2% 15
B LLM only simulated stand-in 97.8% 85.6% 100% 130
C InvoiceGuard (LLM + rules + router) simulated stand-in 97.8% 85.6% 33.2% (60.1% on error-free docs) 1
  • A and A+ are real measurements. B and C use SimLLMExtractor, a noise model with assumed error rates, not a real model run. Replace them with measured numbers via python -m invoiceguard.cli evaluate --extractor claude --limit 50 (needs an API key).
  • The corpus is error-rich on purpose (35% injected errors, 14% invoices ≥ RM10,000 that policy sends to humans), so headline STP is low.
  • The baseline's collapse on scans/photos depends on the degradation severity chosen in synth.degrade: read direction, not magnitude.
  • The one wrong auto-approval (IG-0075) is a scanned invoice whose total was misread by RM0.01. That sits inside the RM0.011 rule tolerance, so every rule passed. Tolerance is a trade-off, and a self-consistent misread is the residual risk of any rules-based gate.
  • Rules are only as strong as the extraction behind them: OCR+regex returns no line items, so line-based rules (V01/V03/V06) never fire.

Dashboard

dashboard/dist/index.html is one self-contained page: Overview & EDA · Evaluation · Review queue · Invoice inspector · ROI simulator. The Invoice inspector shows, for each test invoice, the extracted JSON next to what the document prints. You can edit the JSON and the validation rules re-run in your browser, flipping the decision. The browser rules are tested against the Python engine on every test invoice (tests/test_dashboard_js.py). Charts load Chart.js from cdnjs, so they need internet.

1 · Setup

Three things are needed: Python packages (pip), plus Poppler and Tesseract (not pip packages). make doctor checks all three and tells you exactly what is missing.

Windows (PowerShell)

# 1. Python 3.11+ from python.org (tick "Add python.exe to PATH"), then in the project folder:
python -m venv .venv
.\.venv\Scripts\Activate.ps1          # if blocked: Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
python -m pip install -r requirements.txt

# 2. External tools (one-time). Examples; check the exact package names with `winget search` / `scoop search`:
#    Tesseract: install the UB Mannheim Windows build (winget search tesseract). If it is not on PATH, set TESSERACT_CMD to the full path of tesseract.exe
#    Poppler:   scoop install poppler   (or: conda install -c conda-forge poppler; or unzip a release and set POPPLER_BIN to its bin folder)

# 3. Check, then run (open a NEW terminal after installing tools so PATH refreshes; keep the venv active)
python -m invoiceguard.cli doctor
make all                                  # or the equivalent commands below if you do not have make

Always run make / python in the same terminal where the venv is active, otherwise python is a different interpreter and you get ModuleNotFoundError: No module named 'yaml'.

make target Equivalent (any OS, no make needed)
make doctor python -m invoiceguard.cli doctor
make all python -m invoiceguard.cli all then python -m pytest -q
make pages python -m invoiceguard.cli pages
make app streamlit run app/streamlit_app.py

macOS / Linux

python -m venv .venv && source .venv/bin/activate
python -m pip install -r requirements.txt
sudo apt-get install -y tesseract-ocr poppler-utils       # macOS: brew install tesseract poppler
make doctor && make all                                   # data -> OCR baseline -> evaluate -> EDA -> dashboard -> tests (~5 min)
make app                                                  # Streamlit app at http://localhost:8501
make pages                                                # build the dashboard and copy it to docs/index.html for GitHub Pages

In VS Code: open the folder, pick the .venv interpreter (Ctrl+Shift+P, "Python: Select Interpreter"), accept the recommended extensions.

Reproducibility: a fresh clone with a new virtualenv reproduces the committed reports/*.csv and docs/index.html byte for byte. If a future library release ever changes something, install with -c constraints-tested.txt. The measured OCR baseline depends on the Tesseract and Poppler versions, so tiny differences on another machine are possible; doctor prints your versions (verified here with Poppler 24.02 and Tesseract 5.3.4).

2 · Repo map

config/params.yaml      all assumptions (seed, mix, simulator, router, ROI)      config/rules.yaml  rule catalogue
src/invoiceguard/       synth · extract · validate · route · evaluate · roi · eda · cli
notebooks/01_eda.py     EDA as VS Code "# %%" cells (also runs as a script)
app/streamlit_app.py    EDA · evaluation · human review UI · ROI simulator · live extraction
dashboard/              build_static.py + template.html -> dist/index.html
tests/                  rule unit tests · oracle test · ROI/extractor/router tests · JS-vs-Python parity test
docs/                   business_problem.md · roadmap.md · evidence_log.csv

3 · Pipeline

generate (300 invoices, 8 layouts, EN/BM, noise, injected errors, fixed seed, 50 dev / 250 test) → baseline (pdftotext / Tesseract cache) → evaluate (4 systems) → eda → dashboard. Tune only on dev; report only test. A clean rebuild reproduces identical results.

4 · Validation rules (config/rules.yaml)

V00 unreadable field · V01 Σlines = subtotal · V02 subtotal + tax = total · V03 qty × price = line · V04 currency / FX rate · V05 TIN present, well-formed, known (lookup is a mock of the MyInvois TIN API) · V06 tax code list · V07 ≥ RM10,000 · V08 duplicate · V09 future date · V10 passport ID ≤ 12 · V11 no UIN. Code lists in codes.py are an illustrative subset; replace them from the SDK.

5 · Tests

make test: 26 tests. The oracle test validates the ground truth and requires every injected error to fire exactly its expected rule with zero false alarms. The parity test (needs Node and a built dashboard) checks the browser rules against Python on 500 invoice-system pairs.

6 · Real extractor

cp .env.example .env     # add ANTHROPIC_API_KEY; model name via INVOICEGUARD_MODEL (check the current model list)
python -m invoiceguard.cli evaluate --extractor claude --limit 50    # synthetic invoices only

Adds C_invoiceguard_claude (measured) to results and dashboards. Expect lower catch rates than the simulator.

7 · Hosting

  • Static dashboard: make pages, push, then Settings ▸ Pages ▸ Branch main, folder /docs. Or drop dashboard/dist/index.html into Netlify Drop.
  • Streamlit: Streamlit Community Cloud (main file app/streamlit_app.py) or Docker (docker build -t invoiceguard . && docker run -p 8501:8501 invoiceguard).

8 · Honest limits

Synthetic data only · simulator ≠ real model · TIN lookup mocked · code lists illustrative · ROI inputs are assumptions · regulatory facts (dates, RM10,000 rule, penalties, the reported 24 Oct 2026 validation change) are [VERIFY] items · no client results are claimed.

来源:GitHub · github.com