LovnishVerma commited on
Commit
d2c798d
ยท
verified ยท
1 Parent(s): 76f2eee

Upload 5 files

Browse files
Files changed (5) hide show
  1. .env.example +0 -4
  2. README.md +135 -139
  3. app.py +34 -33
  4. officers.csv +6 -0
  5. test_network.py +12 -0
.env.example CHANGED
@@ -8,7 +8,3 @@ NVIDIA_API_KEY=your_nvidia_api_key
8
 
9
  # MongoDB
10
  MONGODB_URI=mongodb+srv://username:password@cluster0.sxci1.mongodb.net/?retryWrites=true&w=majority
11
-
12
- # Telegram API
13
- TELEGRAM_BOT_TOKEN=your_bot_token_here
14
- TELEGRAM_GROUP_ID=your_group_chat_id_here
 
8
 
9
  # MongoDB
10
  MONGODB_URI=mongodb+srv://username:password@cluster0.sxci1.mongodb.net/?retryWrites=true&w=majority
 
 
 
 
README.md CHANGED
@@ -1,139 +1,135 @@
1
- ---
2
- title: ALDDS
3
- emoji: ๐Ÿ’ป
4
- colorFrom: purple
5
- colorTo: red
6
- sdk: gradio
7
- sdk_version: 6.14.0
8
- python_version: '3.13'
9
- app_file: app.py
10
- pinned: false
11
- ---
12
-
13
- # โš–๏ธ Automated Legal Document Digitization System (ALDDS)
14
-
15
- ![Python](https://img.shields.io/badge/Python-3.13-blue.svg)
16
- ![Gradio](https://img.shields.io/badge/Gradio-6.14.0-orange.svg)
17
- ![MongoDB](https://img.shields.io/badge/MongoDB-Atlas-green.svg)
18
- ![Hugging Face](https://img.shields.io/badge/Deploy-Hugging%20Face-yellow.svg)
19
-
20
- Upload a photo of a legal document (bailable warrant, summon, etc.) and seamlessly convert it into structured JSON data. ALDDS handles the OCR, AI parsing, secure storage, and live dispatcher notifications in a single streamlined pipeline.
21
-
22
- ## ๐Ÿš€ Pipeline & Architecture
23
-
24
- ```text
25
- Image Upload โ†’ Cloudinary Hosting โ†’ Tesseract OCR โ†’ NVIDIA LLMs โ†’ MongoDB โ†’ Telegram IO Alert
26
- ```
27
-
28
- 1. **OCR Extraction**: Uses Tesseract to extract raw text from image uploads.
29
- 2. **AI Parsing**: Leverages advanced NVIDIA models (`qwen/qwen3-coder-480b-a35b-instruct`, Llama 3) to parse the unstructured OCR text into a strict 10-field JSON schema.
30
- 3. **Secure Storage**: Automatically commits the digital record to a MongoDB database.
31
- 4. **Live Dashboard**: A real-time, searchable Police Dashboard built directly into the UI.
32
- 5. **Instant Notifications**: Dispatchers can ping Investigating Officers (IOs) via Telegram with the parsed data using a secure Frontend JavaScript bypass.
33
-
34
- ---
35
-
36
- ## ๐Ÿ“‹ Features
37
-
38
- - **Multi-Model Fallback**: The app cycles through a priority list of NVIDIA LLMs ensuring maximum uptime and reliability during the parsing phase.
39
- - **๐Ÿ‘ฎ Live Police Dashboard**: A dedicated tab for station dispatchers to monitor incoming warrants. Includes a real-time MongoDB search filter (by Case No, IO Name, Station, etc.).
40
- - **๐Ÿ“จ Frontend JS Telegram Alerts**: Send an automated markdown summary and document link to an IO via Telegram. The request executes directly in the browser using JavaScript to bypass restrictive institutional or cloud IP firewalls (like Hugging Face).
41
-
42
- ---
43
-
44
- ## ๐Ÿ”‘ Environment Setup
45
-
46
- To run ALDDS locally or in the cloud, you need the following API keys configured in a `.env` file (or as Secrets on Hugging Face).
47
-
48
- ```env
49
- # Cloudinary (Image Hosting)
50
- CLOUDINARY_CLOUD_NAME=your_cloud_name
51
- CLOUDINARY_API_KEY=your_api_key
52
- CLOUDINARY_API_SECRET=your_api_secret
53
-
54
- # NVIDIA API (LLM Parsing)
55
- NVIDIA_API_KEY=your_nvidia_api_key
56
-
57
- # MongoDB (Database)
58
- MONGODB_URI=mongodb+srv://username:password@cluster0.../?retryWrites=true&w=majority
59
-
60
- # Telegram (IO Notifications)
61
- TELEGRAM_BOT_TOKEN=your_bot_token_here
62
- ```
63
-
64
- | Variable | Where to get it |
65
- |---|---|
66
- | `CLOUDINARY_*` | [Cloudinary Console](https://console.cloudinary.com/) โ†’ Dashboard |
67
- | `NVIDIA_API_KEY` | [NVIDIA Build](https://build.nvidia.com/) โ†’ API Catalog โ†’ Get API Key |
68
- | `MONGODB_URI` | [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) โ†’ Database โ†’ Connect |
69
- | `TELEGRAM_BOT_TOKEN` | [Telegram](https://core.telegram.org/bots) โ†’ @BotFather |
70
-
71
- ---
72
-
73
- ## ๐Ÿ’ป Local Installation Guide
74
-
75
- ### 1. Install Tesseract OCR (System Binary)
76
- Python's `pytesseract` requires the underlying Tesseract engine to be installed on your OS.
77
-
78
- **Windows**
79
- 1. Download installer from: https://github.com/UB-Mannheim/tesseract/wiki
80
- 2. Run installer (default path: `C:\Program Files\Tesseract-OCR\`)
81
- 3. The app is hardcoded to look for this path on Windows.
82
-
83
- **Linux (Debian/Ubuntu)**
84
- ```bash
85
- sudo apt-get update
86
- sudo apt-get install tesseract-ocr
87
- ```
88
-
89
- **macOS**
90
- ```bash
91
- brew install tesseract
92
- ```
93
-
94
- ### 2. Run the App
95
- ```bash
96
- # Clone repository
97
- git clone https://huggingface.co/spaces/LovnishVerma/ALDDS
98
- cd ALDDS
99
-
100
- # Install Dependencies
101
- pip install -r requirements.txt
102
-
103
- # Run the Server
104
- python app.py
105
- ```
106
- The interface will launch at **http://127.0.0.1:7860**.
107
-
108
- ---
109
-
110
- ## โ˜๏ธ Hugging Face Spaces Deployment
111
-
112
- If you are deploying ALDDS to Hugging Face Spaces, follow these critical steps:
113
-
114
- 1. **Set Up Secrets**: Go to your Space **Settings** -> **Variables and secrets**. Add all variables from your `.env` file as **Secrets**.
115
- 2. **System Dependencies**: Hugging Face runs Debian Linux. The repository includes a `packages.txt` file telling Hugging Face to install `tesseract-ocr` and `libtesseract-dev` during the Docker build.
116
- 3. **CRLF Warning**: Ensure that `packages.txt` is saved with Unix (`LF`) line endings. If it has Windows (`CRLF`) line endings, the Hugging Face Docker build will fail with a `Package not found` error.
117
- 4. **Restart**: Always click **Restart Space** after adding or modifying Secrets so the new environment variables are loaded into the container.
118
-
119
- ---
120
-
121
- ## ๐Ÿ“Š Extracted JSON Schema
122
-
123
- The LLM is strictly prompted to extract the following fields. If a field cannot be found, it defaults to `null`.
124
-
125
- | JSON Key | Description |
126
- |---|---|
127
- | `Case_FIR_Number` | FIR or court case reference number |
128
- | `Act_and_Sections` | Applicable IPC/CRPC legal acts and sections |
129
- | `Type_of_Document` | Warrant, summon, notice, etc. |
130
- | `Target_Police_Station` | Police station the document is addressed to |
131
- | `IO_Name_and_Belt_No` | Investigating Officer's name and belt number |
132
- | `IO_Mobile_Number` | IO's contact number |
133
- | `Person_Name_To_Serve` | Name of the person to be served/arrested |
134
- | `Person_Address` | Address of the target person |
135
- | `Court_Name` | Issuing court name |
136
- | `Hearing_Date` | Scheduled hearing or appearance date (DD-MM-YYYY) |
137
-
138
- ---
139
- *Built to streamline station workflows, eliminate manual data entry, and instantly notify field officers.*
 
1
+ ---
2
+ title: ALDDS
3
+ emoji: ๐Ÿ’ป
4
+ colorFrom: purple
5
+ colorTo: red
6
+ sdk: gradio
7
+ sdk_version: 6.14.0
8
+ python_version: '3.13'
9
+ app_file: app.py
10
+ pinned: false
11
+ ---
12
+
13
+ # โš–๏ธ Automated Legal Document Digitization System (ALDDS)
14
+
15
+ ![Python](https://img.shields.io/badge/Python-3.13-blue.svg)
16
+ ![Gradio](https://img.shields.io/badge/Gradio-6.14.0-orange.svg)
17
+ ![MongoDB](https://img.shields.io/badge/MongoDB-Atlas-green.svg)
18
+ ![Hugging Face](https://img.shields.io/badge/Deploy-Hugging%20Face-yellow.svg)
19
+
20
+ Upload a photo of a legal document (bailable warrant, summon, etc.) and seamlessly convert it into structured JSON data. ALDDS handles the OCR, AI parsing, secure storage, and live dispatcher notifications in a single streamlined pipeline.
21
+
22
+ ## ๐Ÿš€ Pipeline & Architecture
23
+
24
+ ```text
25
+ Image Upload โ†’ Cloudinary Hosting โ†’ Tesseract OCR โ†’ NVIDIA LLMs โ†’ MongoDB โ†’ WhatsApp Alert
26
+ ```
27
+
28
+ 1. **OCR Extraction**: Uses Tesseract to extract raw text from image uploads.
29
+ 2. **AI Parsing**: Leverages advanced NVIDIA models (`qwen/qwen3-coder-480b-a35b-instruct`, Llama 3) to parse the unstructured OCR text into a strict 10-field JSON schema.
30
+ 3. **Secure Storage**: Automatically commits the digital record to a MongoDB database.
31
+ 4. **Live Dashboard**: A real-time, searchable Police Dashboard built directly into the UI.
32
+ 5. **Instant Notifications**: Dispatchers can notify Investigating Officers (IOs) instantly via zero-cost WhatsApp `wa.me` links populated from an internal CSV database.
33
+
34
+ ---
35
+
36
+ ## ๐Ÿ“‹ Features
37
+
38
+ - **Multi-Model Fallback**: The app cycles through a priority list of NVIDIA LLMs ensuring maximum uptime and reliability during the parsing phase.
39
+ - **๐Ÿ‘ฎ Live Police Dashboard**: A dedicated tab for station dispatchers to monitor incoming warrants. Includes a real-time MongoDB search filter (by Case No, IO Name, Station, etc.).
40
+ - **๐Ÿ’ฌ WhatsApp Integration**: Zero-API-cost notifications. Selecting an officer from the dropdown dynamically pulls their phone number from `officers.csv` and opens a pre-filled WhatsApp window for the dispatcher to send manually.
41
+
42
+ ---
43
+
44
+ ## ๐Ÿ”‘ Environment Setup
45
+
46
+ To run ALDDS locally or in the cloud, you need the following API keys configured in a `.env` file (or as Secrets on Hugging Face).
47
+
48
+ ```env
49
+ # Cloudinary (Image Hosting)
50
+ CLOUDINARY_CLOUD_NAME=your_cloud_name
51
+ CLOUDINARY_API_KEY=your_api_key
52
+ CLOUDINARY_API_SECRET=your_api_secret
53
+
54
+ # NVIDIA API (LLM Parsing)
55
+ NVIDIA_API_KEY=your_nvidia_api_key
56
+
57
+ # MongoDB (Database)
58
+ MONGODB_URI=mongodb+srv://username:password@cluster0.../?retryWrites=true&w=majority
59
+ ```
60
+
61
+ | Variable | Where to get it |
62
+ |---|---|
63
+ | `CLOUDINARY_*` | [Cloudinary Console](https://console.cloudinary.com/) โ†’ Dashboard |
64
+ | `NVIDIA_API_KEY` | [NVIDIA Build](https://build.nvidia.com/) โ†’ API Catalog โ†’ Get API Key |
65
+ | `MONGODB_URI` | [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) โ†’ Database โ†’ Connect |
66
+
67
+ ---
68
+
69
+ ## ๐Ÿ’ป Local Installation Guide
70
+
71
+ ### 1. Install Tesseract OCR (System Binary)
72
+ Python's `pytesseract` requires the underlying Tesseract engine to be installed on your OS.
73
+
74
+ **Windows**
75
+ 1. Download installer from: https://github.com/UB-Mannheim/tesseract/wiki
76
+ 2. Run installer (default path: `C:\Program Files\Tesseract-OCR\`)
77
+ 3. The app is hardcoded to look for this path on Windows.
78
+
79
+ **Linux (Debian/Ubuntu)**
80
+ ```bash
81
+ sudo apt-get update
82
+ sudo apt-get install tesseract-ocr
83
+ ```
84
+
85
+ **macOS**
86
+ ```bash
87
+ brew install tesseract
88
+ ```
89
+
90
+ ### 2. Run the App
91
+ ```bash
92
+ # Clone repository
93
+ git clone https://huggingface.co/spaces/LovnishVerma/ALDDS
94
+ cd ALDDS
95
+
96
+ # Install Dependencies
97
+ pip install -r requirements.txt
98
+
99
+ # Run the Server
100
+ python app.py
101
+ ```
102
+ The interface will launch at **http://127.0.0.1:7860**.
103
+
104
+ ---
105
+
106
+ ## โ˜๏ธ Hugging Face Spaces Deployment
107
+
108
+ If you are deploying ALDDS to Hugging Face Spaces, follow these critical steps:
109
+
110
+ 1. **Set Up Secrets**: Go to your Space **Settings** -> **Variables and secrets**. Add all variables from your `.env` file as **Secrets**.
111
+ 2. **System Dependencies**: Hugging Face runs Debian Linux. The repository includes a `packages.txt` file telling Hugging Face to install `tesseract-ocr` and `libtesseract-dev` during the Docker build.
112
+ 3. **CRLF Warning**: Ensure that `packages.txt` is saved with Unix (`LF`) line endings. If it has Windows (`CRLF`) line endings, the Hugging Face Docker build will fail with a `Package not found` error.
113
+ 4. **Restart**: Always click **Restart Space** after adding or modifying Secrets so the new environment variables are loaded into the container.
114
+
115
+ ---
116
+
117
+ ## ๐Ÿ“Š Extracted JSON Schema
118
+
119
+ The LLM is strictly prompted to extract the following fields. If a field cannot be found, it defaults to `null`.
120
+
121
+ | JSON Key | Description |
122
+ |---|---|
123
+ | `Case_FIR_Number` | FIR or court case reference number |
124
+ | `Act_and_Sections` | Applicable IPC/CRPC legal acts and sections |
125
+ | `Type_of_Document` | Warrant, summon, notice, etc. |
126
+ | `Target_Police_Station` | Police station the document is addressed to |
127
+ | `IO_Name_and_Belt_No` | Investigating Officer's name and belt number |
128
+ | `IO_Mobile_Number` | IO's contact number |
129
+ | `Person_Name_To_Serve` | Name of the person to be served/arrested |
130
+ | `Person_Address` | Address of the target person |
131
+ | `Court_Name` | Issuing court name |
132
+ | `Hearing_Date` | Scheduled hearing or appearance date (DD-MM-YYYY) |
133
+
134
+ ---
135
+ *Built to streamline station workflows, eliminate manual data entry, and instantly notify field officers.*
 
 
 
 
app.py CHANGED
@@ -14,6 +14,7 @@ import re
14
  import json
15
  import concurrent.futures
16
  import requests
 
17
 
18
  import gradio as gr
19
  import cloudinary
@@ -65,6 +66,15 @@ if mongo_uri:
65
  print(f"โŒ MongoDB connection failed: {exc}")
66
  collection = None
67
 
 
 
 
 
 
 
 
 
 
68
 
69
  # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
70
  # B. Core Processing Logic
@@ -608,13 +618,17 @@ with gr.Blocks(
608
  raw_ocr_out = gr.Textbox(label="๐Ÿ” Raw OCR Text", lines=8, interactive=False)
609
  json_out = gr.JSON(label="๐Ÿ“‹ Extracted Structured Data (JSON)")
610
 
611
- gr.Markdown("### ๐Ÿ“จ Notify Investigating Officer")
612
  with gr.Row():
613
- manual_id_in = gr.Textbox(label="Telegram Chat ID", placeholder="Enter ID here...", scale=3)
614
- send_alert_btn = gr.Button("๐Ÿšจ Send Telegram Alert", variant="secondary", scale=1)
615
- alert_status_out = gr.HTML()
 
616
 
617
- bot_token_hidden = gr.Textbox(value=os.environ.get("TELEGRAM_BOT_TOKEN", ""), visible=False)
 
 
 
618
 
619
  def _make_status_html(icon, message, color):
620
  return (
@@ -662,45 +676,32 @@ with gr.Blocks(
662
  outputs=[status_out, cloudinary_url_out, cloudinary_link_html, raw_ocr_out, json_out],
663
  )
664
 
665
- js_code = """
666
- async (chat_id, url, data, bot_token) => {
667
- if (!chat_id) return "โŒ Please enter a Chat ID.";
668
  if (!url) return "โŒ No document uploaded yet.";
669
- if (!bot_token) return "โŒ Bot token not configured in .env";
670
 
671
  let case_no = data && data["Case_FIR_Number"] ? data["Case_FIR_Number"] : "Unknown Case";
672
  let court = data && data["Court_Name"] ? data["Court_Name"] : "Unknown Court";
673
 
674
  let text = `๐Ÿšจ *New Warrant Uploaded*\\n*Case:* ${case_no}\\n*Court:* ${court}\\n*Document:* ${url}`;
675
- let api_url = `https://api.telegram.org/bot${bot_token}/sendMessage`;
676
 
677
- try {
678
- let res = await fetch(api_url, {
679
- method: "POST",
680
- headers: { "Content-Type": "application/json" },
681
- body: JSON.stringify({
682
- chat_id: chat_id.trim(),
683
- text: text,
684
- parse_mode: "Markdown"
685
- })
686
- });
687
- let out = await res.json();
688
- if (out.ok) {
689
- return `โœ… Alert sent successfully to ${chat_id}!`;
690
- } else {
691
- return `โŒ Failed: ${out.description}`;
692
- }
693
- } catch (e) {
694
- return `โŒ Error connecting to Telegram: ${e.message}`;
695
- }
696
  }
697
  """
698
 
699
- send_alert_btn.click(
700
  fn=None,
701
- inputs=[manual_id_in, cloudinary_url_out, json_out, bot_token_hidden],
702
- outputs=[alert_status_out],
703
- js=js_code
704
  )
705
 
706
  with gr.Tab("๐Ÿ‘ฎ Live Police Dashboard"):
 
14
  import json
15
  import concurrent.futures
16
  import requests
17
+ import csv
18
 
19
  import gradio as gr
20
  import cloudinary
 
66
  print(f"โŒ MongoDB connection failed: {exc}")
67
  collection = None
68
 
69
+ # Load Officers Database
70
+ officers_db = {}
71
+ try:
72
+ with open("officers.csv", "r", encoding="utf-8") as f:
73
+ reader = csv.DictReader(f)
74
+ for row in reader:
75
+ officers_db[row["Officer_Name"]] = row["Phone_Number"]
76
+ except Exception as e:
77
+ print(f"โš ๏ธ Could not load officers.csv: {e}")
78
 
79
  # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
80
  # B. Core Processing Logic
 
618
  raw_ocr_out = gr.Textbox(label="๐Ÿ” Raw OCR Text", lines=8, interactive=False)
619
  json_out = gr.JSON(label="๐Ÿ“‹ Extracted Structured Data (JSON)")
620
 
621
+ gr.Markdown("### ๐Ÿ“จ Notify Investigating Officer (WhatsApp)")
622
  with gr.Row():
623
+ io_dropdown = gr.Dropdown(label="Select Officer (from CSV)", choices=list(officers_db.keys()), scale=2)
624
+ manual_phone_in = gr.Textbox(label="WhatsApp Mobile No.", placeholder="e.g. 919876543210", scale=2)
625
+ send_wa_btn = gr.Button("๐Ÿ’ฌ Send via WhatsApp", variant="secondary", scale=1)
626
+ wa_status_out = gr.HTML()
627
 
628
+ # Auto-fill phone when IO selected
629
+ def update_phone(officer_name):
630
+ return officers_db.get(officer_name, "")
631
+ io_dropdown.change(fn=update_phone, inputs=[io_dropdown], outputs=[manual_phone_in])
632
 
633
  def _make_status_html(icon, message, color):
634
  return (
 
676
  outputs=[status_out, cloudinary_url_out, cloudinary_link_html, raw_ocr_out, json_out],
677
  )
678
 
679
+ js_code_wa = """
680
+ (phone, url, data) => {
681
+ if (!phone) return "โŒ Please enter a WhatsApp number.";
682
  if (!url) return "โŒ No document uploaded yet.";
 
683
 
684
  let case_no = data && data["Case_FIR_Number"] ? data["Case_FIR_Number"] : "Unknown Case";
685
  let court = data && data["Court_Name"] ? data["Court_Name"] : "Unknown Court";
686
 
687
  let text = `๐Ÿšจ *New Warrant Uploaded*\\n*Case:* ${case_no}\\n*Court:* ${court}\\n*Document:* ${url}`;
688
+ let encoded_text = encodeURIComponent(text);
689
 
690
+ let clean_phone = phone.replace(/[^0-9]/g, '');
691
+ if (!clean_phone) return "โŒ Invalid phone number.";
692
+
693
+ let wa_url = `https://wa.me/${clean_phone}?text=${encoded_text}`;
694
+ window.open(wa_url, '_blank');
695
+
696
+ return `โœ… WhatsApp opened for ${phone}! Click Send in WhatsApp.`;
 
 
 
 
 
 
 
 
 
 
 
 
697
  }
698
  """
699
 
700
+ send_wa_btn.click(
701
  fn=None,
702
+ inputs=[manual_phone_in, cloudinary_url_out, json_out],
703
+ outputs=[wa_status_out],
704
+ js=js_code_wa
705
  )
706
 
707
  with gr.Tab("๐Ÿ‘ฎ Live Police Dashboard"):
officers.csv ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ Officer_Name,Phone_Number
2
+ Insp. Lovnish Verma (101),+918894869371
3
+ SI Amit Singh (102),+919876543211
4
+ ASI Vikram Sharma (103),+919876543212
5
+ HC Ramesh Chand (104),+919876543213
6
+ SI Vikas Kumar (105),+919876543214
test_network.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+
3
+ try:
4
+ print("Testing basic internet access...")
5
+ google_check = requests.get("https://www.google.com", timeout=10)
6
+ print(f"Google status: {google_check.status_code}")
7
+
8
+ print("Testing Telegram endpoint access...")
9
+ telegram_check = requests.get("https://api.telegram.org", timeout=10)
10
+ print(f"Telegram status: {telegram_check.status_code}")
11
+ except Exception as e:
12
+ print(f"โŒ Network blocked: {e}")