Skip to content

Repository files navigation

alibi

Local-first financial document intelligence. Extracts structured data from photos of receipts, invoices, and financial documents using local OCR. Matches documents across sources. Learns from corrections. Privacy-first: 64% of documents processed entirely locally with zero cloud API cost.

API-first architecture: every feature is available through the REST API. The CLI, Telegram bot, MCP server, and web UI are all thin clients over the same service layer.

Services & URLs

Once running, alibi exposes these interfaces (all thin clients over the same REST API). Defaults assume a local host:

Interface URL / address Start Notes
Web UI http://localhost:3100/web uv run lt serve User management + enrichment dashboard (self-contained single-page app)
REST API http://localhost:3100 uv run lt serve API-first; every feature. Swagger below
API docs (Swagger) http://localhost:3100/docs uv run lt serve Interactive OpenAPI explorer
Health check http://localhost:3100/health uv run lt serve Liveness probe (returns 200)
Telegram bot your bot in Telegram ./docker/run-telegram-bot.sh up Thin HTTP client of the API; runs as an OrbStack container
Datasette explorer http://127.0.0.1:8001 ./scripts/run-datasette.sh Read-only record browser over a WAL-safe DB snapshot. See docs/DATASETTE_EXPLORER.md

Host/port are configurable via ALIBI_API_HOST (default 127.0.0.1) and ALIBI_API_PORT (default 3100) — see .env.example. The Telegram container reaches the host API at host.docker.internal:3100 (ALIBI_API_URL).

For a persistent deployment, run the API and Datasette as launchd agents (macOS) or systemd units (Linux) and the bot as its container, so they survive logout and restart on boot.

Why alibi?

Receipt scanners extract vendor + total. Expense trackers require manual data entry. Cloud APIs charge per scan and see all your data.

Alibi does more:

  • Line-item extraction: individual products with quantity, unit, price, brand, category, tax, barcode -- not just totals
  • Cross-document matching: a receipt + a bank statement + a payment confirmation = one confirmed financial fact, with split payment detection
  • Cross-vendor price comparison: comparable_unit_price normalizes EUR/kg, EUR/L, EUR/pcs across vendors. comparable_name translates product names across languages. Answer "where is milk cheapest?" across stores and countries
  • Product variants: tracks that 3% milk differs from 1.5%, L eggs from M eggs, organic from conventional -- at the schema level, not as free text
  • Price factor analysis: discovers why prices differ (brand premium, organic markup, vendor pricing) from your data
  • Vendor intelligence: VAT-based identity resolution, POS system signature detection (16 systems), template learning per vendor
  • Privacy controls: 5-tier data masking (T0-T4, fully masked to full detail) and 3-level anonymization export (categories-only, pseudonymized, statistical)
  • Product enrichment: 8-tier cascade from Open Food Facts to Gemini, with provenance tracking and optional contribution back to OFF
  • Adaptive learning: gets smarter with every correction -- templates, categories, vendor defaults, extraction quality self-diagnostics
  • Local-first: Ollama (glm-ocr 1.1B) for OCR, heuristic parser handles 64% of documents without any LLM

The core data model -- Atoms (raw observations) -> Clouds (probabilistic clusters) -> Facts (confirmed events) -- is a general epistemological pattern for turning uncertain observations into confirmed knowledge.

Document-agnostic by design

Alibi works with whatever you have. A single POS slip records the amount and vendor. A receipt adds item-level detail. A bank statement confirms the transaction from the bank's side. When multiple documents describe the same purchase, they validate each other and collapse into a single fact with richer data -- each document type is another dimension, not a duplicate. The system never requires a specific document type; one is enough, several are better.

Human-editable YAML intermediaries

Every processed document produces a .alibi.yaml file alongside the original image/PDF. This YAML file is the single source of truth between the document and the database:

document_type: receipt
vendor: Alphamega
vendor_vat: "10XXXXXXY"
date: "2026-03-01"
currency: EUR
total: 45.67
subtotal: 43.25
tax_total: 2.42
payment_method: card
line_items:
  - name: Organic Milk 1L
    quantity: 2
    unit: l                  # measurement dimension (l for liquids, kg for weight, pcs for counted)
    unit_quantity: 1.0       # package size in unit dimension (1.0L) — enables EUR/L comparison
    unit_price: 2.35
    total_price: 4.70
    tax_rate: 5.0
    brand: ""                # filled by enrichment cascade
    category: ""             # filled by enrichment cascade
    product_variant: ""      # subcategory: "3%" for milk fat, "L" for egg size
    barcode: ""              # detected from receipt or photo

