Update app.py
Browse files
app.py
CHANGED
@@ -246,7 +246,7 @@ body {
|
|
246 |
.container {
|
247 |
max-width: 1200px;
|
248 |
margin: auto;
|
249 |
-
padding:
|
250 |
background-color: white;
|
251 |
border-radius: 10px;
|
252 |
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
@@ -254,117 +254,146 @@ body {
|
|
254 |
|
255 |
.header {
|
256 |
text-align: center;
|
257 |
-
margin-bottom:
|
258 |
-
padding-bottom:
|
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.
|
266 |
}
|
267 |
|
268 |
.subheader {
|
269 |
color: var(--text-color);
|
270 |
-
font-size: 1rem;
|
271 |
-
line-height: 1.
|
272 |
-
margin-bottom:
|
|
|
273 |
}
|
274 |
|
275 |
-
.
|
276 |
-
|
277 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
}
|
279 |
|
280 |
-
.
|
281 |
-
|
282 |
}
|
283 |
|
284 |
-
.
|
285 |
-
|
|
|
|
|
|
|
|
|
|
|
286 |
}
|
287 |
|
288 |
-
.
|
289 |
-
|
|
|
|
|
|
|
|
|
290 |
border-radius: 10px;
|
291 |
padding: 1rem;
|
292 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
margin-bottom: 1rem;
|
294 |
-
|
|
|
295 |
}
|
296 |
|
297 |
.info-box {
|
298 |
background-color: #E6F3FF;
|
299 |
border: 1px solid var(--secondary-color);
|
300 |
border-radius: 5px;
|
301 |
-
padding:
|
302 |
-
margin-bottom:
|
303 |
font-size: 0.9rem;
|
304 |
}
|
305 |
|
306 |
.info-box h4 {
|
307 |
color: var(--secondary-color);
|
308 |
margin-top: 0;
|
309 |
-
margin-bottom: 0.
|
310 |
}
|
311 |
|
312 |
-
.info-box ul
|
313 |
margin: 0;
|
314 |
-
padding-left: 1.
|
315 |
}
|
316 |
|
317 |
.tag {
|
318 |
display: inline-block;
|
319 |
background-color: var(--primary-color);
|
320 |
color: white;
|
321 |
-
padding: 0.
|
322 |
border-radius: 3px;
|
323 |
font-size: 0.8rem;
|
324 |
-
margin-right: 0.
|
325 |
-
margin-bottom: 0.
|
326 |
-
}
|
327 |
-
|
328 |
-
.analyze-button {
|
329 |
-
background-color: var(--primary-color) !important;
|
330 |
-
color: white !important;
|
331 |
-
font-size: 1.1rem !important;
|
332 |
-
padding: 0.5rem 1rem !important;
|
333 |
-
border-radius: 5px !important;
|
334 |
-
width: 100%;
|
335 |
-
transition: background-color 0.3s ease;
|
336 |
-
}
|
337 |
-
|
338 |
-
.analyze-button:hover {
|
339 |
-
background-color: #E85A2A !important;
|
340 |
}
|
341 |
|
342 |
.footer {
|
343 |
-
margin-top:
|
344 |
-
padding-top:
|
345 |
border-top: 2px solid var(--primary-color);
|
346 |
display: flex;
|
347 |
-
justify-content:
|
348 |
align-items: center;
|
|
|
349 |
}
|
350 |
|
351 |
.groq-badge {
|
352 |
background-color: var(--secondary-color);
|
353 |
color: white;
|
354 |
-
padding:
|
355 |
border-radius: 5px;
|
356 |
font-weight: bold;
|
357 |
-
font-size:
|
358 |
display: inline-block;
|
359 |
-
margin-right: 0.5rem;
|
360 |
}
|
361 |
|
362 |
.model-info {
|
363 |
color: var(--text-color);
|
364 |
-
font-size: 0.
|
|
|
365 |
}
|
366 |
"""
|
367 |
|
|
|
368 |
with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as iface:
|
369 |
gr.HTML(
|
370 |
"""
|
@@ -376,35 +405,18 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as iface:
|
|
376 |
"""
|
377 |
)
|
378 |
|
379 |
-
with gr.Row(
|
380 |
-
with gr.Column(
|
381 |
-
gr.
|
382 |
file_input = gr.File(
|
383 |
label="Upload Construction Site Images or Videos",
|
384 |
file_count="multiple",
|
385 |
type="filepath",
|
386 |
elem_classes="file-upload-container"
|
387 |
)
|
388 |
-
|
389 |
-
with gr.Row():
|
390 |
-
gr.HTML(
|
391 |
-
"""
|
392 |
-
<div class="info-box">
|
393 |
-
<h4>How to use:</h4>
|
394 |
-
<ol>
|
395 |
-
<li>Upload images or videos of your construction site</li>
|
396 |
-
<li>Click "Detect Snags" to analyze the files</li>
|
397 |
-
<li>Review the detected snags in the chat area</li>
|
398 |
-
<li>Ask follow-up questions about the snags or request more information</li>
|
399 |
-
<li>Download a comprehensive report for your records</li>
|
400 |
-
</ol>
|
401 |
-
</div>
|
402 |
-
"""
|
403 |
-
)
|
404 |
-
|
405 |
analyze_button = gr.Button("🔍 Detect Snags", elem_classes="analyze-button")
|
406 |
|
407 |
-
with gr.Column(
|
408 |
gr.HTML(
|
409 |
"""
|
410 |
<div class="info-box">
|
@@ -427,26 +439,80 @@ with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as iface:
|
|
427 |
</div>
|
428 |
"""
|
429 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
430 |
|
431 |
gr.HTML(
|
432 |
"""
|
433 |
<div class="footer">
|
434 |
-
<div
|
435 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
436 |
</div>
|
437 |
"""
|
438 |
)
|
439 |
|
440 |
-
def
|
441 |
-
|
442 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
443 |
|
444 |
analyze_button.click(
|
445 |
-
|
446 |
inputs=[file_input],
|
447 |
-
outputs=[
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
448 |
)
|
449 |
|
|
|
450 |
if __name__ == "__main__":
|
451 |
try:
|
452 |
iface.launch(debug=True)
|
|
|
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);
|
|
|
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 |
+
.section-title {
|
330 |
+
color: var(--secondary-color);
|
331 |
+
font-size: 1.5rem;
|
332 |
+
margin-top: 2rem;
|
333 |
margin-bottom: 1rem;
|
334 |
+
border-bottom: 2px solid var(--primary-color);
|
335 |
+
padding-bottom: 0.5rem;
|
336 |
}
|
337 |
|
338 |
.info-box {
|
339 |
background-color: #E6F3FF;
|
340 |
border: 1px solid var(--secondary-color);
|
341 |
border-radius: 5px;
|
342 |
+
padding: 1rem;
|
343 |
+
margin-bottom: 1.5rem;
|
344 |
font-size: 0.9rem;
|
345 |
}
|
346 |
|
347 |
.info-box h4 {
|
348 |
color: var(--secondary-color);
|
349 |
margin-top: 0;
|
350 |
+
margin-bottom: 0.5rem;
|
351 |
}
|
352 |
|
353 |
+
.info-box ul {
|
354 |
margin: 0;
|
355 |
+
padding-left: 1.5rem;
|
356 |
}
|
357 |
|
358 |
.tag {
|
359 |
display: inline-block;
|
360 |
background-color: var(--primary-color);
|
361 |
color: white;
|
362 |
+
padding: 0.25rem 0.5rem;
|
363 |
border-radius: 3px;
|
364 |
font-size: 0.8rem;
|
365 |
+
margin-right: 0.5rem;
|
366 |
+
margin-bottom: 0.5rem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
367 |
}
|
368 |
|
369 |
.footer {
|
370 |
+
margin-top: 2rem;
|
371 |
+
padding-top: 1rem;
|
372 |
border-top: 2px solid var(--primary-color);
|
373 |
display: flex;
|
374 |
+
justify-content: space-between;
|
375 |
align-items: center;
|
376 |
+
flex-wrap: wrap;
|
377 |
}
|
378 |
|
379 |
.groq-badge {
|
380 |
background-color: var(--secondary-color);
|
381 |
color: white;
|
382 |
+
padding: 8px 15px;
|
383 |
border-radius: 5px;
|
384 |
font-weight: bold;
|
385 |
+
font-size: 1rem;
|
386 |
display: inline-block;
|
|
|
387 |
}
|
388 |
|
389 |
.model-info {
|
390 |
color: var(--text-color);
|
391 |
+
font-size: 0.9rem;
|
392 |
+
margin-top: 0.5rem;
|
393 |
}
|
394 |
"""
|
395 |
|
396 |
+
# Create the Gradio interface
|
397 |
with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as iface:
|
398 |
gr.HTML(
|
399 |
"""
|
|
|
405 |
"""
|
406 |
)
|
407 |
|
408 |
+
with gr.Row():
|
409 |
+
with gr.Column(scale=2):
|
410 |
+
gr.HTML('<h3 class="section-title">Upload Files</h3>')
|
411 |
file_input = gr.File(
|
412 |
label="Upload Construction Site Images or Videos",
|
413 |
file_count="multiple",
|
414 |
type="filepath",
|
415 |
elem_classes="file-upload-container"
|
416 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
417 |
analyze_button = gr.Button("🔍 Detect Snags", elem_classes="analyze-button")
|
418 |
|
419 |
+
with gr.Column(scale=1):
|
420 |
gr.HTML(
|
421 |
"""
|
422 |
<div class="info-box">
|
|
|
439 |
</div>
|
440 |
"""
|
441 |
)
|
442 |
+
|
443 |
+
gr.HTML('<h3 class="section-title">Snag Detection Results</h3>')
|
444 |
+
chatbot = gr.Chatbot(
|
445 |
+
label="Snag Detection Results and Expert Chat",
|
446 |
+
elem_classes="chatbot",
|
447 |
+
show_share_button=False,
|
448 |
+
show_copy_button=False
|
449 |
+
)
|
450 |
+
|
451 |
+
with gr.Row():
|
452 |
+
msg = gr.Textbox(
|
453 |
+
label="Ask about detected snags or quality issues",
|
454 |
+
placeholder="E.g., 'What are the most critical snags detected?'",
|
455 |
+
show_label=False,
|
456 |
+
elem_classes="chat-input"
|
457 |
+
)
|
458 |
+
|
459 |
+
with gr.Row():
|
460 |
+
clear = gr.Button("🗑️ Clear Chat", elem_classes="clear-button")
|
461 |
+
download_button = gr.Button("📥 Download Report", elem_classes="download-button")
|
462 |
+
|
463 |
+
report_file = gr.File(label="Download Snag Detection Report")
|
464 |
|
465 |
gr.HTML(
|
466 |
"""
|
467 |
<div class="footer">
|
468 |
+
<div>
|
469 |
+
<div class="groq-badge">Powered by Groq</div>
|
470 |
+
<div class="model-info">Model: llama-3.2-90b-vision-preview</div>
|
471 |
+
</div>
|
472 |
+
<div class="info-box" style="margin-bottom: 0;">
|
473 |
+
<h4>How to use:</h4>
|
474 |
+
<ol>
|
475 |
+
<li>Upload images or videos of your construction site</li>
|
476 |
+
<li>Click "Detect Snags" to analyze the files</li>
|
477 |
+
<li>Review the detected snags in the chat area</li>
|
478 |
+
<li>Ask follow-up questions about the snags or request more information</li>
|
479 |
+
<li>Download a comprehensive report for your records</li>
|
480 |
+
</ol>
|
481 |
+
</div>
|
482 |
</div>
|
483 |
"""
|
484 |
)
|
485 |
|
486 |
+
def process_files(files):
|
487 |
+
results = []
|
488 |
+
for file in files:
|
489 |
+
result = detect_snags(file)
|
490 |
+
results.append((file.name, result))
|
491 |
+
return results
|
492 |
+
|
493 |
+
def update_chat(history, new_messages):
|
494 |
+
history = history or []
|
495 |
+
for title, content in new_messages:
|
496 |
+
history.append((None, f"File: {title}\n\n{content}"))
|
497 |
+
return history
|
498 |
|
499 |
analyze_button.click(
|
500 |
+
process_files,
|
501 |
inputs=[file_input],
|
502 |
+
outputs=[chatbot],
|
503 |
+
postprocess=lambda x: update_chat(chatbot.value, x)
|
504 |
+
)
|
505 |
+
|
506 |
+
msg.submit(chat_about_snags, [msg, chatbot], [msg, chatbot])
|
507 |
+
clear.click(lambda: None, None, chatbot, queue=False)
|
508 |
+
|
509 |
+
download_button.click(
|
510 |
+
download_snag_report,
|
511 |
+
inputs=[chatbot],
|
512 |
+
outputs=[report_file]
|
513 |
)
|
514 |
|
515 |
+
# Launch the app
|
516 |
if __name__ == "__main__":
|
517 |
try:
|
518 |
iface.launch(debug=True)
|