Spaces:
Sleeping
Sleeping
DIVYANSHI SINGH commited on
Commit ·
a112630
1
Parent(s): 353eb66
Remove outdated configuration, add live HF link
Browse files- README.md +2 -0
- bill_invoice_scanner.md +0 -210
- render.yaml +0 -10
README.md
CHANGED
|
@@ -11,6 +11,8 @@ pinned: false
|
|
| 11 |
|
| 12 |
# 🧾 Invoice Scanner Pro
|
| 13 |
|
|
|
|
|
|
|
| 14 |
## 📖 Project Description
|
| 15 |
Invoice Scanner Pro is a highly capable, GPU-accelerated web application built on Streamlit and EasyOCR. It rapidly automates financial data processing by utilizing regex rules to extract vendor names, precise transaction dates, and total amounts directly from uploaded receipts and invoices. Featuring an interactive dashboard, users can easily perform human-in-the-loop data corrections, push verified information into a local SQLite database, and seamlessly export their records into instantly updated real-time CSV or Excel spreadsheets.
|
| 16 |
|
|
|
|
| 11 |
|
| 12 |
# 🧾 Invoice Scanner Pro
|
| 13 |
|
| 14 |
+
🚀 **Live Application:** [https://huggingface.co/spaces/Divya499/Bill-Invoice-Scanner-Pro](https://huggingface.co/spaces/Divya499/Bill-Invoice-Scanner-Pro)
|
| 15 |
+
|
| 16 |
## 📖 Project Description
|
| 17 |
Invoice Scanner Pro is a highly capable, GPU-accelerated web application built on Streamlit and EasyOCR. It rapidly automates financial data processing by utilizing regex rules to extract vendor names, precise transaction dates, and total amounts directly from uploaded receipts and invoices. Featuring an interactive dashboard, users can easily perform human-in-the-loop data corrections, push verified information into a local SQLite database, and seamlessly export their records into instantly updated real-time CSV or Excel spreadsheets.
|
| 18 |
|
bill_invoice_scanner.md
DELETED
|
@@ -1,210 +0,0 @@
|
|
| 1 |
-
# Project 01 — Bill / Invoice Scanner · Easy Tier
|
| 2 |
-
|
| 3 |
-
## What You Are Building
|
| 4 |
-
|
| 5 |
-
A Streamlit web application that accepts a photograph or scan of any printed bill, receipt, or GST invoice and automatically extracts structured fields — vendor name, invoice number, date, subtotal, GST amount, and total payable — from the raw image. The pipeline runs OCR to convert the image to text, then applies rule-based NLP parsing to locate and extract each field. All extracted records are persisted to a local SQLite database and can be exported as Excel or JSON at any time. The user can review and correct extracted fields before saving, making the system robust to OCR errors.
|
| 6 |
-
|
| 7 |
-
---
|
| 8 |
-
|
| 9 |
-
## Why This Architecture
|
| 10 |
-
|
| 11 |
-
A bill image is unstructured visual data — there is no schema, no fixed column positions, and no guaranteed layout across vendors. Two approaches exist: template matching (defining fixed regions per vendor layout) and OCR-plus-NLP (convert the entire image to text, then parse the text). Template matching breaks the moment a vendor changes their invoice design. OCR-plus-NLP is layout-agnostic — it works on any bill from any vendor as long as the text is readable.
|
| 12 |
-
|
| 13 |
-
PaddleOCR is chosen over Tesseract because it handles skewed, low-resolution, and partially degraded images significantly better out of the box, and it natively supports both printed and handwritten text. The preprocessing step — denoising, deskewing, adaptive thresholding — is essential because phone-camera bill photos have uneven lighting, slight rotation, and JPEG compression artifacts that reduce OCR accuracy by 20–40% if not corrected first.
|
| 14 |
-
|
| 15 |
-
The NLP extraction layer uses regex patterns and keyword matching rather than a trained NER model. This is the correct engineering decision for this tier: bills follow predictable text patterns ("Total: ₹1,250", "Invoice No. INV-2024-001") that regex handles reliably without requiring labeled training data or GPU inference. A trained model would add complexity without meaningfully improving accuracy on well-formatted printed bills.
|
| 16 |
-
|
| 17 |
-
SQLite is chosen for storage because it requires zero configuration, stores everything in a single file, and is directly queryable by pandas — which powers the dashboard and export functionality.
|
| 18 |
-
|
| 19 |
-
---
|
| 20 |
-
|
| 21 |
-
## Core Concepts to Understand Before Building
|
| 22 |
-
|
| 23 |
-
**1. OCR Pipeline**
|
| 24 |
-
Optical Character Recognition converts a raster image into a string of characters. Modern OCR engines like PaddleOCR use a detect-then-recognize pipeline: a text detection model first draws bounding boxes around text regions, then a recognition model reads the characters inside each box. The output is a list of (bounding_box, text, confidence_score) tuples. Confidence scores below 0.6 should be filtered — low-confidence results are usually noise, damaged characters, or background patterns mistaken for text.
|
| 25 |
-
|
| 26 |
-
**2. Image Preprocessing**
|
| 27 |
-
Raw bill photos fail OCR for three reasons: noise (camera grain, paper texture), skew (the camera was not perfectly parallel to the bill), and poor contrast (shadow across one side of the bill). Denoising smooths grain without blurring text. Deskew detects the dominant angle of text lines and rotates the image to make them horizontal. Adaptive thresholding converts the grayscale image to pure black-and-white, eliminating uneven lighting — this is more robust than a global threshold because it computes a local threshold per small region rather than one threshold for the entire image.
|
| 28 |
-
|
| 29 |
-
**3. Regex for Field Extraction**
|
| 30 |
-
Regular expressions match patterns in strings. For bill parsing, the pattern is always: find a keyword (e.g., "total", "invoice no"), then find the value immediately after it on the same line. Amount patterns must handle currency symbols, comma-separated thousands, and optional decimal points. Date patterns must handle multiple formats (DD/MM/YYYY, DD-Mon-YYYY, Mon DD YYYY). Build and test each pattern independently before combining them.
|
| 31 |
-
|
| 32 |
-
**4. SQLite with Python**
|
| 33 |
-
SQLite is a file-based relational database built into Python's standard library — no installation required. A connection opens the file (creating it if absent), a cursor executes SQL statements, and commit() writes changes to disk. The entire database is a single `.db` file that can be copied, backed up, or deleted like any other file. Pandas can read directly from SQLite via read_sql_query(), which returns a DataFrame — this makes the connection between storage and the dashboard seamless.
|
| 34 |
-
|
| 35 |
-
**5. Streamlit Application Structure**
|
| 36 |
-
Streamlit reruns the entire script top to bottom on every user interaction. This means state — like whether a file has been uploaded and processed — must be managed carefully. st.session_state persists values across reruns. The layout is controlled by st.columns() for side-by-side panels and st.expander() for collapsible sections. File uploads use st.file_uploader(), which returns a file-like object that can be passed directly to PIL.Image.open().
|
| 37 |
-
|
| 38 |
-
**6. Confidence-Based Validation**
|
| 39 |
-
Not every field will be extracted correctly from every bill. The system should surface its confidence to the user rather than silently returning wrong values. A field with no match returns None — the UI renders this as an empty input box, signaling the user to fill it manually. This human-in-the-loop design makes the system useful even when OCR or parsing fails partially.
|
| 40 |
-
|
| 41 |
-
---
|
| 42 |
-
|
| 43 |
-
## Project Workflow
|
| 44 |
-
|
| 45 |
-
### Phase 1 — OCR Engine Working
|
| 46 |
-
|
| 47 |
-
The goal of this phase is to get PaddleOCR installed and producing readable text from a bill photo. Do not build the UI yet. Work in a single script or notebook to isolate and validate the OCR output before building on top of it.
|
| 48 |
-
|
| 49 |
-
Collect 5 real bill photos to test with — phone camera shots of grocery receipts, utility bills, or restaurant bills. These should include at least one photo with slight skew and one with uneven lighting. These will serve as your evaluation set throughout the project.
|
| 50 |
-
|
| 51 |
-
Implement the preprocessing function. Apply it to each test image and visually inspect the preprocessed result — the output should look like clean black text on a white background. If the deskew step is over-rotating (straightening text that was already straight), add a rotation threshold: only rotate if the detected angle exceeds 1 degree.
|
| 52 |
-
|
| 53 |
-
Run PaddleOCR on both the raw image and the preprocessed image and compare the output. The preprocessed version should produce fewer garbled characters and higher average confidence scores. Log the full OCR output for each test bill — you will reference this when building the field extractor.
|
| 54 |
-
|
| 55 |
-
Success criterion: for each of your 5 test bills, PaddleOCR on the preprocessed image produces text that a human could read and extract a total amount from.
|
| 56 |
-
|
| 57 |
-
---
|
| 58 |
-
|
| 59 |
-
### Phase 2 — Field Extraction Working
|
| 60 |
-
|
| 61 |
-
The goal of this phase is to reliably extract vendor name, date, invoice number, total, GST, and subtotal from the raw OCR text. Work in isolation — use the OCR text strings you logged in Phase 1 as hardcoded inputs, not live OCR. This separates the parsing logic from the OCR dependency.
|
| 62 |
-
|
| 63 |
-
For each field, write the extraction function, test it against all 5 bill text strings, and record which bills it fails on and why. Fix the pattern or add a fallback before moving to the next field.
|
| 64 |
-
|
| 65 |
-
Vendor name extraction is the most heuristic: the first non-empty, non-numeric line is usually the company name. This fails for bills that begin with a header like "TAX INVOICE" — handle this by skipping known header strings before taking the first line.
|
| 66 |
-
|
| 67 |
-
Amount extraction must handle the following formats: "1,250.00", "1250", "₹ 1,250", "Rs.1250.50". Build one regex that handles all of these and test it against real values from your test bills.
|
| 68 |
-
|
| 69 |
-
Date extraction must handle at least three formats: DD/MM/YYYY, DD-MM-YYYY, and DD Mon YYYY (e.g., 15 Jan 2024). Use a list of patterns tried in sequence — return the first match.
|
| 70 |
-
|
| 71 |
-
Success criterion: for each of your 5 test bills, the extractor correctly identifies the total amount. Vendor, date, and invoice number are acceptable to miss on 1–2 bills — total amount must always be found.
|
| 72 |
-
|
| 73 |
-
---
|
| 74 |
-
|
| 75 |
-
### Phase 3 — Database and Export
|
| 76 |
-
|
| 77 |
-
The goal of this phase is a working SQLite database and export pipeline. Test this phase without the UI — write a small script that calls save_invoice() with hardcoded data, then calls fetch_all() and prints the result, then exports to Excel.
|
| 78 |
-
|
| 79 |
-
The database schema has one table: invoices. Columns are id (auto-increment primary key), vendor (text), invoice_number (text), date (text), subtotal (real), gst (real), total (real), raw_text (text), and created_at (timestamp with default current_timestamp). Store date as text — parsing it into a Python date object adds complexity with no benefit for this tier.
|
| 80 |
-
|
| 81 |
-
The Excel export uses pandas to_excel() with openpyxl as the engine. The JSON export uses pandas to_json() with orient="records" and indent=2. Both exports write to an exports/ directory. The download buttons in Streamlit read the file from disk and serve it — do not store binary data in session state.
|
| 82 |
-
|
| 83 |
-
Success criterion: save 3 invoices, run fetch_all(), confirm all 3 appear in the returned DataFrame, export to Excel, open the Excel file and confirm the data is correct.
|
| 84 |
-
|
| 85 |
-
---
|
| 86 |
-
|
| 87 |
-
### Phase 4 — Streamlit UI
|
| 88 |
-
|
| 89 |
-
The goal of this phase is to connect all three phases into a working application. The UI layout has a sidebar for file upload and a two-column main area: left column shows the uploaded image, right column shows the extracted and editable fields.
|
| 90 |
-
|
| 91 |
-
All extracted fields must be editable before saving. Use st.text_input() for text fields and st.number_input() for amount fields. Pre-fill each input with the extracted value. This is the most important UX decision in the project — users must be able to correct OCR errors before the data enters the database.
|
| 92 |
-
|
| 93 |
-
The bottom section of the page shows a summary metrics row (total invoices, total amount, total GST, unique vendors) followed by the full invoice table and download buttons.
|
| 94 |
-
|
| 95 |
-
Show a spinner during OCR and extraction — these operations take 2���5 seconds and the UI must communicate that processing is happening. Use st.spinner() wrapping the OCR and extraction calls.
|
| 96 |
-
|
| 97 |
-
Success criterion: upload a real bill photo, see the extracted fields pre-filled in the form, correct one field, click save, see the invoice appear in the table below, and successfully download the Excel export.
|
| 98 |
-
|
| 99 |
-
---
|
| 100 |
-
|
| 101 |
-
## Folder Structure
|
| 102 |
-
|
| 103 |
-
```
|
| 104 |
-
bill_scanner/
|
| 105 |
-
├── app.py ← Streamlit entry point, UI layout, page config
|
| 106 |
-
├── ocr.py ← PaddleOCR wrapper, text extraction functions
|
| 107 |
-
├── extractor.py ← Regex field parser (vendor, date, amounts, invoice no.)
|
| 108 |
-
├── database.py ← SQLite init, save, fetch, delete functions
|
| 109 |
-
├── utils.py ← Image preprocessing (denoise, deskew, threshold)
|
| 110 |
-
├── requirements.txt
|
| 111 |
-
├── invoices.db ← Created automatically on first run
|
| 112 |
-
├── exports/ ← Excel and JSON downloads written here
|
| 113 |
-
│ ├── invoices.xlsx
|
| 114 |
-
│ └── invoices.json
|
| 115 |
-
└── test_images/ ← Store your 5 test bill photos here during development
|
| 116 |
-
└── .gitkeep
|
| 117 |
-
```
|
| 118 |
-
|
| 119 |
-
---
|
| 120 |
-
|
| 121 |
-
## File Responsibilities
|
| 122 |
-
|
| 123 |
-
**app.py** — Streamlit page configuration, sidebar upload widget, two-column layout, editable field form, save button, summary metrics, invoice table, download buttons. Imports from all other modules. Contains no business logic — only UI wiring.
|
| 124 |
-
|
| 125 |
-
**ocr.py** — PaddleOCR instance initialization (singleton pattern — initialize once, reuse). Function to extract full text string from a numpy image array. Function to extract text with bounding boxes and confidence scores for debugging. Confidence filtering (discard results below 0.6).
|
| 126 |
-
|
| 127 |
-
**extractor.py** — One function per field: extract_vendor(), extract_date(), extract_invoice_number(), extract_amounts(). One master function parse_invoice() that calls all of them and returns a single dict with all fields. All functions accept a raw text string and return a value or None. No imports from other project modules.
|
| 128 |
-
|
| 129 |
-
**database.py** — init_db() creates the invoices table if it does not exist. save_invoice() inserts one record and returns the new row id. fetch_all() returns a pandas DataFrame of all records ordered by id descending. delete_invoice() removes one record by id. All functions open and close their own connection — do not share connections across calls.
|
| 130 |
-
|
| 131 |
-
**utils.py** — preprocess_image() accepts an image file path string and returns a preprocessed numpy array ready for OCR. pil_to_cv2() converts a PIL Image to a cv2-compatible numpy array. These are pure functions with no side effects.
|
| 132 |
-
|
| 133 |
-
---
|
| 134 |
-
|
| 135 |
-
## Requirements
|
| 136 |
-
|
| 137 |
-
```
|
| 138 |
-
requirements.txt
|
| 139 |
-
----------------
|
| 140 |
-
paddlepaddle==2.6.1
|
| 141 |
-
paddleocr==2.7.3
|
| 142 |
-
opencv-python-headless==4.9.0.80
|
| 143 |
-
pillow==10.3.0
|
| 144 |
-
streamlit==1.35.0
|
| 145 |
-
pandas==2.2.2
|
| 146 |
-
openpyxl==3.1.2
|
| 147 |
-
numpy==1.26.4
|
| 148 |
-
```
|
| 149 |
-
|
| 150 |
-
---
|
| 151 |
-
|
| 152 |
-
## Known Failure Modes and Fixes
|
| 153 |
-
|
| 154 |
-
**OCR produces garbled text on a clear photo**
|
| 155 |
-
The image color mode is wrong. PaddleOCR expects BGR (OpenCV format). If you pass an RGB array (PIL default), colors are inverted and OCR quality drops significantly. Always convert PIL images to cv2 BGR format before passing to PaddleOCR.
|
| 156 |
-
|
| 157 |
-
**Deskew rotates a straight image by 45 degrees**
|
| 158 |
-
The minAreaRect angle computation has a quadrant ambiguity — it returns angles between -90 and 0. When the detected angle is close to -45, the correction formula flips. Add a guard: if the absolute angle is less than 1 degree, skip rotation entirely.
|
| 159 |
-
|
| 160 |
-
**Total amount extracted as None on every bill**
|
| 161 |
-
The keyword matching is case-sensitive and your bills use "TOTAL" (uppercase). Make all keyword comparisons case-insensitive by lowercasing the line before matching. Also check for whitespace between the keyword and the colon — "Total : ₹1,250" has a space before the colon that a tight regex will miss.
|
| 162 |
-
|
| 163 |
-
**Streamlit re-runs OCR on every interaction**
|
| 164 |
-
Streamlit reruns the full script on every widget interaction. Wrapping the OCR call in a function decorated with @st.cache_data and keyed on the file bytes prevents re-running OCR when the user edits a field. Cache the (raw_text, parsed_fields) result, not the image.
|
| 165 |
-
|
| 166 |
-
**Excel export fails with PermissionError**
|
| 167 |
-
The exports/invoices.xlsx file is open in Excel when the export runs. Write to a timestamped filename (e.g., invoices_20240115_143022.xlsx) instead of overwriting the same file each time.
|
| 168 |
-
|
| 169 |
-
**PaddleOCR download fails on first run behind a proxy**
|
| 170 |
-
PaddleOCR downloads model weights on first initialization. Behind a corporate proxy or on Kaggle, this may fail silently. Download the model weights manually from the PaddleOCR GitHub releases page and set the model_dir parameter in PaddleOCR() to point to the local directory.
|
| 171 |
-
|
| 172 |
-
---
|
| 173 |
-
|
| 174 |
-
## Upgrade Path After Basic Works
|
| 175 |
-
|
| 176 |
-
Once the basic version runs end-to-end on your 5 test bills, these extensions add real value in roughly increasing order of difficulty.
|
| 177 |
-
|
| 178 |
-
**Hindi/regional language support** — Change lang='en' to lang='hi' in PaddleOCR initialization. Test on bills with mixed Hindi and English text. The extraction regex patterns need no changes because amounts and dates are typically in numerals regardless of language.
|
| 179 |
-
|
| 180 |
-
**PDF support** — Use the pdf2image library to convert each page of a PDF to a PIL Image, then pass each page through the existing pipeline. Bills received by email are often PDFs — this extension makes the tool useful for accountants who receive digital invoices.
|
| 181 |
-
|
| 182 |
-
**Duplicate detection** — Hash the raw_text string using hashlib.md5() and store the hash in the database. Before saving, check if the hash already exists — if it does, warn the user that this bill appears to already be saved. This prevents double-counting when the same bill is uploaded twice.
|
| 183 |
-
|
| 184 |
-
**Confidence scoring per field** — Instead of returning None for missing fields, return a (value, confidence) tuple where confidence is 1.0 for exact regex matches, 0.7 for fuzzy matches, and 0.0 for no match. Display a color indicator next to each field in the UI (green for high confidence, yellow for medium, red for no match) so users know which fields to review carefully.
|
| 185 |
-
|
| 186 |
-
---
|
| 187 |
-
|
| 188 |
-
## Dataset and Test Resources
|
| 189 |
-
|
| 190 |
-
**Test data** — Collect your own bill photos using a phone camera. Target at least 10 diverse bills: grocery store receipts, utility bills, restaurant bills, GST invoices from e-commerce, and medical bills. Diversity in vendor, layout, and language makes your test set meaningful.
|
| 191 |
-
|
| 192 |
-
**SROIE Dataset** — A publicly available dataset of 1,000 scanned receipt images with ground truth annotations for vendor, date, address, and total. Available on Kaggle (search "SROIE receipt OCR"). Use this to benchmark your extractor's accuracy quantitatively — compute field-level accuracy (fraction of bills where the extracted value matches ground truth) for each field.
|
| 193 |
-
|
| 194 |
-
**PaddleOCR documentation** — github.com/PaddlePaddle/PaddleOCR — the README contains installation instructions, language support list, and a quickstart that matches exactly what this project needs.
|
| 195 |
-
|
| 196 |
-
---
|
| 197 |
-
|
| 198 |
-
## Checkpoint — Before Moving to Next Project
|
| 199 |
-
|
| 200 |
-
Answer these questions without looking at your code. If you cannot answer all of them confidently, revisit the relevant phase.
|
| 201 |
-
|
| 202 |
-
1. **Conceptual** — Explain why adaptive thresholding produces better OCR results than a global threshold on a bill photo taken with a phone camera. What property of phone-camera images makes global thresholding fail?
|
| 203 |
-
|
| 204 |
-
2. **Diagnostic** — Your extractor returns None for total on 3 out of 10 test bills. All 3 are from the same supermarket chain. What is the most likely reason, and what is your first debugging step?
|
| 205 |
-
|
| 206 |
-
3. **Engineering** — A user uploads the same bill twice in one session. The database currently saves it twice. Describe the exact change you would make to detect and prevent this duplicate, including which file you would modify and what new column you would add.
|
| 207 |
-
|
| 208 |
-
4. **Practical** — Your Streamlit app re-runs OCR every time the user clicks the save button, even though the image has not changed. Explain why this happens and describe the fix using st.cache_data.
|
| 209 |
-
|
| 210 |
-
5. **Extension** — A client asks you to process a folder of 500 PDF invoices overnight without any human review. Which parts of the current pipeline would break, which would work unchanged, and what would you add to make this work as a batch job?
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
render.yaml
DELETED
|
@@ -1,10 +0,0 @@
|
|
| 1 |
-
services:
|
| 2 |
-
- type: web
|
| 3 |
-
name: bill-scanner-pro
|
| 4 |
-
env: python
|
| 5 |
-
buildCommand: "pip install -r requirements.txt"
|
| 6 |
-
startCommand: "streamlit run app.py --server.port $PORT --server.address 0.0.0.0"
|
| 7 |
-
plan: free
|
| 8 |
-
envVars:
|
| 9 |
-
- key: PYTHON_VERSION
|
| 10 |
-
value: 3.10.12
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|