If the extraction got something wrong, you edit the YAML (it is designed to be human-readable) and re-run lt process — the updated values replace the previous database records. The unit + unit_quantity pair is key to comparison: unit is the measurement dimension (l for liquids, kg for weight, pcs for counted items) and unit_quantity is the package size in that dimension. This enables comparable_unit_price (e.g., EUR/L across different milk brands and package sizes). This gives you full control over your data without needing to understand the database schema.

Quick Start

Prerequisites

  • Python 3.12+
  • uv (Python package manager)
  • Ollama with the glm-ocr model

Optional system dependencies:

  • poppler — for PDF processing (brew install poppler / apt install poppler-utils)
  • zbar — for barcode scanning (brew install zbar / apt install libzbar0)

Install

git clone https://github.com/viberesearch/alibi.git
cd alibi

# Core install (CLI + API + OCR processing)
uv sync

# Full install (all optional features)
uv sync --extra all

# Pull the OCR model
ollama pull glm-ocr

# Optional: pull the local LLM for Stage 3 structuring + local enrichment
ollama pull gemma4:12b

Configure

cp .env.example .env
# Edit .env — only ALIBI_OLLAMA_URL is truly required
# See .env.example for the full list of options

cp data/vendor_aliases.example.yaml data/vendor_aliases.yaml
cp data/unit_aliases.example.yaml data/unit_aliases.yaml

Run

# Initialize the database
uv run lt init

# Process a receipt photo
uv run lt process -p ~/path/to/receipt.jpg

# View extracted facts
uv run lt facts list

# Start the API server (interactive docs at http://localhost:3100/docs)
uv run lt serve

Architecture

Client (CLI / REST API / Telegram / MCP / Web UI)
  |
  v
Service Layer (alibi/services/ — 13 facades, ~88 functions)
  |
  +---> Extraction Pipeline (3-stage hybrid)
  |       Stage 1: OCR (glm-ocr, local, 1.5-6s)
  |       Stage 2: Heuristic parser (~2ms, handles 64% of docs)
  |       Stage 3: LLM structuring (local gemma4:12b OR cloud Gemini 3.5 Flash)
  |
  +---> Atom-Cloud-Fact Pipeline
  |       atoms/parser -> clouds/formation -> clouds/collapse
  |
  +---> SQLite (schema v44, 23+ tables + FTS5 index)
  |
  +---> Event Bus -> Obsidian notes, webhooks, analytics export

Stack: Python 3.12, FastAPI, SQLite, Ollama, pydantic-settings, httpx, Pillow. Optional: Google Gemini, Anthropic Claude, aiogram (Telegram), pyzbar (barcodes), lancedb (vectors).

Stage 3: Local vs Cloud

The extraction pipeline's Stage 3 (LLM correction) supports two backends:

Local (Ollama) Cloud (Gemini)
Model gemma4:12b Gemini 3.5 Flash
Cost Free ~$0.001/doc
Speed 2-5s 0.5-1s
RAM ~8GB None
Privacy Full Product names only (no PII)
Config Default ALIBI_GEMINI_EXTRACTION_ENABLED=true

Most documents (64%) are handled by the heuristic parser alone, making Stage 3 a fallback for complex/unusual documents.

Features

Extraction

  • Human-editable YAML intermediaries (.alibi.yaml) -- edit and re-ingest to correct data
  • 3-stage hybrid pipeline: OCR -> heuristic parser -> conditional LLM
  • Per-item extraction: quantity, unit, price, brand, category, tax, barcode
  • Product variant extraction: fat %, egg size (L/M/S), organic, light, strained, unsalted
  • Cash flow tracking: amount tendered and change due (when payment_method=cash)
  • Folder-based document routing with country/vendor/type inference from directory structure
  • Multi-language OCR with fallback models for non-Latin scripts (Greek, Russian, CJK)
  • POS system signature detection (16 systems) to bootstrap vendor templates
  • Image optimization on ingest (EXIF stripping, resize, compression)
  • Duplicate detection: file hash (MD5) + perceptual hash (aHash) + fuzzy vendor matching
  • Barcode detection from receipt photos (EAN/UPC/QR via pyzbar)
  • CSV and OFX import for bank statements and transaction data

