Spaces:
Sleeping
Sleeping
Venkat V
commited on
Commit
Β·
28b59e0
1
Parent(s):
0b65367
lazy loading of model
Browse files- api_backend.py +55 -16
- combined_app.py +6 -5
api_backend.py
CHANGED
@@ -19,24 +19,61 @@ import json
|
|
19 |
import base64
|
20 |
import os
|
21 |
|
22 |
-
# π§ Import local processing modules
|
23 |
-
from yolo_module import run_yolo
|
24 |
-
from ocr_module import extract_text, count_elements, validate_structure
|
25 |
-
from graph_module import map_arrows, build_flowchart_json
|
26 |
-
from summarizer_module import summarize_flowchart
|
27 |
-
|
28 |
# π₯ Initialize FastAPI app
|
29 |
app = FastAPI()
|
30 |
|
31 |
-
# π Enable CORS
|
32 |
app.add_middleware(
|
33 |
CORSMiddleware,
|
34 |
-
allow_origins=["*"], #
|
35 |
allow_credentials=True,
|
36 |
-
allow_methods=["
|
37 |
allow_headers=["*"],
|
|
|
38 |
)
|
39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
|
41 |
@app.post("/process-image")
|
42 |
async def process_image(
|
@@ -54,6 +91,9 @@ async def process_image(
|
|
54 |
Returns:
|
55 |
JSONResponse: Contains flowchart structure, summary, debug output, and optional YOLO overlay.
|
56 |
"""
|
|
|
|
|
|
|
57 |
debug_mode = debug.lower() == "true"
|
58 |
debug_log = []
|
59 |
|
@@ -69,25 +109,24 @@ async def process_image(
|
|
69 |
print("β
Image converted to RGB")
|
70 |
|
71 |
# π¦ YOLO Detection for boxes and arrows
|
72 |
-
boxes, arrows, vis_debug = run_yolo(image)
|
73 |
if debug_mode:
|
74 |
debug_log.append(f"π¦ Detected {len(boxes)} boxes, {len(arrows)} arrows")
|
75 |
|
76 |
# π Run OCR on each detected box
|
77 |
for box in boxes:
|
78 |
-
box["text"] = extract_text(image, box["bbox"], debug=debug_mode)
|
79 |
print(f"π OCR for {box['id']}: {box['text']}")
|
80 |
if debug_mode:
|
81 |
debug_log.append(f"π {box['id']}: {box['text']}")
|
82 |
|
83 |
-
|
84 |
# π§ Build structured JSON from nodes and edges
|
85 |
-
flowchart_json = build_flowchart_json(boxes, arrows)
|
86 |
print("π§ Flowchart JSON:", json.dumps(flowchart_json, indent=2))
|
87 |
|
88 |
# β
Validate structure
|
89 |
-
structure_info = count_elements(boxes, arrows, debug=debug_mode)
|
90 |
-
validation = validate_structure(
|
91 |
flowchart_json,
|
92 |
expected_boxes=structure_info["box_count"],
|
93 |
expected_arrows=len(arrows),
|
@@ -97,7 +136,7 @@ async def process_image(
|
|
97 |
debug_log.append(f"π§Ύ Validation: {validation}")
|
98 |
|
99 |
# βοΈ Generate plain-English summary
|
100 |
-
summary = summarize_flowchart(flowchart_json)
|
101 |
print("π Summary:", summary)
|
102 |
|
103 |
# πΌοΈ Encode YOLO debug image (if debug enabled)
|
|
|
19 |
import base64
|
20 |
import os
|
21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
# π₯ Initialize FastAPI app
|
23 |
app = FastAPI()
|
24 |
|
25 |
+
# π Enable CORS with more specific configuration for Hugging Face Spaces
|
26 |
app.add_middleware(
|
27 |
CORSMiddleware,
|
28 |
+
allow_origins=["*", "https://venkatviswa-flowchart-to-text.hf.space"], # Include your specific domain
|
29 |
allow_credentials=True,
|
30 |
+
allow_methods=["GET", "POST", "OPTIONS"], # Explicitly allow methods
|
31 |
allow_headers=["*"],
|
32 |
+
expose_headers=["*"],
|
33 |
)
|
34 |
|
35 |
+
# Add a health check endpoint
|
36 |
+
@app.get("/")
|
37 |
+
async def health_check():
|
38 |
+
"""Health check endpoint to verify API is running."""
|
39 |
+
return {"status": "ok", "message": "API is running"}
|
40 |
+
|
41 |
+
|
42 |
+
@app.options("/process-image")
|
43 |
+
async def options_process_image():
|
44 |
+
"""Handle OPTIONS requests for the process-image endpoint."""
|
45 |
+
return {}
|
46 |
+
|
47 |
+
|
48 |
+
# Lazy-loading for ML modules to avoid startup issues
|
49 |
+
SKIP_MODEL_LOADING = os.getenv("SKIP_MODEL_LOADING", "0") == "1"
|
50 |
+
yolo_module = None
|
51 |
+
ocr_module = None
|
52 |
+
graph_module = None
|
53 |
+
summarizer_module = None
|
54 |
+
|
55 |
+
def load_modules():
|
56 |
+
global yolo_module, ocr_module, graph_module, summarizer_module
|
57 |
+
|
58 |
+
if yolo_module is None:
|
59 |
+
# Only import these when needed, not during startup
|
60 |
+
from yolo_module import run_yolo as yolo_run
|
61 |
+
from ocr_module import extract_text as ocr_extract, count_elements, validate_structure
|
62 |
+
from graph_module import map_arrows, build_flowchart_json
|
63 |
+
from summarizer_module import summarize_flowchart
|
64 |
+
|
65 |
+
yolo_module = {"run_yolo": yolo_run}
|
66 |
+
ocr_module = {
|
67 |
+
"extract_text": ocr_extract,
|
68 |
+
"count_elements": count_elements,
|
69 |
+
"validate_structure": validate_structure
|
70 |
+
}
|
71 |
+
graph_module = {
|
72 |
+
"map_arrows": map_arrows,
|
73 |
+
"build_flowchart_json": build_flowchart_json
|
74 |
+
}
|
75 |
+
summarizer_module = {"summarize_flowchart": summarize_flowchart}
|
76 |
+
|
77 |
|
78 |
@app.post("/process-image")
|
79 |
async def process_image(
|
|
|
91 |
Returns:
|
92 |
JSONResponse: Contains flowchart structure, summary, debug output, and optional YOLO overlay.
|
93 |
"""
|
94 |
+
# Lazy load modules when first request comes in
|
95 |
+
load_modules()
|
96 |
+
|
97 |
debug_mode = debug.lower() == "true"
|
98 |
debug_log = []
|
99 |
|
|
|
109 |
print("β
Image converted to RGB")
|
110 |
|
111 |
# π¦ YOLO Detection for boxes and arrows
|
112 |
+
boxes, arrows, vis_debug = yolo_module["run_yolo"](image)
|
113 |
if debug_mode:
|
114 |
debug_log.append(f"π¦ Detected {len(boxes)} boxes, {len(arrows)} arrows")
|
115 |
|
116 |
# π Run OCR on each detected box
|
117 |
for box in boxes:
|
118 |
+
box["text"] = ocr_module["extract_text"](image, box["bbox"], debug=debug_mode)
|
119 |
print(f"π OCR for {box['id']}: {box['text']}")
|
120 |
if debug_mode:
|
121 |
debug_log.append(f"π {box['id']}: {box['text']}")
|
122 |
|
|
|
123 |
# π§ Build structured JSON from nodes and edges
|
124 |
+
flowchart_json = graph_module["build_flowchart_json"](boxes, arrows)
|
125 |
print("π§ Flowchart JSON:", json.dumps(flowchart_json, indent=2))
|
126 |
|
127 |
# β
Validate structure
|
128 |
+
structure_info = ocr_module["count_elements"](boxes, arrows, debug=debug_mode)
|
129 |
+
validation = ocr_module["validate_structure"](
|
130 |
flowchart_json,
|
131 |
expected_boxes=structure_info["box_count"],
|
132 |
expected_arrows=len(arrows),
|
|
|
136 |
debug_log.append(f"π§Ύ Validation: {validation}")
|
137 |
|
138 |
# βοΈ Generate plain-English summary
|
139 |
+
summary = summarizer_module["summarize_flowchart"](flowchart_json)
|
140 |
print("π Summary:", summary)
|
141 |
|
142 |
# πΌοΈ Encode YOLO debug image (if debug enabled)
|
combined_app.py
CHANGED
@@ -1,10 +1,7 @@
|
|
1 |
"""
|
2 |
combined_app.py - A unified approach that runs both FastAPI and Streamlit in a single process.
|
3 |
This is specifically designed for Hugging Face Spaces deployments.
|
4 |
-
|
5 |
-
Usage:
|
6 |
-
1. Make this your entry point in Hugging Face Spaces
|
7 |
-
2. It will start the FastAPI backend and then launch Streamlit in the same process
|
8 |
"""
|
9 |
|
10 |
import streamlit as st
|
@@ -20,7 +17,11 @@ import subprocess
|
|
20 |
# Use environment variable to determine if we're in Spaces
|
21 |
IS_SPACE = "SPACE_ID" in os.environ
|
22 |
|
23 |
-
# Import FastAPI app
|
|
|
|
|
|
|
|
|
24 |
from api_backend import app as fastapi_app
|
25 |
|
26 |
# Add a route for checking if the API is running
|
|
|
1 |
"""
|
2 |
combined_app.py - A unified approach that runs both FastAPI and Streamlit in a single process.
|
3 |
This is specifically designed for Hugging Face Spaces deployments.
|
4 |
+
Uses lazy loading to avoid loading models during startup.
|
|
|
|
|
|
|
5 |
"""
|
6 |
|
7 |
import streamlit as st
|
|
|
17 |
# Use environment variable to determine if we're in Spaces
|
18 |
IS_SPACE = "SPACE_ID" in os.environ
|
19 |
|
20 |
+
# Import FastAPI app but avoid importing modules that load models
|
21 |
+
# This is critical to prevent infinite loops during deployment
|
22 |
+
os.environ["SKIP_MODEL_LOADING"] = "1"
|
23 |
+
|
24 |
+
# Now import the FastAPI app
|
25 |
from api_backend import app as fastapi_app
|
26 |
|
27 |
# Add a route for checking if the API is running
|