Spaces:
Running
Running
| import gradio as gr | |
| import json | |
| import time | |
| import traceback | |
| from validation import validate_json, validate_croissant, validate_records | |
| def process_file(file): | |
| results = [] | |
| # Check 1: JSON validation | |
| json_valid, json_message, json_data = validate_json(file.name) | |
| results.append(("JSON Format Validation", json_valid, json_message)) | |
| if not json_valid: | |
| return results | |
| # Check 2: Croissant validation | |
| croissant_valid, croissant_message = validate_croissant(json_data) | |
| results.append(("Croissant Schema Validation", croissant_valid, croissant_message)) | |
| if not croissant_valid: | |
| return results | |
| # Check 3: Records validation | |
| records_valid, records_message = validate_records(json_data) | |
| results.append(("Records Generation Test", records_valid, records_message)) | |
| return results | |
| def create_ui(): | |
| with gr.Blocks(theme=gr.themes.Soft()) as app: | |
| gr.Markdown("# Croissant JSON-LD Validator for NeurIPS") | |
| gr.Markdown(""" | |
| Upload your Croissant JSON-LD file to validate if it meets the requirements for NeurIPS submission. | |
| The validator will check: | |
| 1. If the file is valid JSON | |
| 2. If it passes Croissant schema validation | |
| 3. If records can be generated within a reasonable time | |
| """) | |
| with gr.Row(): | |
| file_input = gr.File(label="Upload Croissant JSON-LD File", file_types=[".json", ".jsonld"]) | |
| upload_progress = gr.HTML( | |
| """<div class="progress-container"> | |
| <div class="progress-status">Ready for upload</div> | |
| </div>""", visible=True) | |
| validate_btn = gr.Button("Validate", variant="primary") | |
| # Create containers for each validation step | |
| validation_results = gr.HTML(visible=False) | |
| # Define CSS for the validation UI | |
| gr.HTML(""" | |
| <style> | |
| .gradio-container { | |
| max-width: 800px; | |
| margin: 0 auto; | |
| } | |
| .validation-step { | |
| margin-bottom: 15px; | |
| border: 1px solid #e0e0e0; | |
| border-radius: 8px; | |
| overflow: hidden; | |
| } | |
| .step-header { | |
| padding: 10px 15px; | |
| background-color: #f5f5f5; | |
| display: flex; | |
| align-items: center; | |
| cursor: pointer; | |
| } | |
| .step-left { | |
| display: flex; | |
| align-items: center; | |
| flex-grow: 1; | |
| } | |
| .step-status { | |
| margin-right: 10px; | |
| width: 24px; | |
| height: 24px; | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-weight: bold; | |
| color: white !important; | |
| font-size: 16px; | |
| text-shadow: 0px 0px 1px rgba(0,0,0,0.5); | |
| } | |
| .arrow-indicator { | |
| margin-left: 10px; | |
| font-size: 16px; | |
| transition: transform 0.3s ease; | |
| } | |
| .arrow-down { | |
| transform: rotate(90deg); | |
| } | |
| .status-success { | |
| background-color: #4caf50; | |
| } | |
| .status-error { | |
| background-color: #f44336; | |
| } | |
| .status-waiting { | |
| background-color: #9e9e9e; | |
| } | |
| </style> | |
| """) | |
| def on_file_upload(file): | |
| if file is None: | |
| return """<div class="progress-container"> | |
| <div class="progress-status">Ready for upload</div> | |
| </div>""", gr.update(visible=False) | |
| return """<div class="progress-container"> | |
| <div class="progress-status">β File uploaded successfully</div> | |
| </div>""", gr.update(visible=False) | |
| def on_validate(file): | |
| if file is None: | |
| return gr.update(visible=False) | |
| # Process the file and get results | |
| results = process_file(file) | |
| # Build the HTML for validation results | |
| html = '<div class="validation-results">' | |
| for i, (test_name, passed, message) in enumerate(results): | |
| # Determine status class | |
| status_class = "status-success" if passed else "status-error" | |
| status_icon = "β" if passed else "β" | |
| # Use direct inline JavaScript manipulation instead of a function call | |
| html += f''' | |
| <div class="validation-step" id="step-{i}"> | |
| <div class="step-header" onclick=" | |
| var details = document.getElementById('details-{i}'); | |
| var arrow = document.getElementById('arrow-{i}'); | |
| if(details.style.display === 'none') {{ | |
| details.style.display = 'block'; | |
| arrow.classList.add('arrow-down'); | |
| }} else {{ | |
| details.style.display = 'none'; | |
| arrow.classList.remove('arrow-down'); | |
| }}"> | |
| <div class="step-left"> | |
| <div class="step-status {status_class}">{status_icon}</div> | |
| <div class="step-title">{test_name}</div> | |
| <div class="arrow-indicator" id="arrow-{i}">βΆ</div> | |
| </div> | |
| </div> | |
| <div class="step-details" id="details-{i}" style="display: none;"> | |
| {message} | |
| </div> | |
| </div> | |
| ''' | |
| html += '</div>' | |
| # No separate JavaScript function needed | |
| return gr.update(value=html, visible=True) | |
| file_input.change(on_file_upload, inputs=file_input, outputs=[upload_progress, validation_results]) | |
| validate_btn.click(on_validate, inputs=file_input, outputs=validation_results) | |
| gr.HTML(""" | |
| <div style="text-align: center; margin-top: 20px;"> | |
| <p>Based on the <a href="https://github.com/mlcommons/croissant" target="_blank">Croissant format</a> from MLCommons.</p> | |
| </div> | |
| """) | |
| return app | |
| if __name__ == "__main__": | |
| app = create_ui() | |
| app.launch() |