hikmat123 commited on
Commit
cef56ef
·
1 Parent(s): 937fe69

update the app

Browse files
Files changed (3) hide show
  1. .gitignore +2 -1
  2. README.md +1 -1
  3. app.py +62 -10
.gitignore CHANGED
@@ -3,4 +3,5 @@ __pycache__/
3
  route_venv/
4
  .env
5
  /updates
6
- /github code/
 
 
3
  route_venv/
4
  .env
5
  /updates
6
+ /github code/
7
+ Project_Inventory_and_Technical_Overview.md
README.md CHANGED
@@ -16,4 +16,4 @@ short_description: Route image to structured JSON with constraint extraction.
16
 
17
  Upload a route document image — get clean structured JSON with constraint classification.
18
 
19
- **Model:** `Qwen/Qwen2.5-0.5B-Instruct` (free, open-source, runs on CPU)
 
16
 
17
  Upload a route document image — get clean structured JSON with constraint classification.
18
 
19
+ **Model:** `gemini-flash-latest` (via Google GenAI) and `PaddleOCR` (Lightweight)
app.py CHANGED
@@ -1,15 +1,6 @@
1
  """
2
  app.py – OCR Route Data Extraction | Hugging Face Space
3
  =======================================================
4
-
5
- Improved Pipeline:
6
- 1. Engine-specific preprocessing
7
- 2. OCR with EasyOCR OR Lightweight PaddleOCR
8
- 3. OCR normalization
9
- 4. Content-based semantic column classification
10
- 5. Row reconstruction
11
- 6. Rule-based constraint extraction
12
- 7. Structured JSON output
13
  """
14
 
15
  from __future__ import annotations
@@ -23,12 +14,57 @@ import logging
23
  import re
24
  import time
25
  from statistics import median
26
- from typing import Optional
27
 
28
  import cv2
29
  import gradio as gr
30
  import numpy as np
31
  from PIL import Image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
 
34
  # ============================================================
@@ -753,6 +789,7 @@ def run_gemini_correction(image_pil: Image.Image, initial_json: dict, api_key: s
753
 
754
  client = genai.Client(api_key=api_key)
755
 
 
756
  prompt = f"""
757
  You are an expert OCR data extraction and validation system for route documents.
758
  You are given an image of a route document and an initial JSON extraction. The basic OCR system is flawed and often misses data or misinterprets columns.
@@ -770,6 +807,9 @@ CRITICAL EXTRACTION RULES:
770
 
771
  Output ONLY valid JSON matching the exact schema.
772
 
 
 
 
773
  Initial JSON (FLAWED - USE FOR REFERENCE ONLY):
774
  {json.dumps(initial_json, indent=2)}
775
  """
@@ -779,11 +819,17 @@ Initial JSON (FLAWED - USE FOR REFERENCE ONLY):
779
  contents=[image_pil, prompt],
780
  config=types.GenerateContentConfig(
781
  response_mime_type="application/json",
 
782
  temperature=0.0
783
  )
784
  )
785
 
786
  try:
 
 
 
 
 
787
  return json.loads(response.text)
788
  except json.JSONDecodeError:
789
  raise ValueError(f"Failed to parse JSON from Gemini response:\n{response.text}")
@@ -986,6 +1032,11 @@ def run_pipeline(
986
  "steps": steps
987
  }
988
 
 
 
 
 
 
989
  if "Gemini" in ocr_engine or api_key.strip():
990
  progress(0.85, desc="Validating the JSON output ...")
991
  try:
@@ -999,6 +1050,7 @@ def run_pipeline(
999
  result["accuracy_metrics"] = {}
1000
  result["accuracy_metrics"]["total_accuracy"] = 98.5
1001
  result["accuracy_metrics"]["gemini_confidence"] = "High"
 
1002
  except Exception as e:
1003
  import traceback; traceback.print_exc()
1004
  error_text = str(e)
 
1
  """
2
  app.py – OCR Route Data Extraction | Hugging Face Space
3
  =======================================================
 
 
 
 
 
 
 
 
 
4
  """
5
 
6
  from __future__ import annotations
 
14
  import re
15
  import time
16
  from statistics import median
17
+ from typing import List, Optional
18
 
19
  import cv2
20
  import gradio as gr
21
  import numpy as np
22
  from PIL import Image
23
+ from pydantic import BaseModel, ConfigDict, Field, ValidationError
24
+
25
+
26
+ class ConstraintModel(BaseModel):
27
+ model_config = ConfigDict(populate_by_name=True)
28
+
29
+ type: str
30
+ action: str
31
+ from_: str = Field(alias="from")
32
+ to: str
33
+ priority: Optional[str] = None
34
+
35
+
36
+ class StepModel(BaseModel):
37
+ step: int = Field(ge=1)
38
+ given_miles: float = Field(ge=0)
39
+ road: str
40
+ instruction: str
41
+ distance: float = Field(ge=0)
42
+ est_time: str = Field(pattern=r"^\d{2}:\d{2}$")
43
+ constraints: List[ConstraintModel] = Field(default_factory=list)
44
+
45
+
46
+ class AccuracyMetricsModel(BaseModel):
47
+ ocr_confidence: Optional[float] = Field(default=None, ge=0, le=100)
48
+ extraction_score: Optional[float] = Field(default=None, ge=0, le=100)
49
+ total_accuracy: Optional[float] = Field(default=None, ge=0, le=100)
50
+ gemini_confidence: Optional[str] = None
51
+
52
+
53
+ class RouteExtractionModel(BaseModel):
54
+ source: str
55
+ extracted_at: str
56
+ ocr_engine: str
57
+ extraction: str
58
+ accuracy_metrics: Optional[AccuracyMetricsModel] = None
59
+ total_steps: int = Field(ge=0)
60
+ total_miles: float = Field(ge=0)
61
+ total_time: str = Field(pattern=r"^\d{2}:\d{2}$")
62
+ steps: List[StepModel]
63
+ warning: Optional[str] = None
64
+ gemini_error: Optional[str] = None
65
+
66
+
67
+ ROUTE_EXTRACTION_JSON_SCHEMA = RouteExtractionModel.model_json_schema()
68
 
69
 
70
  # ============================================================
 
789
 
790
  client = genai.Client(api_key=api_key)
791
 
792
+ schema_text = json.dumps(ROUTE_EXTRACTION_JSON_SCHEMA, indent=2)
793
  prompt = f"""
794
  You are an expert OCR data extraction and validation system for route documents.
795
  You are given an image of a route document and an initial JSON extraction. The basic OCR system is flawed and often misses data or misinterprets columns.
 
807
 
808
  Output ONLY valid JSON matching the exact schema.
809
 
810
+ JSON SCHEMA (MUST MATCH):
811
+ {schema_text}
812
+
813
  Initial JSON (FLAWED - USE FOR REFERENCE ONLY):
814
  {json.dumps(initial_json, indent=2)}
815
  """
 
819
  contents=[image_pil, prompt],
820
  config=types.GenerateContentConfig(
821
  response_mime_type="application/json",
822
+ response_schema=RouteExtractionModel,
823
  temperature=0.0
824
  )
825
  )
826
 
827
  try:
828
+ parsed = getattr(response, "parsed", None)
829
+ if parsed is not None:
830
+ if hasattr(parsed, "model_dump"):
831
+ return parsed.model_dump(by_alias=True)
832
+ return parsed
833
  return json.loads(response.text)
834
  except json.JSONDecodeError:
835
  raise ValueError(f"Failed to parse JSON from Gemini response:\n{response.text}")
 
1032
  "steps": steps
1033
  }
1034
 
1035
+ try:
1036
+ result = RouteExtractionModel.model_validate(result).model_dump(by_alias=True)
1037
+ except ValidationError as e:
1038
+ log.warning("Schema validation failed for rule-based output: %s", e)
1039
+
1040
  if "Gemini" in ocr_engine or api_key.strip():
1041
  progress(0.85, desc="Validating the JSON output ...")
1042
  try:
 
1050
  result["accuracy_metrics"] = {}
1051
  result["accuracy_metrics"]["total_accuracy"] = 98.5
1052
  result["accuracy_metrics"]["gemini_confidence"] = "High"
1053
+ result = RouteExtractionModel.model_validate(result).model_dump(by_alias=True)
1054
  except Exception as e:
1055
  import traceback; traceback.print_exc()
1056
  error_text = str(e)