Spaces:
Sleeping
Sleeping
| import os | |
| import json | |
| import gradio as gr | |
| import pandas as pd | |
| from python_request import process_wod_document | |
| from dummy import output_test | |
| # --- Authentication Function --- | |
| def authenticate_user(username, password): | |
| """ | |
| Simple authentication function. | |
| In production, you should use more secure methods like hashed passwords. | |
| """ | |
| return username == "demo" and password == os.environ["PASSWORD"] | |
| # --- Core Application Logic --- | |
| def analyze_wod(file_obj, wod_type): | |
| """ | |
| This function analyzes a Work Order Document using the remote API. | |
| Args: | |
| file_obj: The uploaded file object from Gradio. | |
| wod_type: The selected type of Work Order Document. | |
| Returns: | |
| A pandas DataFrame with the analysis results. | |
| """ | |
| # Check if user has selected a valid WOD type | |
| if wod_type == "-- WOD type --" or wod_type is None: | |
| # Show warning dialog and return empty DataFrame | |
| gr.Warning("Please select a WOD type first!") | |
| return "", pd.DataFrame() | |
| # Check if file is uploaded | |
| if file_obj is None: | |
| gr.Warning("Please upload a PDF file first!") | |
| return "", pd.DataFrame() | |
| print(f"Analyzing '{file_obj.name}' (Type: {wod_type})...") | |
| try: | |
| # In modern Gradio versions, file_obj is already a path string | |
| # We can use it directly or get the path from it | |
| if hasattr(file_obj, 'name') and os.path.isfile(file_obj.name): | |
| # file_obj has a .name attribute pointing to the temporary file | |
| temp_file_path = file_obj.name | |
| cleanup_needed = False | |
| else: | |
| # Fallback: assume file_obj is a path string | |
| temp_file_path = str(file_obj) | |
| cleanup_needed = False | |
| # Process the document using the API | |
| api_response = process_wod_document(temp_file_path, wod_type) | |
| # api_response = json.loads(output_test) | |
| # Clean up temporary file if we created one | |
| if cleanup_needed: | |
| os.unlink(temp_file_path) | |
| # Check if API call was successful | |
| if api_response.get("status") != "success": | |
| error_msg = api_response.get("message", "Unknown error occurred") | |
| gr.Error(f"API Error: {error_msg}") | |
| return "", pd.DataFrame() | |
| # Parse the API response | |
| results = api_response.get("results", {}) | |
| summary = results.get("summary", {}) | |
| # Convert API response to DataFrame format | |
| requirements = [] | |
| reasons = [] | |
| statuses = [] | |
| for requirement_name, details in summary.items(): | |
| requirements.append(requirement_name) | |
| reasons.append(details.get("reasoning", "")) | |
| # Convert true/false to PASS/FAIL | |
| status_bool = details.get("status", "false") | |
| if isinstance(status_bool, str): | |
| status = "PASS" if status_bool.lower() == "true" else "FAIL" | |
| else: | |
| status = "PASS" if status_bool else "FAIL" | |
| statuses.append(status) | |
| # Create DataFrame | |
| df = pd.DataFrame({ | |
| "Requirement": requirements, | |
| "Reason": reasons, | |
| "Status": statuses | |
| }) | |
| # Get prediction for display | |
| prediction = results.get("prediction", "Unknown") | |
| gr.Info(f"Analysis completed! Overall prediction: {prediction}") | |
| # Format prediction as centered H1 for display | |
| prediction_display = f"<h1 style='text-align: center; color: #1f77b4;'>{prediction}</h1>" if prediction != "Unknown" else "" | |
| return prediction_display, df | |
| except Exception as e: | |
| error_msg = f"Error processing document: {str(e)}" | |
| print(error_msg) | |
| gr.Error(error_msg) | |
| return "", pd.DataFrame() | |
| js_func = """ | |
| function refresh() { | |
| const url = new URL(window.location); | |
| if (url.searchParams.get('__theme') !== 'light') { | |
| url.searchParams.set('__theme', 'light'); | |
| window.location.href = url.href; | |
| } | |
| } | |
| """ | |
| # --- Gradio User Interface Definition --- | |
| # Using gr.Blocks() for a custom layout that matches the elegant design. | |
| with gr.Blocks( | |
| #theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky"), | |
| theme=gr.themes.Default(primary_hue="blue", secondary_hue="sky"), | |
| js=js_func, | |
| css=".gradio-container {max-width: 960px !important; margin: auto !important;}" | |
| ) as demo: | |
| # Main Title and Description | |
| gr.Markdown( | |
| """ | |
| # WOD Analyzer | |
| Upload a Work Order Document to automatically check for requirements. | |
| """ | |
| ) | |
| # Input Section | |
| with gr.Row(): | |
| # File Upload Component | |
| file_input = gr.File(label="Upload WOD PDF") | |
| # Dropdown for WOD Type | |
| type_input = gr.Dropdown( | |
| ["-- WOD type --", "REPLACEMENT", "THERMAL", "VISIT", "PREVENTIVE_MAINTENANCE", "INSTALLATION", "WITHDRAWAL"], | |
| label="Type", | |
| value="-- WOD type --", | |
| info="Select the type of work order." | |
| ) | |
| # Action Button | |
| analyze_btn = gr.Button("Analyze Document", variant="primary") | |
| # Results Section | |
| gr.Markdown("---") | |
| gr.Markdown("## Results") | |
| # Prediction display (centered H1) | |
| prediction_output = gr.Markdown(value="", visible=True) | |
| # DataFrame to display the output, with styling for the 'Status' column | |
| results_output = gr.DataFrame( | |
| headers=["Requirement", "Reason", "Status"], | |
| datatype=["str", "str", "str"], | |
| interactive=False, | |
| max_height=1250, | |
| column_widths=[30, 60, 10], | |
| wrap=True | |
| ) | |
| # Define the interaction: clicking the button calls the function | |
| analyze_btn.click( | |
| fn=analyze_wod, | |
| inputs=[file_input, type_input], | |
| outputs=[prediction_output, results_output] | |
| ) | |
| # --- Launch the Application with Authentication --- | |
| if __name__ == "__main__": | |
| # The launch() command creates a web server with authentication enabled | |
| # Users must provide the correct username and password to access the app | |
| # demo.launch(debug=True) | |
| demo.launch( | |
| auth=authenticate_user, # Enable authentication | |
| auth_message="Please enter your credentials to access the WOD Analyzer", | |
| share=True, | |
| ssr_mode=False, | |
| ) |