# coco-finbot configuration. # Locally: copy to .env. On Hugging Face: set these under Space Settings > Secrets. # Never commit the real .env. # --- Telegram ------------------------------------------------------------- # From @BotFather. TELEGRAM_BOT_TOKEN= # Random string you invent. Telegram echoes it back in the # X-Telegram-Bot-Api-Secret-Token header; requests without it are rejected. # Generate one with: python -c "import secrets; print(secrets.token_urlsafe(32))" TELEGRAM_WEBHOOK_SECRET= # Comma-separated Telegram @handles allowed to use the bot, with or without the # @. This is the friendly way to configure access. # # Handles are matched case-insensitively. Note they are MUTABLE and can be # recycled to a different person, so they gate access only -- your ledger is # keyed on Telegram's immutable numeric id, which means renaming your handle # never loses your history. # # Leave both lists EMPTY to allow nobody (safe default). Ignored when # OPEN_ACCESS=true. ALLOWED_TELEGRAM_USERNAMES= # Numeric ids still work, and are the only option for users who have not set a # @username at all. ALLOWED_TELEGRAM_USER_IDS= # --- Web dashboard --------------------------------------------------------- # Public origin used to build /dashboard sign-in links. Derived from SPACE_HOST # on a Space; set explicitly when self-hosting. PUBLIC_BASE_URL= # How long a dashboard link stays valid. Short on purpose: the token rides in # the URL, and URLs end up in history, referrers and screenshots. DASHBOARD_LINK_MINUTES=30 # Let ANYONE on Telegram use the bot. Each user gets their own isolated ledger, # so this makes the bot multi-tenant -- it does NOT expose your spending to # other people. What it does expose is your wallet: every stranger's receipt # and statement is read using YOUR HF_TOKEN. Cap that below. # Must be set explicitly, so an unconfigured allowlist stays closed. OPEN_ACCESS=false # Model-backed uploads (receipt photos, statements) per user per day. # Typed expenses are parsed locally and are never counted. 0 disables the cap. UPLOADS_PER_USER_PER_DAY=20 # --- Inference ------------------------------------------------------------- # Which backend does the thinking: # local -- run a small model on this machine's/Space's own GPU. Free per # call, so it is what makes OPEN_ACCESS affordable. # remote -- call HF Inference Providers. Better quality, costs credits. # off -- no inference; deterministic features only. # auto -- local if a CUDA GPU is present, else remote if HF_TOKEN is set. LLM_BACKEND=auto # Local models. Sized for ZeroGPU's A10G (24 GB) in bfloat16. LOCAL_LLM_MODEL=Qwen/Qwen2.5-3B-Instruct LOCAL_VISION_MODEL=Qwen/Qwen2.5-VL-3B-Instruct # --- Remote inference (Hugging Face Inference Providers) ------------------- # A HF token with "Make calls to Inference Providers" permission. # On a Space you can leave this unset and the bot still works -- it falls back # to the deterministic parser and skips receipt/statement understanding. HF_TOKEN= # OpenAI-compatible base URL. HF's router fans one token out to many providers. LLM_BASE_URL=https://router.huggingface.co/v1 # Text model used for extraction, categorisation and advice. LLM_MODEL=Qwen/Qwen3-235B-A22B-Instruct-2507 # Vision model used for receipt photos. Must accept image_url content parts. LLM_VISION_MODEL=Qwen/Qwen2.5-VL-72B-Instruct # --- Durable storage ------------------------------------------------------ # Spaces disk is EPHEMERAL -- it is wiped on every restart, sleep or rebuild. # The bot keeps SQLite locally and mirrors it to a PRIVATE dataset repo so your # data survives. Set to a repo you own, e.g. "your-username/finbot-data". # Leave empty to run purely local (fine for dev; DATA LOSS on a Space). HF_DATASET_REPO= # How often (minutes) to push the database to the dataset repo. SYNC_EVERY_MINUTES=5 # Where the local SQLite file lives inside the container. DATA_DIR=/home/user/data # --- Behaviour ------------------------------------------------------------ # Default currency for bare amounts like "coffee 250". ISO 4217 code. DEFAULT_CURRENCY=INR # IANA timezone used to decide what "today" and "this month" mean. TIMEZONE=Asia/Kolkata