Spaces:
Running
Running
| """Policy definition tab UI components.""" | |
| import os | |
| import sys | |
| import gradio as gr | |
| sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
| from utils.helpers import load_policy_from_file, load_preset_policy | |
| def build_policy_tab(base_dir: str) -> dict: | |
| """Build the policy definition tab UI.""" | |
| with gr.Tab("📋 Policy Definition"): | |
| current_policy_state = gr.State(value="") | |
| uploaded_policies_state = gr.State(value={}) # Store uploaded policies: {"Uploaded - filename": content} | |
| # Existing Policy Accordion | |
| with gr.Accordion("📥 Load Existing Policy", open=False): | |
| with gr.Row(): | |
| with gr.Column(): | |
| preset_dropdown = gr.Dropdown( | |
| label="Select Preset", | |
| choices=["Hate Speech Policy", "Violence Policy", "Toxicity Policy"], | |
| value=None | |
| ) | |
| load_preset_btn = gr.Button("Load Preset") | |
| credit_markdown = gr.Markdown("**Credit:** The example policies were taken from the [Zentropi website](https://zentropi.ai/labelers).") | |
| with gr.Column(): | |
| gr.Markdown("Upload a markdown file:") | |
| upload_file = gr.File(label="Upload Markdown File", file_types=[".md"]) | |
| # Manual Edition Accordion | |
| with gr.Accordion("✏️ Manual Editing", open=False): | |
| manual_text = gr.Textbox( | |
| label="Policy Text", | |
| placeholder="Enter or edit policy markdown...", | |
| lines=20 | |
| ) | |
| policy_preview = gr.Markdown(value="*No policy loaded*") | |
| # Clear button | |
| clear_policy_btn = gr.Button("Clear Policy", variant="secondary") | |
| # Handlers | |
| def load_preset_handler(name, uploaded_policies): | |
| """Load policy from preset or uploaded policies.""" | |
| if not name: | |
| return "", "*No policy loaded*", "" | |
| # Check presets first | |
| preset_choices = ["Hate Speech Policy", "Violence Policy", "Toxicity Policy"] | |
| if name in preset_choices: | |
| policy_text, _ = load_preset_policy(name, base_dir) | |
| return policy_text, policy_text, policy_text | |
| # Check uploaded policies | |
| if name in uploaded_policies: | |
| policy_text = uploaded_policies[name] | |
| return policy_text, policy_text, policy_text | |
| return "", "*No policy loaded*", "" | |
| load_preset_btn.click( | |
| load_preset_handler, | |
| inputs=[preset_dropdown, uploaded_policies_state], | |
| outputs=[current_policy_state, manual_text, policy_preview], | |
| ) | |
| def load_upload_handler(f, uploaded_policies): | |
| """Handle file upload: load policy, store it, and update dropdown.""" | |
| if not f: | |
| return "", "", "*No policy loaded*", gr.update(), {} | |
| # Extract filename | |
| filename = os.path.basename(f.name) | |
| upload_key = f"Uploaded - {filename}" | |
| # Load policy content | |
| policy_text, _ = load_policy_from_file(f.name) | |
| # Ensure uploaded_policies is a dict (handle case where it might be None) | |
| if uploaded_policies is None: | |
| uploaded_policies = {} | |
| # Check for duplicate BEFORE storing | |
| is_duplicate = upload_key in uploaded_policies | |
| # Store policy in state (overwrites if duplicate) | |
| uploaded_policies[upload_key] = policy_text | |
| # Build updated choices: presets + uploaded policies | |
| preset_choices = ["Hate Speech Policy", "Violence Policy", "Toxicity Policy"] | |
| all_choices = preset_choices + sorted(uploaded_policies.keys()) | |
| # Show warning if duplicate (gr.Warning is a function, not an exception) | |
| if is_duplicate: | |
| gr.Warning(f"Policy '{filename}' already uploaded. Previous version overwritten.") | |
| return ( | |
| policy_text, # current_policy_state | |
| policy_text, # manual_text | |
| policy_text, # policy_preview | |
| gr.update(choices=all_choices), # preset_dropdown | |
| uploaded_policies # uploaded_policies_state | |
| ) | |
| upload_file.change( | |
| load_upload_handler, | |
| inputs=[upload_file, uploaded_policies_state], | |
| outputs=[current_policy_state, manual_text, policy_preview, preset_dropdown, uploaded_policies_state], | |
| ) | |
| def update_preview(text): | |
| return text if text else "*No policy loaded*" | |
| # Update state and preview when user leaves the textbox (blur event) | |
| manual_text.blur( | |
| lambda t: (t, update_preview(t)), | |
| inputs=manual_text, | |
| outputs=[current_policy_state, policy_preview], | |
| ) | |
| clear_policy_btn.click( | |
| lambda: ("", "", "*No policy loaded*"), | |
| outputs=[current_policy_state, manual_text, policy_preview], | |
| ) | |
| # Sync UI components when state changes externally (e.g., from dataset load) | |
| def sync_policy_ui(policy_text): | |
| preview_text = policy_text if policy_text else "*No policy loaded*" | |
| return policy_text, preview_text | |
| current_policy_state.change( | |
| sync_policy_ui, | |
| inputs=current_policy_state, | |
| outputs=[manual_text, policy_preview], | |
| ) | |
| return { | |
| "current_policy_state": current_policy_state, | |
| } | |