Varshithdharmajv commited on
Commit
5d4095b
·
verified ·
1 Parent(s): d49a022

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +230 -230
app.py CHANGED
@@ -1,230 +1,230 @@
1
- import gradio as gr
2
- import os
3
- import time
4
- import cv2
5
- import numpy as np
6
- from PIL import Image
7
- import tempfile
8
- import json
9
- import re
10
-
11
- # Import consolidated modules
12
- from ocr_module import MVM2OCREngine
13
- from reasoning_engine import run_agent_orchestrator
14
- from verification_service import calculate_symbolic_score
15
- from consensus_fusion import evaluate_consensus
16
- from report_module import generate_mvm2_report, export_to_pdf
17
- from image_enhancing import ImageEnhancer
18
- from flow_module import generate_flow_html
19
-
20
- # Initialize Engines
21
- ocr_engine = MVM2OCREngine()
22
- enhancer = ImageEnhancer(sigma=1.2)
23
-
24
- # Load custom CSS
25
- with open("theme.css", "r") as f:
26
- css_content = f.read()
27
-
28
- def create_gauge(label, value, color="#6366f1"):
29
- """Generates an animated SVG circular gauge."""
30
- percentage = max(0, min(100, value * 100))
31
- dash_offset = 251.2 * (1 - percentage / 100)
32
- return f"""
33
- <div class="gauge-container">
34
- <svg width="100" height="100" viewBox="0 0 100 100">
35
- <circle class="circle-bg" cx="50" cy="50" r="40" />
36
- <circle class="circle-progress" cx="50" cy="50" r="40"
37
- stroke="{color}" stroke-dasharray="251.2"
38
- stroke-dashoffset="{dash_offset}"
39
- style="filter: drop-shadow(0 0 5px {color}88);"/>
40
- <text x="50" y="55" text-anchor="middle" font-size="18" font-weight="bold" fill="white">{int(percentage)}%</text>
41
- </svg>
42
- <div style="font-size: 0.8em; color: #94a3b8; font-weight: 500;">{label}</div>
43
- </div>
44
- """
45
-
46
- def format_step_viewer(consensus_result):
47
- """Formats the Reasoning Trace with Step-Level Consensus highlights."""
48
- html = '<div style="display: flex; flex-direction: column; gap: 12px;">'
49
-
50
- # We aggregate steps from all agents for a collective view
51
- agent_data = consensus_result.get("detail_scores", [])
52
-
53
- for agent in agent_data:
54
- # Simulate step-level analysis for UI purposes:
55
- # In a real system, we'd have Score_j per step. Here we use the agent's overall score.
56
- score = agent["Score_j"]
57
- status_class = "step-valid" if score >= 0.7 else "step-warning"
58
- icon = "✅" if score >= 0.7 else "⚠️"
59
- glow_style = "box-shadow: 0 0 10px rgba(16, 185, 129, 0.2);" if score >= 0.7 else "box-shadow: 0 0 10px rgba(245, 158, 11, 0.2);"
60
-
61
- # Get matching agent response for trace
62
- # (This assumes agent_responses were passed in or stored)
63
- # For the UI, we'll just show the representative trace from valid agents
64
- if not agent["is_hallucinating"] or score > 0.4:
65
- html += f"""
66
- <div class="glass-card reasoning-step {status_class}" style="{glow_style}">
67
- <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
68
- <span class="monospace" style="color: #6366f1; font-weight: 600;">{agent['agent']} Reasoning Path</span>
69
- <span style="font-size: 0.8em; background: rgba(0,0,0,0.3); padding: 2px 8px; border-radius: 4px;">Consensus: {score:.2f} {icon}</span>
70
- </div>
71
- <div style="font-size: 0.9em; line-height: 1.6; color: #cbd5e1;">
72
- {"<br>".join([f"• {step}" for step in agent.get('reasoning_trace', ['Processing...'])])}
73
- </div>
74
- </div>
75
- """
76
- html += "</div>"
77
- return html
78
-
79
- def process_mvm2_pipeline(image, auto_enhance):
80
- if image is None:
81
- return None, "Please upload an image.", None, "", None, ""
82
-
83
- # 1. Preprocessing & Preview
84
- enhanced_img_np, meta = enhancer.enhance(image)
85
- temp_img_path = os.path.join(tempfile.gettempdir(), 'input_processed.png')
86
- cv2.imwrite(temp_img_path, enhanced_img_np)
87
-
88
- preview_img = Image.fromarray(cv2.cvtColor(enhanced_img_np, cv2.COLOR_BGR2RGB))
89
-
90
- # 2. OCR Extraction
91
- ocr_results = ocr_engine.process_image(temp_img_path)
92
- latex_text = ocr_results['latex_output']
93
- ocr_conf = ocr_results['weighted_confidence']
94
-
95
- # Update flow for current state (Visual sync)
96
- flow_html = generate_flow_html("reasoning") # Transitioning to reasoning
97
-
98
- # 3. Multi-Agent Reasoning
99
- agent_responses = run_agent_orchestrator(latex_text)
100
-
101
- # Attach traces back to detail_scores for UI formatting
102
- for i, res in enumerate(agent_responses):
103
- agent_responses[i]["response"]["agent_id"] = i # tag
104
-
105
- # 4. Consensus Fusion
106
- consensus_result = evaluate_consensus(agent_responses, ocr_confidence=ocr_conf)
107
-
108
- # Map traces to detail_scores for UI
109
- for i, score_data in enumerate(consensus_result["detail_scores"]):
110
- # Match by agent name
111
- for res in agent_responses:
112
- if res["agent"] == score_data["agent"]:
113
- consensus_result["detail_scores"][i]["reasoning_trace"] = res["response"].get("Reasoning Trace", [])
114
- break
115
-
116
- # 5. Gauges & UI Elements
117
- avg_v_sym = np.mean([s["V_sym"] for s in consensus_result["detail_scores"]])
118
- avg_l_logic = np.mean([s["L_logic"] for s in consensus_result["detail_scores"]])
119
- avg_c_clf = np.mean([s["C_clf"] for s in consensus_result["detail_scores"]])
120
-
121
- gauges_html = f"""
122
- <div class="signal-panel">
123
- {create_gauge("Symbolic", avg_v_sym, "#10b981")}
124
- {create_gauge("Logic", avg_l_logic, "#6366f1")}
125
- {create_gauge("Classifier", avg_c_clf, "#8b5cf6")}
126
- </div>
127
- """
128
-
129
- # Final Calibration Bar
130
- winner = consensus_result["winning_score"]
131
- calibrated_conf = winner * (0.9 + 0.1 * ocr_conf)
132
- conf_bar = f"""
133
- <div style="margin-top: 20px;">
134
- <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
135
- <span style="font-weight: 600; color: #94a3b8;">Final Confidence Calibration</span>
136
- <span style="color: #10b981; font-weight: bold;">{calibrated_conf:.3f}</span>
137
- </div>
138
- <div style="width: 100%; bg: rgba(255,255,255,0.05); height: 8px; border-radius: 4px; overflow: hidden;">
139
- <div style="width: {min(100, calibrated_conf*50)}%; background: linear-gradient(90deg, #6366f1 0%, #10b981 100%); height: 100%; transition: width 1s ease;"></div>
140
- </div>
141
- </div>
142
- """
143
-
144
- # 6. Report & PDF
145
- reports = generate_mvm2_report(consensus_result, latex_text, ocr_conf)
146
- md_report = format_step_viewer(consensus_result)
147
-
148
- pdf_path = os.path.join(tempfile.gettempdir(), f'MVM2_Report_{reports["report_id"]}.pdf')
149
- export_to_pdf(json.loads(reports['json']), pdf_path)
150
-
151
- final_flow = generate_flow_html("success")
152
-
153
- return preview_img, latex_text, gauges_html, conf_bar, md_report, pdf_path, final_flow
154
-
155
- # Build Interface
156
- with gr.Blocks(css=css_content, title="MVM²: Senior UI AI Dashboard") as demo:
157
- with gr.Row(elem_id="header-row"):
158
- gr.Markdown(
159
- """
160
- <div style="text-align: center; padding: 20px 0;">
161
- <h1 style="font-size: 2.5em; margin-bottom: 0;">MVM² <span style="color: #6366f1;">Neuro-Symbolic</span></h1>
162
- <p style="color: #94a3b8; font-size: 1.1em; margin-top: 8px;">High-Fidelity Mathematical Verification & Consensus Dashboard</p>
163
- </div>
164
- """
165
- )
166
-
167
- with gr.Row():
168
- # --- LEFT PANEL: Upload & Preview ---
169
- with gr.Column(scale=1, variant="panel"):
170
- gr.Markdown("### 📤 Input Intelligence")
171
- input_img = gr.Image(type="pil", label="Capture Solution", elem_classes="glass-card")
172
- enhance_toggle = gr.Checkbox(label="Enable Opti-Scan Preprocessing", value=True)
173
- run_btn = gr.Button("INITIALIZE VERIFICATION", variant="primary", elem_classes="download-btn")
174
-
175
- gr.Markdown("#### 🔍 Preprocessing Preview")
176
- preview_output = gr.Image(label="Enhanced Signal", interactive=False, elem_classes="preview-img")
177
-
178
- # --- CENTER STAGE: Canvas ---
179
- with gr.Column(scale=2):
180
- with gr.Tabs():
181
- with gr.TabItem("Solver Visualization"):
182
- gr.Markdown("### 🎨 MVM² Verification Canvas")
183
- with gr.Group(elem_classes="glass-card"):
184
- canvas_latex = gr.Textbox(label="Canonical LaTeX Transcription", lines=2, interactive=False, elem_classes="monospace")
185
- calib_bar_html = gr.HTML()
186
-
187
- gr.Markdown("### 🪜 Dynamic Reasoning Trace")
188
- trace_html = gr.HTML()
189
-
190
- with gr.TabItem("How It Works (Architecture Flow)"):
191
- gr.Markdown("### 🚀 Real-Time Pipeline Visualization")
192
- flow_view = gr.HTML(generate_flow_html("idle"))
193
- gr.Markdown(
194
- """
195
- **Pipeline Phases:**
196
- 1. **Enhance:** CLAHE & Gaussian Blur noise reduction.
197
- 2. **OCR:** Pix2Text LaTeX structure reconstruction.
198
- 3. **Reasoning:** Quad-agent parallel logic processing.
199
- 4. **Verification:** SymPy deterministic symbolic check.
200
- 5. **Consensus:** Multi-signal weighted confidence fusion.
201
- """
202
- )
203
-
204
- # --- RIGHT PANEL: Signal Intel ---
205
- with gr.Column(scale=1, variant="panel"):
206
- gr.Markdown("### ⚡ Signal Intelligence")
207
- with gr.Group(elem_classes="glass-card"):
208
- signal_gauges = gr.HTML()
209
-
210
- gr.Markdown("### 📄 Educational Assessment")
211
- download_btn = gr.File(label="Download Diagnostic PDF", elem_classes="download-btn")
212
-
213
- with gr.Group(elem_classes="glass-card status-box"):
214
- gr.Markdown(
215
- """
216
- **System Status**
217
- - Pix2Text VLM: `Online`
218
- - SymPy Core: `1.12.0`
219
- - Consensus: `4-Agent parallel`
220
- """
221
- )
222
-
223
- run_btn.click(
224
- fn=process_mvm2_pipeline,
225
- inputs=[input_img, enhance_toggle],
226
- outputs=[preview_output, canvas_latex, signal_gauges, calib_bar_html, trace_html, download_btn, flow_view]
227
- )
228
-
229
- if __name__ == "__main__":
230
- demo.launch()
 
