""" Ammu-1.0 FactCheck Classifier - Gradio Demo for Hugging Face Spaces Author: Kalyan KS (https://huggingface.co/kalyan-ks) """ import os import pandas as pd import gradio as gr import torch from transformers import pipeline # Support Hugging Face ZeroGPU Spaces with local fallback try: import spaces except ImportError: class spaces: @staticmethod def GPU(func): return func ############################################################ # Model Catalog & Pipeline Cache ############################################################ MODEL_OPTIONS = { "Ammu-1.0-Base (150M)": "kalyan-ks/Ammu-1.0-FactCheck-Need-base", "Ammu-1.0-Small (68M)": "kalyan-ks/Ammu-1.0-FactCheck-Need-small", "Ammu-1.0-Tiny (33M)": "kalyan-ks/Ammu-1.0-FactCheck-Need-tiny", "Ammu-1.0-Nano (17M)": "kalyan-ks/Ammu-1.0-FactCheck-Need-nano", } MODEL_URLS = { "Ammu-1.0-Base (150M)": "https://huggingface.co/kalyan-ks/Ammu-1.0-FactCheck-Need-base", "Ammu-1.0-Small (68M)": "https://huggingface.co/kalyan-ks/Ammu-1.0-FactCheck-Need-small", "Ammu-1.0-Tiny (33M)": "https://huggingface.co/kalyan-ks/Ammu-1.0-FactCheck-Need-tiny", "Ammu-1.0-Nano (17M)": "https://huggingface.co/kalyan-ks/Ammu-1.0-FactCheck-Need-nano", } MODEL_PERFORMANCE = { "Ammu-1.0-Base (150M)": "96.56% Macro-F1", "Ammu-1.0-Small (68M)": "96.13% Macro-F1", "Ammu-1.0-Tiny (33M)": "96.35% Macro-F1", "Ammu-1.0-Nano (17M)": "95.66% Macro-F1", } # In-memory pipeline cache to prevent reloading overhead MODELS = {} def get_factcheck_pipeline(model_name): if model_name not in MODELS: device = 0 if torch.cuda.is_available() else -1 MODELS[model_name] = pipeline( task="text-classification", model=model_name, device=device, top_k=None # Returns probabilities for all classes ) return MODELS[model_name] ############################################################ # Benchmark Examples ############################################################ EXAMPLES = { "Example 1 (Factual Question)": "India is the most populous country in the world. Do you agree?", "Example 2 (Complex Age Calculation)": "Assume that I was born 16 years 4 months 3 days exactly after Sachin Tendulkar was born. How old I am today?", "Example 3 (Short Age Query)": "I was born 16 years 4 months 3 days exactly after Sachin Tendulkar was born. My age?", "Example 4 (Input-Text Entity Extraction)": "Kalyan KS is from India. Extract named entities from the given sentence.", "Example 5 (Task Instruction with Input)": "Extract named entities: Kalyan KS is from India.", } ############################################################ # UI & Helper Functions ############################################################ def update_model_info(selected_model_key): url = MODEL_URLS[selected_model_key] model_id = MODEL_OPTIONS[selected_model_key] perf = MODEL_PERFORMANCE[selected_model_key] info = f""" - **Model:** [{model_id}]({url}) - **Architecture:** ModernBERT Encoder - **Parameters:** {selected_model_key.split('(')[-1].replace(')', '')} - **Task:** Fact-Check Need Classification (Single-Label) - **Classes:** `FACT_CHECK_NEEDED`, `NO_FACT_CHECK_NEEDED` - **Performance:** {perf} """ footer = f""" ### 🔗 Resources & Links - **Hugging Face Model:** [{model_id}]({url}) - **Creator:** [Kalyan KS](https://huggingface.co/kalyan-ks) - **License:** Apache 2.0 --- Built with ❤️ using **Gradio** and **Hugging Face Transformers**. """ return info, footer def update_stats(text): if not text: return "Characters: 0", "Approx. Tokens: 0" char_count = len(text) approx_tokens = int(len(text.split()) * 1.3) return f"Characters: {char_count}", f"Approx. Tokens: {approx_tokens}" def load_example_text(example_key): return EXAMPLES.get(example_key, "") def clear_inputs(): empty_df = pd.DataFrame(columns=["Class Label", "Probability", "Confidence Bar"]) return ( "", # input_text "Characters: 0", # char_caption "Approx. Tokens: 0", # token_caption "", # status_output "", # result_card_html empty_df, # prob_table "", # metric_prediction "", # metric_confidence "", # metric_routing ) @spaces.GPU def process_classification(input_text, selected_model_key): if not input_text or not input_text.strip(): empty_df = pd.DataFrame(columns=["Class Label", "Probability", "Confidence Bar"]) return ( "⚠️ Please enter a prompt to classify.", "", empty_df, "-", "-", "-", ) model_id = MODEL_OPTIONS[selected_model_key] classifier = get_factcheck_pipeline(model_id) # Run inference raw_results = classifier(input_text.strip()) if isinstance(raw_results, list) and len(raw_results) > 0 and isinstance(raw_results[0], list): scores_list = raw_results[0] elif isinstance(raw_results, list): scores_list = raw_results else: scores_list = [raw_results] scores_dict = {item["label"]: float(item["score"]) for item in scores_list} top_label = max(scores_dict, key=scores_dict.get) top_score = scores_dict[top_label] # Styling based on prediction if top_label == "FACT_CHECK_NEEDED": badge_bg = "#FFEBEE" badge_border = "#EF5350" badge_color = "#C62828" icon = "⚠️" action_title = "FACT CHECK NEEDED" routing_desc = "Route to Retrieval (RAG) / Search / Knowledge Base before generating response." routing_short = "Trigger RAG / Web Search" else: badge_bg = "#E8F5E9" badge_border = "#66BB6A" badge_color = "#2E7D32" icon = "✅" action_title = "NO FACT CHECK NEEDED" routing_desc = "Safe for direct LLM generation (Creative writing, code, math logic, or input-grounded task)." routing_short = "Direct LLM Generation" # HTML Result Card styled_html = f"""
{routing_desc}