Data Model

  • Atom-Cloud-Fact pipeline: observations -> probabilistic clusters -> confirmed events
  • Cross-document matching (receipt + payment confirmation + bank statement = one fact)
  • Split payment detection: multiple payment methods summing to one transaction
  • Vendor identity resolution (VAT number, tax ID, fuzzy name matching)
  • Vendor template learning with reliability tracking (6 learned fields per vendor)
  • Annotations: open-ended key-value metadata on any entity (tags, notes, product attributes)
  • Budget system: scenarios with parent/child categories, variance tracking, period-based alerts

Enrichment

  • 8-tier cascade: historical -> Open Food Facts -> UPCitemdb -> GS1 prefix -> fuzzy name -> local LLM -> Gemini -> Anthropic
  • Combined local pass (lt enrich all): fills unit, comparable_name, category and attributes in one LLM call per vendor batch (~4x fewer round-trips), with single-field fallbacks
  • Cross-language product comparison via comparable_name (e.g., "ΓΑΛΑ ΠΛΗΡΕΣ" -> "whole milk")
  • Comparable-name canonicalization: tidy-comparable-names strips leftover size/pack tokens deterministically; propose-name-merges / apply-name-merges cluster semantic duplicates (synonyms, singular/plural, OCR garble) by embedding similarity within each unit, human-review-gated (never auto-merges)
  • Product state facet: a controlled vocabulary (fresh / frozen / canned / dried / cured / pickled / roasted / cooked) written into each item's attributes, distinguishing forms of the same food the unit alone can't — fresh vs canned artichokes, raw vs roasted cashews, fresh vs smoked salmon (lt enrich states)
  • Flexible per-item attributes JSON (size, fat %, organic, free-range, lactose-free, state, ...) filterable/groupable independently
  • Enrichment provenance tracking with user feedback loop (confirm/reject via Web UI or Telegram)
  • Cross-vendor barcode matching (shared EAN/UPC propagation)
  • Nutritional tracking: joins purchased items with OFF product data for per-item nutritional estimates
  • Open Food Facts contribution: optionally submit enriched products back to OFF
  • Scheduled enrichment daemon: automatic background processing on staggered intervals

Analytics & Comparison

  • Item-as-star analytics (item_stars mirror + lt items): a denormalized per-FactItem view for fast aggregations — average comparable price by product/vendor/category (avg-price), price trends over time (trend), basket composition (basket); always grouped by comparable_unit so EUR/L is never blended with EUR/piece; rebuilt on collapse and after bulk enrichment (rebuild)
  • Cross-vendor price comparison: comparable_unit_price normalizes to EUR/kg, EUR/L, EUR/pcs across vendors and package sizes
  • Price factor analysis: discovers price drivers from data (brand premiums, organic markups, vendor pricing strategies)
  • Product variant comparison: compare 3% milk vs 1.5% milk, L eggs vs M eggs across vendors
  • Subscription detection (k-means on recurring amounts with period classification)
  • Anomaly detection (statistical outlier detection with baseline drift and severity scoring)
  • Correction confusion matrix: self-diagnostics showing which extraction fields need improvement
  • Location analytics (spending heatmap, branch comparison, nearby vendors)
  • Period comparison (month-over-month, year-over-year, category trend analysis)
  • MindsDB predictors (spending forecast, category classification)
  • All data accessible via MCP for LLM-powered natural language analytics