1
+ import gradio as gr
2
+ import os
3
+ import time
4
+ import cv2
5
+ import numpy as np
6
+ from PIL import Image
7
+ import tempfile
8
+ import json
9
+ import re
10
+
11
+ # Import consolidated modules
12
+ from ocr_module import MVM2OCREngine
13
+ from reasoning_engine import run_agent_orchestrator
14
+ from verification_service import calculate_symbolic_score
15
+ from consensus_fusion import evaluate_consensus
16
+ from report_module import generate_mvm2_report, export_to_pdf
17
+ from image_enhancing import ImageEnhancer
18
+ from flow_module import generate_flow_html
19
+
20
+ # Initialize Engines
21
+ ocr_engine = MVM2OCREngine()
22
+ enhancer = ImageEnhancer(sigma=1.2)
23
+
24
+ # Load custom CSS
25
+ with open("theme.css", "r") as f:
26
+ css_content = f.read()
27
+
28
+ def create_gauge(label, value, color="#6366f1"):
29
+ """Generates an animated SVG circular gauge."""
30
+ percentage = max(0, min(100, value * 100))
31
+ dash_offset = 251.2 * (1 - percentage / 100)
32
+ return f"""
33
+ <div class="gauge-container">
34
+ <svg width="100" height="100" viewBox="0 0 100 100">
35
+ <circle class="circle-bg" cx="50" cy="50" r="40" />
36
+ <circle class="circle-progress" cx="50" cy="50" r="40"
37
+ stroke="{color}" stroke-dasharray="251.2"
38
+ stroke-dashoffset="{dash_offset}"
39
+ style="filter: drop-shadow(0 0 5px {color}88);"/>
40
+ <text x="50" y="55" text-anchor="middle" font-size="18" font-weight="bold" fill="white">{int(percentage)}%</text>
41
+ </svg>
42
+ <div style="font-size: 0.8em; color: #94a3b8; font-weight: 500;">{label}</div>
43
+ </div>
44
+ """
45
+
46
+ def format_step_viewer(consensus_result):
47
+ """Formats the Reasoning Trace with Step-Level Consensus highlights."""
48
+ html = '<div style="display: flex; flex-direction: column; gap: 12px;">'
49
+
50
+ # We aggregate steps from all agents for a collective view
51
+ agent_data = consensus_result.get("detail_scores", [])
52
+
53
+ for agent in agent_data:
54
+ # Simulate step-level analysis for UI purposes:
55
+ # In a real system, we'd have Score_j per step. Here we use the agent's overall score.
56
+ score = agent["Score_j"]
57
+ status_class = "step-valid" if score >= 0.7 else "step-warning"
58
+ icon = "✅" if score >= 0.7 else "⚠️"
59
+ glow_style = "box-shadow: 0 0 10px rgba(16, 185, 129, 0.2);" if score >= 0.7 else "box-shadow: 0 0 10px rgba(245, 158, 11, 0.2);"
60
+
61
+ # Get matching agent response for trace
62
+ # (This assumes agent_responses were passed in or stored)
63
+ # For the UI, we'll just show the representative trace from valid agents
64
+ if not agent["is_hallucinating"] or score > 0.4:
65
+ html += f"""
66
+ <div class="glass-card reasoning-step {status_class}" style="{glow_style}">
67
+ <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;">
68
+ <span class="monospace" style="color: #6366f1; font-weight: 600;">{agent['agent']} Reasoning Path</span>
69
+ <span style="font-size: 0.8em; background: rgba(0,0,0,0.3); padding: 2px 8px; border-radius: 4px;">Consensus: {score:.2f} {icon}</span>
70
+ </div>
71
+ <div style="font-size: 0.9em; line-height: 1.6; color: #cbd5e1;">
72
+ {"<br>".join([f"• {step}" for step in agent.get('reasoning_trace', ['Processing...'])])}
73
+ </div>
74
+ </div>
75
+ """
76
+ html += "</div>"
77
+ return html
78
+
79
+ def process_mvm2_pipeline(image, auto_enhance):
80
+ if image is None:
81
+ return None, "Please upload an image.", None, "", None, ""
82
+
83
+ # 1. Preprocessing & Preview
84
+ enhanced_img_np, meta = enhancer.enhance(image)
85
+ temp_img_path = os.path.join(tempfile.gettempdir(), 'input_processed.png')
86
+ cv2.imwrite(temp_img_path, enhanced_img_np)
87
+
88
+ preview_img = Image.fromarray(cv2.cvtColor(enhanced_img_np, cv2.COLOR_BGR2RGB))
89
+
90
+ # 2. OCR Extraction
91
+ ocr_results = ocr_engine.process_image(temp_img_path)
92
+ latex_text = ocr_results['latex_output']
93
+ ocr_conf = ocr_results['weighted_confidence']
94
+
95
+ # Update flow for current state (Visual sync)
96
+ flow_html = generate_flow_html("reasoning") # Transitioning to reasoning
97
+
98
+ # 3. Multi-Agent Reasoning
99
+ agent_responses = run_agent_orchestrator(latex_text)
100
+
101
+ # Attach traces back to detail_scores for UI formatting
102
+ for i, res in enumerate(agent_responses):
103
+ agent_responses[i]["response"]["agent_id"] = i # tag
104
+
105
+ # 4. Consensus Fusion
106
+ consensus_result = evaluate_consensus(agent_responses, ocr_confidence=ocr_conf)
107
+
108
+ # Map traces to detail_scores for UI
109
+ for i, score_data in enumerate(consensus_result["detail_scores"]):
110
+ # Match by agent name
111
+ for res in agent_responses:
112
+ if res["agent"] == score_data["agent"]:
113
+ consensus_result["detail_scores"][i]["reasoning_trace"] = res["response"].get("Reasoning Trace", [])
114
+ break
115
+
116
+ # 5. Gauges & UI Elements
117
+ avg_v_sym = np.mean([s["V_sym"] for s in consensus_result["detail_scores"]])
118
+ avg_l_logic = np.mean([s["L_logic"] for s in consensus_result["detail_scores"]])
119
+ avg_c_clf = np.mean([s["C_clf"] for s in consensus_result["detail_scores"]])
120
+
121
+ gauges_html = f"""
122
+ <div class="signal-panel">
123
+ {create_gauge("Symbolic", avg_v_sym, "#10b981")}
124
+ {create_gauge("Logic", avg_l_logic, "#6366f1")}
125
+ {create_gauge("Classifier", avg_c_clf, "#8b5cf6")}
126
+ </div>
127
+ """
128
+
129
+ # Final Calibration Bar
130
+ winner = consensus_result["winning_score"]
131
+ calibrated_conf = winner * (0.9 + 0.1 * ocr_conf)
132
+ conf_bar = f"""
133
+ <div style="margin-top: 20px;">
134
+ <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
135
+ <span style="font-weight: 600; color: #94a3b8;">Final Confidence Calibration</span>
136
+ <span style="color: #10b981; font-weight: bold;">{calibrated_conf:.3f}</span>
137
+ </div>
138
+ <div style="width: 100%; bg: rgba(255,255,255,0.05); height: 8px; border-radius: 4px; overflow: hidden;">
139
+ <div style="width: {min(100, calibrated_conf*50)}%; background: linear-gradient(90deg, #6366f1 0%, #10b981 100%); height: 100%; transition: width 1s ease;"></div>
140
+ </div>
141
+ </div>
142
+ """
143
+
144
+ # 6. Report & PDF
145
+ reports = generate_mvm2_report(consensus_result, latex_text, ocr_conf)
146
+ md_report = format_step_viewer(consensus_result)
147
+
148
+ pdf_path = os.path.join(tempfile.gettempdir(), f'MVM2_Report_{reports["report_id"]}.pdf')
149
+ export_to_pdf(json.loads(reports['json']), pdf_path)
150
+
151
+ final_flow = generate_flow_html("success")
152
+
153
+ return preview_img, latex_text, gauges_html, conf_bar, md_report, pdf_path, final_flow
154
+
155
+ # Build Interface
156
+ with gr.Blocks(css=css_content, title="MVM²: Senior UI AI Dashboard") as demo:
157
+ with gr.Row(elem_id="header-row"):
158
+ gr.Markdown(
159
+ """
160
+ <div style="text-align: center; padding: 20px 0;">
161
+ <h1 style="font-size: 2.5em; margin-bottom: 0;">MVM² <span style="color: #6366f1;">Neuro-Symbolic</span></h1>
162
+ <p style="color: #94a3b8; font-size: 1.1em; margin-top: 8px;">High-Fidelity Mathematical Verification & Consensus Dashboard</p>
163
+ </div>
164
+ """
165
+ )
166
+
167
+ with gr.Row():
168
+ # --- LEFT PANEL: Upload & Preview ---
169
+ with gr.Column(scale=1, variant="panel"):
170
+ gr.Markdown("### 📤 Input Intelligence")
171
+ input_img = gr.Image(type="pil", label="Capture Solution", elem_classes="glass-card")
172
+ enhance_toggle = gr.Checkbox(label="Enable Opti-Scan Preprocessing", value=True)
173
+ run_btn = gr.Button("INITIALIZE VERIFICATION", variant="primary", elem_classes="download-btn")
174
+
175
+ gr.Markdown("#### 🔍 Preprocessing Preview")
176
+ preview_output = gr.Image(label="Enhanced Signal", interactive=False, elem_classes="preview-img")
177
+
178
+ # --- CENTER STAGE: Canvas ---
179
+ with gr.Column(scale=2):
180
+ with gr.Tabs():
181
+ with gr.TabItem("Solver Visualization"):
182
+ gr.Markdown("### 🎨 MVM² Verification Canvas")
183
+ with gr.Group(elem_classes="glass-card"):
184
+ canvas_latex = gr.Textbox(label="Canonical LaTeX Transcription", lines=2, interactive=False, elem_classes="monospace")
185
+ calib_bar_html = gr.HTML()
186
+
187
+ gr.Markdown("### 🪜 Dynamic Reasoning Trace")
188
+ trace_html = gr.HTML()
189
+
190
+ with gr.TabItem("How It Works (Architecture Flow)"):
191
+ gr.Markdown("### 🚀 Real-Time Pipeline Visualization")
192
+ flow_view = gr.HTML(generate_flow_html("idle"))
193
+ gr.Markdown(
194
+ """
195
+ **Pipeline Phases:**
196
+ 1. **Enhance:** CLAHE & Gaussian Blur noise reduction.
197
+ 2. **OCR:** Pix2Text LaTeX structure reconstruction.
198
+ 3. **Reasoning:** Quad-agent parallel logic processing.
199
+ 4. **Verification:** SymPy deterministic symbolic check.
200
+ 5. **Consensus:** Multi-signal weighted confidence fusion.
201
+ """
202
+ )
203
+
204
+ # --- RIGHT PANEL: Signal Intel ---
205
+ with gr.Column(scale=1, variant="panel"):
206
+ gr.Markdown("### ⚡ Signal Intelligence")
207
+ with gr.Group(elem_classes="glass-card"):
208
+ signal_gauges = gr.HTML()
209
+
210
+ gr.Markdown("### 📄 Educational Assessment")
211
+ download_btn = gr.File(label="Download Diagnostic PDF", elem_classes="download-btn")
212
+
213
+ with gr.Group(elem_classes="glass-card status-box"):
214
+ gr.Markdown(
215
+ """
216
+ **System Status**
217
+ - Pix2Text VLM: `Online`
218
+ - SymPy Core: `1.12.0`
219
+ - Consensus: `4-Agent parallel`
220
+ """
221
+ )
222
+
223
+ run_btn.click(
224
+ fn=process_mvm2_pipeline,
225
+ inputs=[input_img, enhance_toggle],
226
+ outputs=[preview_output, canvas_latex, signal_gauges, calib_bar_html, trace_html, download_btn, flow_view]
227
+ )
228
+
229
+ if __name__ == "__main__":
230
+ demo.launch()