Update app.py
Browse files
app.py
CHANGED
@@ -228,31 +228,155 @@ def download_snag_report(chat_history):
|
|
228 |
|
229 |
return temp_file_path
|
230 |
|
231 |
-
# Custom CSS for improved styling
|
232 |
custom_css = """
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
color: #
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
}
|
247 |
-
.image-container { border: 2px dashed #3498db; border-radius: 10px; padding: 1rem; text-align: center; margin-bottom: 1rem; }
|
248 |
-
.analyze-button { background-color: #2ecc71 !important; color: white !important; width: 100%; }
|
249 |
-
.clear-button { background-color: #e74c3c !important; color: white !important; width: 100px !important; }
|
250 |
-
.chatbot { border: 1px solid #bdc3c7; border-radius: 10px; padding: 1rem; height: 500px; overflow-y: auto; }
|
251 |
-
.chat-input { border: 1px solid #bdc3c7; border-radius: 5px; padding: 0.5rem; width: 100%; }
|
252 |
-
.groq-badge { position: fixed; bottom: 10px; right: 10px; background-color: #f39c12; color: white; padding: 5px 10px; border-radius: 5px; font-weight: bold; }
|
253 |
-
.chat-container { display: flex; flex-direction: column; height: 100%; }
|
254 |
-
.input-row { display: flex; align-items: center; margin-top: 10px; justify-content: space-between; }
|
255 |
-
.input-row > div:first-child { flex-grow: 1; margin-right: 10px; }
|
256 |
"""
|
257 |
|
258 |
# Create the Gradio interface
|
@@ -261,31 +385,54 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as iface:
|
|
261 |
"""
|
262 |
<div class="container">
|
263 |
<div class="header">
|
264 |
-
<h1
|
|
|
265 |
</div>
|
266 |
-
<p class="subheader">Enhance quality control and project management with AI-powered snag detection using Llama 3.2 90B Vision and expert chat assistance.</p>
|
267 |
-
</div>
|
268 |
"""
|
269 |
)
|
270 |
|
271 |
with gr.Row():
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
281 |
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
|
290 |
with gr.Row():
|
291 |
msg = gr.Textbox(
|
@@ -301,6 +448,27 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as iface:
|
|
301 |
|
302 |
report_file = gr.File(label="Download Snag Detection Report")
|
303 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
304 |
def process_files(files):
|
305 |
results = []
|
306 |
for file in files:
|
@@ -311,7 +479,7 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as iface:
|
|
311 |
def update_chat(history, new_messages):
|
312 |
history = history or []
|
313 |
for title, content in new_messages:
|
314 |
-
history.append((None, f"{title}\n\n{content}"))
|
315 |
return history
|
316 |
|
317 |
analyze_button.click(
|
@@ -330,12 +498,6 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as iface:
|
|
330 |
outputs=[report_file]
|
331 |
)
|
332 |
|
333 |
-
gr.HTML(
|
334 |
-
"""
|
335 |
-
<div class="groq-badge">Powered by Groq</div>
|
336 |
-
"""
|
337 |
-
)
|
338 |
-
|
339 |
# Launch the app
|
340 |
if __name__ == "__main__":
|
341 |
try:
|
|
|
228 |
|
229 |
return temp_file_path
|
230 |
|
|
|
231 |
custom_css = """
|
232 |
+
:root {
|
233 |
+
--primary-color: #FF6B35;
|
234 |
+
--secondary-color: #004E89;
|
235 |
+
--background-color: #F0F4F8;
|
236 |
+
--text-color: #333333;
|
237 |
+
--border-color: #CCCCCC;
|
238 |
+
}
|
239 |
+
|
240 |
+
body {
|
241 |
+
font-family: 'Arial', sans-serif;
|
242 |
+
background-color: var(--background-color);
|
243 |
+
color: var(--text-color);
|
244 |
+
}
|
245 |
+
|
246 |
+
.container {
|
247 |
+
max-width: 1200px;
|
248 |
+
margin: auto;
|
249 |
+
padding: 2rem;
|
250 |
+
background-color: white;
|
251 |
+
border-radius: 10px;
|
252 |
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
253 |
+
}
|
254 |
+
|
255 |
+
.header {
|
256 |
+
text-align: center;
|
257 |
+
margin-bottom: 2rem;
|
258 |
+
padding-bottom: 1rem;
|
259 |
+
border-bottom: 2px solid var(--primary-color);
|
260 |
+
}
|
261 |
+
|
262 |
+
.header h1 {
|
263 |
+
color: var(--secondary-color);
|
264 |
+
font-size: 2.5rem;
|
265 |
+
margin-bottom: 0.5rem;
|
266 |
+
}
|
267 |
+
|
268 |
+
.subheader {
|
269 |
+
color: var(--text-color);
|
270 |
+
font-size: 1.1rem;
|
271 |
+
line-height: 1.4;
|
272 |
+
margin-bottom: 1.5rem;
|
273 |
+
text-align: center;
|
274 |
+
}
|
275 |
+
|
276 |
+
.file-upload-container {
|
277 |
+
border: 2px dashed var(--primary-color);
|
278 |
+
border-radius: 10px;
|
279 |
+
padding: 2rem;
|
280 |
+
text-align: center;
|
281 |
+
margin-bottom: 1.5rem;
|
282 |
+
background-color: #FFF5E6;
|
283 |
+
}
|
284 |
+
|
285 |
+
.analyze-button {
|
286 |
+
background-color: var(--primary-color) !important;
|
287 |
+
color: white !important;
|
288 |
+
font-size: 1.1rem !important;
|
289 |
+
padding: 0.75rem 1.5rem !important;
|
290 |
+
border-radius: 5px !important;
|
291 |
+
width: 100%;
|
292 |
+
transition: background-color 0.3s ease;
|
293 |
+
}
|
294 |
+
|
295 |
+
.analyze-button:hover {
|
296 |
+
background-color: #E85A2A !important;
|
297 |
+
}
|
298 |
+
|
299 |
+
.clear-button, .download-button {
|
300 |
+
background-color: var(--secondary-color) !important;
|
301 |
+
color: white !important;
|
302 |
+
font-size: 1rem !important;
|
303 |
+
padding: 0.5rem 1rem !important;
|
304 |
+
border-radius: 5px !important;
|
305 |
+
transition: background-color 0.3s ease;
|
306 |
+
}
|
307 |
+
|
308 |
+
.clear-button:hover, .download-button:hover {
|
309 |
+
background-color: #003D6E !important;
|
310 |
+
}
|
311 |
+
|
312 |
+
.chatbot {
|
313 |
+
border: 1px solid var(--border-color);
|
314 |
+
border-radius: 10px;
|
315 |
+
padding: 1rem;
|
316 |
+
height: 400px;
|
317 |
+
overflow-y: auto;
|
318 |
+
background-color: white;
|
319 |
+
}
|
320 |
+
|
321 |
+
.chat-input {
|
322 |
+
border: 1px solid var(--border-color);
|
323 |
+
border-radius: 5px;
|
324 |
+
padding: 0.75rem;
|
325 |
+
width: 100%;
|
326 |
+
font-size: 1rem;
|
327 |
+
}
|
328 |
+
|
329 |
+
.groq-badge {
|
330 |
+
position: fixed;
|
331 |
+
bottom: 10px;
|
332 |
+
right: 10px;
|
333 |
+
background-color: var(--secondary-color);
|
334 |
+
color: white;
|
335 |
+
padding: 5px 10px;
|
336 |
+
border-radius: 5px;
|
337 |
+
font-weight: bold;
|
338 |
+
font-size: 0.9rem;
|
339 |
+
}
|
340 |
+
|
341 |
+
.section-title {
|
342 |
+
color: var(--secondary-color);
|
343 |
+
font-size: 1.5rem;
|
344 |
+
margin-top: 2rem;
|
345 |
+
margin-bottom: 1rem;
|
346 |
+
border-bottom: 2px solid var(--primary-color);
|
347 |
+
padding-bottom: 0.5rem;
|
348 |
+
}
|
349 |
+
|
350 |
+
.info-box {
|
351 |
+
background-color: #E6F3FF;
|
352 |
+
border: 1px solid var(--secondary-color);
|
353 |
+
border-radius: 5px;
|
354 |
+
padding: 1rem;
|
355 |
+
margin-bottom: 1.5rem;
|
356 |
+
font-size: 0.9rem;
|
357 |
+
}
|
358 |
+
|
359 |
+
.info-box h4 {
|
360 |
+
color: var(--secondary-color);
|
361 |
+
margin-top: 0;
|
362 |
+
margin-bottom: 0.5rem;
|
363 |
+
}
|
364 |
+
|
365 |
+
.info-box ul {
|
366 |
+
margin: 0;
|
367 |
+
padding-left: 1.5rem;
|
368 |
+
}
|
369 |
+
|
370 |
+
.tag {
|
371 |
+
display: inline-block;
|
372 |
+
background-color: var(--primary-color);
|
373 |
+
color: white;
|
374 |
+
padding: 0.25rem 0.5rem;
|
375 |
+
border-radius: 3px;
|
376 |
+
font-size: 0.8rem;
|
377 |
+
margin-right: 0.5rem;
|
378 |
+
margin-bottom: 0.5rem;
|
379 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
380 |
"""
|
381 |
|
382 |
# Create the Gradio interface
|
|
|
385 |
"""
|
386 |
<div class="container">
|
387 |
<div class="header">
|
388 |
+
<h1>🏗️ Construction Site Snag Detector</h1>
|
389 |
+
<p class="subheader">Enhance quality control and project management with AI-powered snag detection. Upload images or videos of your construction site to identify defects, unfinished work, and quality issues.</p>
|
390 |
</div>
|
|
|
|
|
391 |
"""
|
392 |
)
|
393 |
|
394 |
with gr.Row():
|
395 |
+
with gr.Column(scale=2):
|
396 |
+
gr.HTML('<h3 class="section-title">Upload Files</h3>')
|
397 |
+
file_input = gr.File(
|
398 |
+
label="Upload Construction Site Images or Videos",
|
399 |
+
file_count="multiple",
|
400 |
+
type="filepath",
|
401 |
+
elem_classes="file-upload-container"
|
402 |
+
)
|
403 |
+
analyze_button = gr.Button("🔍 Detect Snags", elem_classes="analyze-button")
|
404 |
+
|
405 |
+
with gr.Column(scale=1):
|
406 |
+
gr.HTML(
|
407 |
+
"""
|
408 |
+
<div class="info-box">
|
409 |
+
<h4>Supported File Types:</h4>
|
410 |
+
<ul>
|
411 |
+
<li>Images: JPG, JPEG, PNG, BMP</li>
|
412 |
+
<li>Videos: MP4, AVI, MOV, WEBM</li>
|
413 |
+
</ul>
|
414 |
+
</div>
|
415 |
+
<div class="info-box">
|
416 |
+
<h4>Common Snags:</h4>
|
417 |
+
<div>
|
418 |
+
<span class="tag">Cracks</span>
|
419 |
+
<span class="tag">Leaks</span>
|
420 |
+
<span class="tag">Uneven Surfaces</span>
|
421 |
+
<span class="tag">Incomplete Work</span>
|
422 |
+
<span class="tag">Poor Finishes</span>
|
423 |
+
<span class="tag">Misalignments</span>
|
424 |
+
</div>
|
425 |
+
</div>
|
426 |
+
"""
|
427 |
+
)
|
428 |
|
429 |
+
gr.HTML('<h3 class="section-title">Snag Detection Results</h3>')
|
430 |
+
chatbot = gr.Chatbot(
|
431 |
+
label="Snag Detection Results and Expert Chat",
|
432 |
+
elem_classes="chatbot",
|
433 |
+
show_share_button=False,
|
434 |
+
show_copy_button=False
|
435 |
+
)
|
436 |
|
437 |
with gr.Row():
|
438 |
msg = gr.Textbox(
|
|
|
448 |
|
449 |
report_file = gr.File(label="Download Snag Detection Report")
|
450 |
|
451 |
+
gr.HTML(
|
452 |
+
"""
|
453 |
+
<div class="info-box">
|
454 |
+
<h4>How to use:</h4>
|
455 |
+
<ol>
|
456 |
+
<li>Upload images or videos of your construction site</li>
|
457 |
+
<li>Click "Detect Snags" to analyze the files</li>
|
458 |
+
<li>Review the detected snags in the chat area</li>
|
459 |
+
<li>Ask follow-up questions about the snags or request more information</li>
|
460 |
+
<li>Download a comprehensive report for your records</li>
|
461 |
+
</ol>
|
462 |
+
</div>
|
463 |
+
"""
|
464 |
+
)
|
465 |
+
|
466 |
+
gr.HTML(
|
467 |
+
"""
|
468 |
+
<div class="groq-badge">Powered by Groq</div>
|
469 |
+
"""
|
470 |
+
)
|
471 |
+
|
472 |
def process_files(files):
|
473 |
results = []
|
474 |
for file in files:
|
|
|
479 |
def update_chat(history, new_messages):
|
480 |
history = history or []
|
481 |
for title, content in new_messages:
|
482 |
+
history.append((None, f"File: {title}\n\n{content}"))
|
483 |
return history
|
484 |
|
485 |
analyze_button.click(
|
|
|
498 |
outputs=[report_file]
|
499 |
)
|
500 |
|
|
|
|
|
|
|
|
|
|
|
|
|
501 |
# Launch the app
|
502 |
if __name__ == "__main__":
|
503 |
try:
|