Privacy & Data Control

  • 5-tier data masking (T0-T4): amounts hidden/rounded/exact, vendor=category/name, dates=month/exact, line items included/excluded, provenance included/excluded
    • CLI: lt export masked output.json --tier 2, API: GET /api/v1/export/masked/transactions?tier=2
  • 3-level anonymization export: categories_only (safe for any external use), pseudonymized (consistent fake names, shifted amounts, preserves patterns), statistical (aggregates only)
    • CLI: lt export anonymized data.json --level pseudonymized --key-file key.json, API: POST /api/v1/export/anonymized?level=statistical
  • Cloud AI masking: automatically masks sensitive entities before sending to cloud APIs, with reversible masking maps
  • Snapshot & diff: detect out-of-band edits (e.g., direct SQL changes in TablePlus) and track them as correction events
  • Backup and restore: compressed archives with manifest and checksum verification (lt db backup/restore)

Adaptive Learning

  • Template reliability tracking per vendor (6 fields: date format, total marker, header/footer ratio, language, layout type)
  • Correction feedback loops with sibling propagation (correct one item, similar items update)
  • Cloud formation weight learning from merge/split history
  • OCR spell correction using identity database as dictionary
  • Barcode position learning per POS/vendor
  • Extraction quality self-assessment: correction confusion matrix highlights weak fields

Interfaces

Alibi is API-first — the REST API is the primary interface. All other interfaces (CLI, Telegram, MCP) call the same service layer. The Telegram bot is a thin HTTP client of the API, and the read-only Datasette explorer sits beside it for browsing and analysing records.

REST API

Start the server:

uv run lt serve
  • Interactive API docs: http://localhost:3100/docs (Swagger UI)
  • Web UI: http://localhost:3100/web (user management and enrichment dashboard)

Key endpoints:

