Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import json | |
| import re | |
| def summarize_text(text: str, max_sentences: int = 2) -> str: | |
| """Summarize text using extractive summarization (works on-device, no model needed). | |
| Use this tool when a user needs to summarize text, messages, emails, or articles. | |
| Optimized for mobile use cases: short inputs, concise outputs. | |
| Args: | |
| text: The text to summarize | |
| max_sentences: Maximum number of sentences in the summary (default 2) | |
| Returns: | |
| JSON string with the summary and stats | |
| """ | |
| if not text or len(text.strip()) < 10: | |
| return json.dumps({"error": "Text too short to summarize"}) | |
| # Split into sentences | |
| sentences = re.split(r'[.!?]+\s+', text.strip()) | |
| sentences = [s.strip() for s in sentences if len(s.strip()) > 5] | |
| if len(sentences) <= max_sentences: | |
| summary = ". ".join(sentences) + "." | |
| else: | |
| # Score sentences by word frequency (extractive summarization) | |
| words = re.findall(r'\w+', text.lower()) | |
| word_freq = {} | |
| for w in words: | |
| if len(w) > 2: | |
| word_freq[w] = word_freq.get(w, 0) + 1 | |
| # Score each sentence | |
| scored = [] | |
| for i, sent in enumerate(sentences): | |
| sent_words = re.findall(r'\w+', sent.lower()) | |
| score = sum(word_freq.get(w, 0) for w in sent_words) / (len(sent_words) + 1) | |
| # Boost first sentences (position bias) | |
| score *= (1.0 - i * 0.1) | |
| scored.append((score, i, sent)) | |
| # Take top sentences, maintain order | |
| scored.sort(key=lambda x: x[0], reverse=True) | |
| top = sorted(scored[:max_sentences], key=lambda x: x[1]) | |
| summary = ". ".join([s[2] for s in top]) + "." | |
| original_words = len(text.split()) | |
| summary_words = len(summary.split()) | |
| reduction = (1 - summary_words / original_words) * 100 if original_words > 0 else 0 | |
| return json.dumps({ | |
| "original_length_chars": len(text), | |
| "original_length_words": original_words, | |
| "summary": summary, | |
| "summary_length_chars": len(summary), | |
| "summary_length_words": summary_words, | |
| "compression_ratio": round(reduction, 1), | |
| "sentences_in_summary": max_sentences, | |
| }, indent=2) | |
| def classify_text(text: str) -> str: | |
| """Classify text as spam/not-spam and detect sentiment. | |
| Use this tool when a user needs to classify a message, email, or notification. | |
| Uses keyword-based heuristics that work on-device without a model. | |
| Args: | |
| text: The text to classify | |
| Returns: | |
| JSON string with classification results | |
| """ | |
| lower = text.lower() | |
| # Spam detection | |
| spam_keywords = ["winner", "congratulations", "click here", "claim now", "free", | |
| "urgent", "limited time", "act now", "cash prize", "gift card", | |
| "verify your account", "suspended", "lottery", "inheritance"] | |
| spam_score = sum(1 for kw in spam_keywords if kw in lower) | |
| is_spam = spam_score >= 2 | |
| # Sentiment | |
| positive_words = ["good", "great", "excellent", "amazing", "love", "happy", | |
| "best", "awesome", "fantastic", "wonderful", "perfect"] | |
| negative_words = ["bad", "terrible", "awful", "hate", "angry", "worst", | |
| "horrible", "disappointing", "frustrated", "broken"] | |
| pos_count = sum(1 for w in positive_words if w in lower) | |
| neg_count = sum(1 for w in negative_words if w in lower) | |
| if pos_count > neg_count: | |
| sentiment = "positive" | |
| elif neg_count > pos_count: | |
| sentiment = "negative" | |
| else: | |
| sentiment = "neutral" | |
| return json.dumps({ | |
| "text": text[:100] + "..." if len(text) > 100 else text, | |
| "is_spam": is_spam, | |
| "spam_confidence": min(spam_score / 3, 1.0), | |
| "sentiment": sentiment, | |
| "positive_signals": pos_count, | |
| "negative_signals": neg_count, | |
| }, indent=2) | |
| with gr.Blocks(title="dispatchAI Summarize MCP") as demo: | |
| gr.Markdown("## ๐ dispatchAI Summarize (MCP Tool)") | |
| with gr.Tab("Summarize"): | |
| s_input = gr.Textbox(label="Text to Summarize", lines=8, placeholder="Paste text here...") | |
| s_max = gr.Slider(1, 5, value=2, step=1, label="Max Sentences") | |
| s_btn = gr.Button("Summarize", variant="primary") | |
| s_out = gr.Textbox(label="Summary (JSON)", lines=10) | |
| s_btn.click(fn=summarize_text, inputs=[s_input, s_max], outputs=s_out) | |
| with gr.Tab("Classify"): | |
| c_input = gr.Textbox(label="Text to Classify", lines=5, placeholder="Paste message here...") | |
| c_btn = gr.Button("Classify", variant="primary") | |
| c_out = gr.Textbox(label="Classification (JSON)", lines=10) | |
| c_btn.click(fn=classify_text, inputs=c_input, outputs=c_out) | |
| demo.launch(mcp_server=True) | |