import gradio as gr import json import time import traceback from validation import validate_json, validate_croissant, validate_records, generate_validation_report import requests def process_file(file): results = [] json_data = None # 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, None # 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, None # Check 3: Records validation records_valid, records_message = validate_records(json_data) results.append(("Records Generation Test", records_valid, records_message)) # Generate detailed report report = generate_validation_report(file.name, json_data, results) return results, report def create_ui(): with gr.Blocks(theme=gr.themes.Soft()) as app: gr.Markdown("# 🔎🥐 Croissant Validator for NeurIPS D&B") gr.Markdown(""" Upload your Croissant JSON-LD file or enter a URL 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 """) # Track the active tab for conditional UI updates active_tab = gr.State("upload") # Default to upload tab # Create a container for the entire input section with gr.Group(): # Input tabs with gr.Tabs() as tabs: with gr.TabItem("Upload File", id="upload_tab"): file_input = gr.File(label="Upload Croissant JSON-LD File", file_types=[".json", ".jsonld"]) validate_btn = gr.Button("Validate Uploaded File", variant="primary") with gr.TabItem("URL Input", id="url_tab"): url_input = gr.Textbox( label="Enter Croissant JSON-LD URL", placeholder="e.g. https://huggingface.co/api/datasets/facebook/natural_reasoning/croissant" ) fetch_btn = gr.Button("Fetch and Validate", variant="primary") # Change initial message to match upload tab upload_progress = gr.HTML( """
Ready for upload
""", visible=True) # Now create the validation results section in a separate group with gr.Group(): # Validation results validation_results = gr.HTML(visible=False) # Report button and options in an expandable group with gr.Group(visible=False) as report_group: gr.Markdown("### Validation Report") with gr.Row(): copy_btn = gr.Button("📋 Copy to Clipboard") download_btn = gr.Button("⬇️ Download as .md") report_text = gr.Textbox(visible=False) # Hidden textbox to store report content # Define CSS for the validation UI gr.HTML(""" """) # Update helper messages based on tab changes def on_tab_change(evt: gr.SelectData): tab_id = evt.value if tab_id == "Upload File": return "upload", """
Ready for upload
""", gr.update(visible=False) else: return "url", """
Enter a URL to fetch
""", gr.update(visible=False) def on_copy_click(report): return report def on_download_click(report, file_name): report_file = f"report_{file_name}.md" with open(report_file, "w") as f: f.write(report) return report_file def on_file_upload(file): if file is None: return [ """
Ready for upload
""", gr.update(visible=False), gr.update(visible=False), None ] return [ """
✅ File uploaded successfully
""", gr.update(visible=False), gr.update(visible=False), None ] def fetch_from_url(url): if not url: return """
Please enter a URL
""", gr.update(visible=False) try: # Fetch JSON from URL response = requests.get(url, timeout=10) response.raise_for_status() json_data = response.json() # Show success message progress_html = """
✅ JSON fetched successfully from URL
""" # Validate the fetched JSON results = [] results.append(("JSON Format Validation", True, "✅ The URL returned valid JSON.")) croissant_valid, croissant_message = validate_croissant(json_data) results.append(("Croissant Schema Validation", croissant_valid, croissant_message)) if not croissant_valid: return progress_html, build_results_html(results) records_valid, records_message = validate_records(json_data) results.append(("Records Generation Test", records_valid, records_message)) return progress_html, build_results_html(results) except requests.exceptions.RequestException as e: error_message = f"❌ Error fetching URL: {str(e)}" return f"""
{error_message}
""", gr.update(visible=False) except json.JSONDecodeError as e: error_message = f"❌ URL did not return valid JSON: {str(e)}" return f"""
{error_message}
""", gr.update(visible=False) except Exception as e: error_message = f"❌ Unexpected error: {str(e)}" return f"""
{error_message}
""", gr.update(visible=False) def build_results_html(results): # Build validation results HTML html = '
' for i, (test_name, passed, message) in enumerate(results): status_class = "status-success" if passed else "status-error" status_icon = "✓" if passed else "✗" html += f'''
{status_icon}
{test_name}
''' html += '
' return gr.update(value=html, visible=True) def on_validate(file): if file is None: return [ gr.update(visible=False), gr.update(visible=False), None ] # Process the file and get results results, report = process_file(file) # Only show report options if validation was successful report_visible = any(passed for passed, _, _ in results) return [ build_results_html(results), gr.update(visible=report_visible), report if report else None ] # Connect UI events to functions tabs.select(on_tab_change, None, [active_tab, upload_progress, validation_results]) file_input.change( on_file_upload, inputs=file_input, outputs=[upload_progress, validation_results, report_group, report_text] ) validate_btn.click( on_validate, inputs=file_input, outputs=[validation_results, report_group, report_text] ) copy_btn.click( on_copy_click, inputs=report_text, outputs=report_text # This triggers the copy ) download_btn.click( on_download_click, inputs=[report_text, file_input], outputs=gr.File() ) fetch_btn.click(fetch_from_url, inputs=url_input, outputs=[upload_progress, validation_results]) # Footer gr.HTML("""

Learn more about Croissant format.

""") return app if __name__ == "__main__": app = create_ui() app.launch()