Method Path Description
POST /api/v1/process Process a document
GET /api/v1/facts List facts (paginated)
GET /api/v1/facts/{id} Fact detail with items
POST /api/v1/search Search by vendor/items
GET /api/v1/analytics/* Spending, subscriptions, anomalies
GET /api/v1/identities Vendor identities
PATCH /api/v1/line-items/{id} Update item enrichment
POST /api/v1/enrichment/run/* Trigger enrichment (cloud/llm/gemini)
GET /api/v1/corrections Correction event log
GET /api/v1/nutrition/summary Nutritional tracking
GET /health Health check with DB stats

See the interactive docs for the full 97-endpoint reference.

Authentication: single-user mode by default (no API key needed). Set ALIBI_API_KEY to require a key, or use the mnemonic API key system for multi-user setups (uv run lt user api-key create).

Web UI

The web UI is a single-page application served by the API server at /web:

  • Dashboard: system stats, user list, quick actions
  • Facts browser: paginated fact list with drill-down to items, bundles, and clouds
  • Document upload: drag-and-drop with type selection, real-time processing feedback
  • Analytics: spending by month/vendor/category, subscription detection, bar charts
  • Search: cross-entity search (documents, facts, items) with type filtering
  • Enrichment review: confidence-based queue, confirm/reject with inline editing, coverage analytics
  • User management: create users, manage contacts (Telegram/email), generate and revoke API keys

No separate build step required -- the UI is a self-contained HTML file. Start the API server and navigate to http://localhost:3100/web.

CLI (lt)

uv run lt process -p <file>          # Process a document
uv run lt process -p <folder>        # Process folder as multi-page document
uv run lt facts list                 # List all facts
uv run lt facts show <id>            # Inspect a fact with items
uv run lt enrich cascade [-l 100]    # Multi-source barcode enrichment
uv run lt enrich all [-l 200]        # Combined local enrichment (unit+name+category+attributes)
uv run lt enrich states              # Product state facet (fresh/canned/cured/roasted/...)
uv run lt enrich propose-name-merges # Embedding-based comparable_name merge proposals (review-gated)
uv run lt enrich gemini [-l 500]     # Gemini mega-batch enrichment
uv run lt items avg-price --group-by comparable_name,comparable_unit  # Item price analytics
uv run lt items trend "milk"         # Price trend for a product over time across vendors
uv run lt items rebuild              # Resync the item_stars analytics mirror
uv run lt analytics corrections      # Correction confusion matrix
uv run lt export masked out.json -t 2   # Tier-masked export
uv run lt export anonymized data.json   # Privacy-preserving export
uv run lt budget list                # List budget scenarios
uv run lt budget actual 2026-03      # Actual spending for a period
uv run lt vectordb search "groceries"   # Semantic search
uv run lt maintain run               # Full maintenance cycle
uv run lt db info                    # Schema version and row counts

The lt command stands for "Life Tracker" (alibi's original working name).

MCP Server

uv run python -m alibi.mcp           # Start MCP server (25 tools)

Alibi is MCP-native -- AI assistants can process documents, query facts, update enrichment, and run analytics through the MCP protocol. Tools include document processing, fact/item queries, vendor identity management, line item updates (barcode, brand, category, unit), analytics summaries, and search.

Telegram Bot

The Telegram bot provides mobile document capture and conversational queries. It is a thin HTTP client of the API: it owns no DB, Ollama, or pipeline code and forwards every request to the host API (lt serve, :3100) over httpx. This lets it run isolated in a container today and move to a remote VPS later with a one-line ALIBI_API_URL change.

Recommended (containerised, single poller):

# Requires TELEGRAM_BOT_TOKEN (+ optional ALIBI_TELEGRAM_ALLOWED_USERS) in .env.
./docker/run-telegram-bot.sh up        # build + start the OrbStack container
./docker/run-telegram-bot.sh logs      # tail

The container (docker-compose.telegram.yml, Dockerfile.telegram) reaches the host API via host.docker.internal:3100 and persists its keystore + offline spool on a mounted /data volume. For local dev without the container you can still run it in-process, but it is gated behind --force to prevent two pollers on one token (uv sync --extra telegram then uv run lt telegram start --force).

Auth (per-user attribution): each Telegram user links their Alibi account once with /link <mnemonic-api-key>; the bot stores {telegram_id → API key} in its keystore and sends it as X-API-Key so the API resolves the right user.

Offline resilience: an upload that arrives while the API is briefly unreachable (e.g. a boot-order race) is spooled to disk and processed automatically when the API returns — no message is lost.

Document capture -- send a photo or file to the bot, or use a type command first:

Command Description
/receipt Next upload is a receipt
/invoice Next upload is an invoice
/warranty Next upload is a warranty document
(send photo) Auto-detect document type

Queries and corrections:

Command Description
/expenses [N] Recent transactions (default: 10)
/summary [period] Spending summary (week/month/year)
/find <query> Search facts by vendor or item
/fix Correct a fact (reply to a bot message)
/merge Merge duplicate vendors
/tag <key> <value> Add annotation to a fact
/untag <key> Remove annotation

Enrichment and management:

Command Description
/enrich Review pending enrichment items
/scan Scan a barcode from a photo
/barcode Manual barcode entry
/lineitem Edit a line item
/budget Budget management
/language Set preferred language
/help List all commands

The bot supports multi-user mode -- each Telegram user can be linked to an alibi user account via /link.

Security: restrict bot access to your family by setting allowed Telegram user IDs:

# Find your Telegram user ID by messaging @userinfobot
export ALIBI_TELEGRAM_ALLOWED_USERS=123456789,987654321

When set, the bot silently ignores messages from all other users. Strongly recommended for any internet-facing bot.

Datasette Explorer (read-only)

A web UI for listing and analysing records without writing code, served by Datasette over a periodic, WAL-safe snapshot of the database. It runs as a launchd service on the host, bound to 127.0.0.1:8001 (no auth, so not exposed on the LAN — tunnel or use Tailscale for remote access).

./scripts/run-datasette.sh             # foreground (uv tool run; first run downloads it)
./scripts/datasette_refresh.sh         # re-snapshot + reload the service

Browse any table (start with item_stars), run ad-hoc read-only SQL, export CSV/JSON, or use the built-in canned queries (spend by vendor/month/category, cross-vendor comparable-unit-price comparison, cheapest vendor per product). See docs/DATASETTE_EXPLORER.md.

File Watcher

uv run lt daemon start                # Watch inbox for new documents
uv run lt daemon start --foreground   # Run in foreground (see logs)
uv run lt daemon status               # Check if watcher is running
uv run lt daemon stop                 # Stop the watcher

Auto-processes documents dropped into the configured inbox folder. Supports typed subfolders (receipts/, invoices/, etc.) for automatic document type routing.

Predictions (MindsDB)

Alibi integrates with MindsDB for ML-powered predictions on your financial data. Two models are available:

Spending forecast -- time-series model that predicts future spending by category, trained on your historical purchase data. Uses a configurable lookback window (default: 6 months) to forecast upcoming months.

Category classifier -- learns from your existing categorized items (vendor + item name + amount) and predicts categories for new uncategorized items. Requires at least 50 categorized items to train.

Setup:

# 1. Run MindsDB (self-hosted, no cloud dependency)
docker run -p 47334:47334 mindsdb/mindsdb:lightwood

# 2. Enable in .env
ALIBI_MINDSDB_ENABLED=true
ALIBI_MINDSDB_URL=http://127.0.0.1:47334

# 3. Train models (requires existing data in alibi)
uv run lt predictions train-forecast     # ~1-5 min depending on data volume
uv run lt predictions train-category     # needs 50+ categorized items

CLI usage:

uv run lt predictions status                           # Model status
uv run lt predictions forecast                         # 3-month spending forecast
uv run lt predictions forecast -m 6 -c Groceries      # 6-month, one category
uv run lt predictions classify "Alphamega" "Milk" 2.50 # Single item
uv run lt predictions classify-pending                 # Preview uncategorized
uv run lt predictions classify-pending --apply         # Apply to database

API endpoints (all under /api/v1/predictions):

Method Endpoint Description
POST /train/forecast Train spending forecast (window, horizon params)
POST /train/category Train category classifier
GET /forecast Get spending predictions (months, category filter)
POST /classify Classify a single item (vendor, name, amount)
GET /classify/uncategorized Batch classify uncategorized items
GET /models List all models and their training status
GET /models/{name}/status Check specific model status
DELETE /models/{name} Delete a model

Retrain models periodically as you accumulate more data for improved accuracy.

Analytics Export

Alibi can push its structured data to an external analytics service for dashboarding, BI, or LLM-powered analysis. When enabled, every fact creation/update triggers an HTTP POST with the full dataset:

ALIBI_ANALYTICS_EXPORT_ENABLED=true
ALIBI_ANALYTICS_STACK_URL=http://localhost:8070

The payload is a JSON snapshot posted to {url}/v1/ingest/alibi:

{
  "facts": [{"id": "...", "vendor": "...", "total_amount": 42.50, ...}],
  "fact_items": [{"id": "...", "name": "Milk", "brand": "...", "category": "dairy", ...}],
  "annotations": [{"key": "project", "value": "kitchen", ...}],
  "documents": [{"id": "...", "source": "telegram", "user_id": "...", ...}]
}

Build your own receiver with any framework (FastAPI, Express, etc.) and store in any database (PostgreSQL, ClickHouse, DuckDB). The export is full-replace (not incremental), so your receiver can simply truncate and reload. See .env.example for the full payload schema.

Vector Search (LanceDB)

Optional semantic search across documents, facts, and items using nomic-embed-text-v2-moe embeddings via Ollama.

# Install vector dependencies
uv sync --extra vector

# Set storage path in .env
ALIBI_LANCE_PATH=data/lancedb

# Build the index from existing data
uv run lt vectordb init --rebuild

# Search
uv run lt vectordb search "grocery shopping"

API: GET /api/v1/search?q=milk&semantic=true uses vector similarity when LanceDB is configured, with automatic SQL fallback.

Budgets

Budget scenarios with actual-vs-target comparison and variance tracking.

uv run lt budget create "March 2026" --type target
uv run lt budget add-entry <id> groceries 500 2026-03
uv run lt budget actual 2026-03
uv run lt budget compare <base-id> <compare-id>

API: full CRUD at /api/v1/budgets/ (scenarios, entries, comparison). Also available via Telegram (/budget) and MCP.

Project Structure

alibi/
  config.py                # pydantic-settings (ALIBI_ prefix)
  cli.py                   # Click CLI entry point (lt command)
  commands/                # CLI command modules (10 modules, 60+ commands)
  services/                # Service layer (13 facades + events + 4 subscribers)
  api/routers/             # FastAPI REST API (19 routers, ~107 endpoints)
  web/                     # Web UI (single-page application)
  mcp/                     # MCP server (25 tools)
  telegram/                # Telegram bot — thin API client (13 handlers + api_client/keystore/spool)
  extraction/              # 3-stage pipeline: OCR, heuristic parser, LLM structurer
  processing/              # Pipeline orchestration, folder routing, image optimizer
  atoms/                   # Atom parsing from extraction data
  clouds/                  # Cloud formation, collapse, split payment detection
  identities/              # Vendor identity resolution and matching
  enrichment/              # Product enrichment cascade (8 tiers)
  analytics/               # Spending, subscriptions, anomalies, nutrition, price factors
  normalizers/             # Pure functions: vendors, numbers, units, dates, tax
  refiners/                # Per-type refiners: purchase, invoice, warranty, contract
  predictions/             # MindsDB predictors (spending forecast, category classifier)
  masking/                 # 5-tier data masking (T0-T4) for privacy-controlled disclosure
  anonymization/           # 3-level anonymization export
  annotations/             # Open-ended metadata on entities (tags, notes, attributes)
  budgets/                 # Budget scenarios with category hierarchies
  matching/                # Duplicate detection (hash, perceptual, fuzzy)
  backup.py                # Database backup and restore with checksums
  maintenance/             # Learning aggregation, template reliability
  db/                      # SQLite schema (generated from migrations), connection, migrations (002-044)
  daemon/                  # File watcher + enrichment scheduler
  i18n/                    # Multi-language support
  auth/                    # API key generation and validation (PBKDF2+salt)
tests/                     # ~4950 tests
data/                      # Runtime data (gitignored; incl. explore/ Datasette snapshot)
docs/                      # Architecture docs and ADRs
datasette/                 # Datasette explorer metadata (canned queries)
scripts/                   # Ops scripts (datasette snapshot/run/refresh, etc.)
docker/                    # Container run helpers (thin Telegram bot)

Configuration

All settings use ALIBI_ prefix. See .env.example for the full reference.

Minimal setup (local-only processing):

ALIBI_OLLAMA_URL=http://127.0.0.1:11434
ALIBI_DEFAULT_CURRENCY=EUR

With cloud Stage 3 (faster, higher accuracy on complex receipts):

ALIBI_GEMINI_API_KEY=your-key-here
ALIBI_GEMINI_EXTRACTION_ENABLED=true

Full setup (all features):

ALIBI_GEMINI_API_KEY=...                    # Gemini extraction + enrichment
ALIBI_GEMINI_ENRICHMENT_ENABLED=true
ALIBI_CLOUD_ENRICHMENT_ENABLED=true         # Anthropic enrichment
ALIBI_ANTHROPIC_API_KEY=sk-ant-...
TELEGRAM_BOT_TOKEN=...                      # Telegram bot
ALIBI_MINDSDB_ENABLED=true                  # MindsDB predictions
ALIBI_ENRICHMENT_SCHEDULE_ENABLED=true      # Background enrichment daemon

Every variable is documented with its purpose and default value in .env.example.

Tested On

Alibi has been developed and tested primarily on Cyprus receipts and invoices (Greek + English, EUR). The extraction pipeline handles:

  • Supermarket receipts (Alphamega, Papas, and others)
  • Fuel station receipts (EKO, Petrolina)
  • Restaurant and retail receipts
  • Bank statements and payment confirmations
  • Card terminal slips (JCC, viva.com, Worldline)

The heuristic parser and LLM correction are language-agnostic. Non-Latin scripts (Greek, Russian, CJK) are supported via the OCR fallback model (minicpm-v).

Documentation

Document Description
Architecture System design, data model, service layer, extraction pipeline
Enrichment Pipeline ADR 8-tier product enrichment cascade design decision
Bulk Corrections Guide Edit data in SQLite GUI, sync back to correction system
iOS Capture Guide iOS Shortcuts for receipt photo capture
Obsidian Note Example Sample generated Obsidian note from a receipt

Development

uv run pytest -x                             # Run tests (~4950 passing)
uv run black . && uv run flake8 && uv run mypy   # Lint + type check

Contributing

Contributions are welcome. Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/your-feature)
  3. Write tests for new functionality
  4. Run uv run pytest -x and uv run black . && uv run flake8 before submitting
  5. Open a pull request

License

MIT

About

Local-first financial document intelligence. Atom-cloud-fact epistemological pipeline for receipt, invoice, and bank statement processing.

Topics

Resources

Contributing

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages