Spaces:
Sleeping
Sleeping
| """ | |
| Advanced AI Text Detector - 4-Category Classification | |
| Enhanced accuracy with nuanced detection categories for Hugging Face Spaces | |
| Renamed to app.py for Hugging Face Spaces deployment | |
| """ | |
| import gradio as gr | |
| import torch | |
| import numpy as np | |
| import re | |
| import time | |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification | |
| from typing import Dict, List, Tuple | |
| import statistics | |
| import string | |
| from collections import Counter | |
| class ImprovedAIDetector: | |
| """ | |
| Enhanced AI text detector with 4-category classification and improved accuracy | |
| """ | |
| def __init__(self): | |
| self.tokenizer = None | |
| self.model = None | |
| self.load_models() | |
| def load_models(self): | |
| """Load and cache detection models""" | |
| try: | |
| model_name = "roberta-base-openai-detector" | |
| self.tokenizer = AutoTokenizer.from_pretrained(model_name) | |
| self.model = AutoModelForSequenceClassification.from_pretrained(model_name) | |
| print("β Models loaded successfully") | |
| except Exception as e: | |
| print(f"β οΈ Model loading failed: {e}") | |
| self.tokenizer = None | |
| self.model = None | |
| def extract_linguistic_features(self, text: str) -> Dict[str, float]: | |
| """ | |
| Extract comprehensive linguistic features for detection | |
| """ | |
| if len(text.strip()) < 10: | |
| return {} | |
| sentences = re.split(r'[.!?]+', text) | |
| sentences = [s.strip() for s in sentences if s.strip()] | |
| words = text.split() | |
| if not sentences or not words: | |
| return {} | |
| features = {} | |
| # Length-based features | |
| features['avg_sentence_length'] = np.mean([len(s.split()) for s in sentences]) | |
| features['avg_word_length'] = np.mean([len(word) for word in words]) | |
| features['total_words'] = len(words) | |
| # Vocabulary diversity | |
| unique_words = len(set(word.lower() for word in words)) | |
| features['lexical_diversity'] = unique_words / len(words) if words else 0 | |
| # Punctuation patterns | |
| punct_count = sum(1 for char in text if char in string.punctuation) | |
| features['punctuation_ratio'] = punct_count / len(text) if text else 0 | |
| # Sentence structure | |
| features['sentence_count'] = len(sentences) | |
| if len(sentences) > 1: | |
| sentence_lengths = [len(s.split()) for s in sentences] | |
| features['sentence_length_variance'] = np.var(sentence_lengths) | |
| else: | |
| features['sentence_length_variance'] = 0 | |
| # Word frequency patterns | |
| word_freq = Counter(word.lower() for word in words) | |
| most_common_freq = word_freq.most_common(1)[0][1] if word_freq else 1 | |
| features['max_word_frequency'] = most_common_freq / len(words) | |
| # Function words (common in AI text) | |
| function_words = {'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'by'} | |
| function_word_count = sum(1 for word in words if word.lower() in function_words) | |
| features['function_word_ratio'] = function_word_count / len(words) if words else 0 | |
| # AI-specific patterns | |
| ai_indicators = ['furthermore', 'moreover', 'additionally', 'consequently', 'therefore', 'thus', 'hence'] | |
| ai_indicator_count = sum(1 for word in words if word.lower() in ai_indicators) | |
| features['ai_indicator_ratio'] = ai_indicator_count / len(words) if words else 0 | |
| # Repetition patterns (AI tends to be more repetitive) | |
| bigrams = [(words[i].lower(), words[i+1].lower()) for i in range(len(words)-1)] | |
| unique_bigrams = len(set(bigrams)) | |
| features['bigram_diversity'] = unique_bigrams / len(bigrams) if bigrams else 0 | |
| return features | |
| def calculate_perplexity_score(self, text: str) -> float: | |
| """ | |
| Calculate a simplified perplexity-like score | |
| """ | |
| if not self.model or not self.tokenizer: | |
| # Fallback heuristic | |
| words = text.split() | |
| if len(words) < 5: | |
| return 0.5 | |
| # Simple heuristic: longer, more complex sentences = higher perplexity | |
| avg_word_length = np.mean([len(word) for word in words]) | |
| sentence_count = len(re.split(r'[.!?]+', text)) | |
| complexity_score = (avg_word_length * sentence_count) / len(words) | |
| return min(max(complexity_score, 0.1), 0.9) | |
| try: | |
| inputs = self.tokenizer(text, return_tensors="pt", truncation=True, max_length=512) | |
| with torch.no_grad(): | |
| outputs = self.model(**inputs) | |
| # Use model confidence as perplexity proxy | |
| probs = torch.softmax(outputs.logits, dim=-1) | |
| confidence = torch.max(probs).item() | |
| # Invert confidence to get perplexity-like score | |
| return 1.0 - confidence | |
| except: | |
| return 0.5 | |
| def detect_refinement_patterns(self, text: str, linguistic_features: Dict) -> Dict[str, float]: | |
| """ | |
| Detect patterns indicating AI refinement/editing | |
| """ | |
| refinement_indicators = {} | |
| # Perfect grammar/structure indicators (suggests AI refinement) | |
| sentences = re.split(r'[.!?]+', text) | |
| sentences = [s.strip() for s in sentences if s.strip()] | |
| # Check for overly consistent sentence structure | |
| if len(sentences) > 2: | |
| lengths = [len(s.split()) for s in sentences] | |
| length_consistency = 1.0 - (np.std(lengths) / np.mean(lengths)) if np.mean(lengths) > 0 else 0 | |
| refinement_indicators['structure_consistency'] = min(length_consistency, 1.0) | |
| else: | |
| refinement_indicators['structure_consistency'] = 0.5 | |
| # Check for formal language patterns | |
| formal_words = ['furthermore', 'moreover', 'consequently', 'therefore', 'additionally', 'subsequently'] | |
| formal_count = sum(1 for word in text.lower().split() if word in formal_words) | |
| refinement_indicators['formality_score'] = min(formal_count / len(text.split()) * 10, 1.0) | |
| # Check for lack of contractions (AI refinement often removes contractions) | |
| contractions = ["n't", "'ll", "'re", "'ve", "'m", "'d", "'s"] | |
| contraction_count = sum(1 for word in text.split() if any(cont in word for cont in contractions)) | |
| words_count = len(text.split()) | |
| refinement_indicators['contraction_absence'] = 1.0 - min(contraction_count / words_count * 5, 1.0) if words_count > 0 else 0.5 | |
| # Check for overly perfect punctuation | |
| punct_perfect_score = 0.5 | |
| if ',' in text and '.' in text: | |
| # Simple heuristic for punctuation correctness | |
| comma_count = text.count(',') | |
| period_count = text.count('.') | |
| if comma_count > 0 and period_count > 0: | |
| punct_ratio = comma_count / (comma_count + period_count) | |
| # Refined text often has more balanced punctuation | |
| if 0.3 <= punct_ratio <= 0.7: | |
| punct_perfect_score = 0.8 | |
| refinement_indicators['punctuation_perfection'] = punct_perfect_score | |
| return refinement_indicators | |
| def classify_text_category(self, text: str) -> Tuple[str, Dict[str, float], float]: | |
| """ | |
| Classify text into 4 categories with confidence scores | |
| """ | |
| if len(text.strip()) < 10: | |
| return "Uncertain", {"ai_generated": 0.25, "ai_refined": 0.25, "human_ai_refined": 0.25, "human_written": 0.25}, 0.3 | |
| # Extract features | |
| linguistic_features = self.extract_linguistic_features(text) | |
| refinement_patterns = self.detect_refinement_patterns(text, linguistic_features) | |
| perplexity_score = self.calculate_perplexity_score(text) | |
| # Get transformer model prediction if available | |
| transformer_ai_prob = 0.5 | |
| if self.model and self.tokenizer: | |
| try: | |
| inputs = self.tokenizer(text, return_tensors="pt", truncation=True, max_length=512) | |
| with torch.no_grad(): | |
| outputs = self.model(**inputs) | |
| probs = torch.softmax(outputs.logits, dim=-1) | |
| transformer_ai_prob = probs[0][1].item() # AI probability | |
| except: | |
| pass | |
| # Calculate category probabilities using ensemble approach | |
| scores = {} | |
| # AI-generated score | |
| ai_generated_score = 0.0 | |
| if linguistic_features: | |
| # AI tends to have: consistent sentence length, formal language, lower lexical diversity | |
| ai_generated_score = ( | |
| transformer_ai_prob * 0.4 + | |
| (1.0 - linguistic_features.get('lexical_diversity', 0.5)) * 0.2 + | |
| linguistic_features.get('ai_indicator_ratio', 0) * 0.15 + | |
| (1.0 - linguistic_features.get('sentence_length_variance', 0.5) / 10) * 0.15 + | |
| (1.0 - perplexity_score) * 0.1 | |
| ) | |
| else: | |
| ai_generated_score = transformer_ai_prob | |
| scores['ai_generated'] = min(max(ai_generated_score, 0.0), 1.0) | |
| # AI-generated & AI-refined score | |
| ai_refined_score = 0.0 | |
| if refinement_patterns: | |
| ai_refined_score = ( | |
| transformer_ai_prob * 0.3 + | |
| refinement_patterns.get('structure_consistency', 0) * 0.25 + | |
| refinement_patterns.get('formality_score', 0) * 0.25 + | |
| refinement_patterns.get('punctuation_perfection', 0) * 0.2 | |
| ) | |
| else: | |
| ai_refined_score = transformer_ai_prob * 0.7 | |
| scores['ai_refined'] = min(max(ai_refined_score, 0.0), 1.0) | |
| # Human-written & AI-refined score | |
| human_ai_refined_score = 0.0 | |
| if linguistic_features and refinement_patterns: | |
| human_ai_refined_score = ( | |
| (1.0 - transformer_ai_prob) * 0.3 + | |
| linguistic_features.get('lexical_diversity', 0.5) * 0.2 + | |
| refinement_patterns.get('structure_consistency', 0) * 0.2 + | |
| refinement_patterns.get('contraction_absence', 0) * 0.15 + | |
| refinement_patterns.get('formality_score', 0) * 0.15 | |
| ) | |
| else: | |
| human_ai_refined_score = (1.0 - transformer_ai_prob) * 0.6 | |
| scores['human_ai_refined'] = min(max(human_ai_refined_score, 0.0), 1.0) | |
| # Human-written score | |
| human_written_score = 0.0 | |
| if linguistic_features: | |
| human_written_score = ( | |
| (1.0 - transformer_ai_prob) * 0.4 + | |
| linguistic_features.get('lexical_diversity', 0.5) * 0.2 + | |
| linguistic_features.get('sentence_length_variance', 0.5) / 10 * 0.15 + | |
| (1.0 - refinement_patterns.get('structure_consistency', 0.5)) * 0.15 + | |
| perplexity_score * 0.1 | |
| ) | |
| else: | |
| human_written_score = 1.0 - transformer_ai_prob | |
| scores['human_written'] = min(max(human_written_score, 0.0), 1.0) | |
| # Normalize scores to sum to 1 | |
| total_score = sum(scores.values()) | |
| if total_score > 0: | |
| scores = {k: v / total_score for k, v in scores.items()} | |
| else: | |
| scores = {"ai_generated": 0.25, "ai_refined": 0.25, "human_ai_refined": 0.25, "human_written": 0.25} | |
| # Determine primary category | |
| primary_category = max(scores, key=scores.get) | |
| confidence = scores[primary_category] | |
| # Map to readable names | |
| category_names = { | |
| 'ai_generated': 'AI-generated', | |
| 'ai_refined': 'AI-generated & AI-refined', | |
| 'human_ai_refined': 'Human-written & AI-refined', | |
| 'human_written': 'Human-written' | |
| } | |
| return category_names[primary_category], scores, confidence | |
| # Initialize detector | |
| detector = ImprovedAIDetector() | |
| def analyze_text(text): | |
| """ | |
| Main analysis function for Gradio interface | |
| """ | |
| if not text or len(text.strip()) < 10: | |
| return ( | |
| "β οΈ Please provide at least 10 characters of text for accurate analysis.", | |
| 0.0, 0.0, 0.0, 0.0, # Four category scores | |
| 0.0, 0.0, # AI and Human probabilities | |
| 0.0, # Confidence | |
| "N/A" # Processing time | |
| ) | |
| start_time = time.time() | |
| try: | |
| # Get detailed classification | |
| primary_category, category_scores, confidence = detector.classify_text_category(text) | |
| # Calculate traditional AI/Human probabilities | |
| ai_probability = category_scores['ai_generated'] + category_scores['ai_refined'] | |
| human_probability = category_scores['human_ai_refined'] + category_scores['human_written'] | |
| processing_time = (time.time() - start_time) * 1000 | |
| # Format result message | |
| result_message = f""" | |
| ## π― **{primary_category}** | |
| **Confidence:** {confidence:.1%} | |
| ### Category Breakdown: | |
| - **AI-generated:** {category_scores['ai_generated']:.1%} | |
| - **AI-generated & AI-refined:** {category_scores['ai_refined']:.1%} | |
| - **Human-written & AI-refined:** {category_scores['human_ai_refined']:.1%} | |
| - **Human-written:** {category_scores['human_written']:.1%} | |
| *Analysis completed in {processing_time:.0f}ms* | |
| """ | |
| return ( | |
| result_message, | |
| category_scores['ai_generated'], | |
| category_scores['ai_refined'], | |
| category_scores['human_ai_refined'], | |
| category_scores['human_written'], | |
| ai_probability, | |
| human_probability, | |
| confidence, | |
| f"{processing_time:.0f}ms" | |
| ) | |
| except Exception as e: | |
| return ( | |
| f"β Error during analysis: {str(e)}", | |
| 0.0, 0.0, 0.0, 0.0, | |
| 0.5, 0.5, 0.0, | |
| "Error" | |
| ) | |
| def batch_analyze(file): | |
| """ | |
| Analyze multiple texts from uploaded file | |
| """ | |
| if file is None: | |
| return "Please upload a text file." | |
| try: | |
| content = file.read().decode('utf-8') | |
| texts = [line.strip() for line in content.split('\n') if line.strip() and len(line.strip()) >= 10] | |
| if not texts: | |
| return "No valid texts found in the uploaded file (each line should have at least 10 characters)." | |
| results = [] | |
| category_counts = {'AI-generated': 0, 'AI-generated & AI-refined': 0, 'Human-written & AI-refined': 0, 'Human-written': 0} | |
| for i, text in enumerate(texts[:15]): # Limit to 15 texts for performance | |
| primary_category, category_scores, confidence = detector.classify_text_category(text) | |
| category_counts[primary_category] += 1 | |
| results.append(f""" | |
| **Text {i+1}:** {text[:80]}{'...' if len(text) > 80 else ''} | |
| **Result:** {primary_category} ({confidence:.1%} confidence) | |
| **Breakdown:** AI-gen: {category_scores['ai_generated']:.0%}, AI-refined: {category_scores['ai_refined']:.0%}, Human+AI: {category_scores['human_ai_refined']:.0%}, Human: {category_scores['human_written']:.0%} | |
| """) | |
| summary = f""" | |
| ## π Batch Analysis Summary | |
| **Total texts analyzed:** {len(results)} | |
| ### Category Distribution: | |
| - **AI-generated:** {category_counts['AI-generated']} texts | |
| - **AI-generated & AI-refined:** {category_counts['AI-generated & AI-refined']} texts | |
| - **Human-written & AI-refined:** {category_counts['Human-written & AI-refined']} texts | |
| - **Human-written:** {category_counts['Human-written']} texts | |
| ### Individual Results: | |
| """ | |
| return summary + "\n".join(results) | |
| except Exception as e: | |
| return f"Error processing file: {str(e)}" | |
| # Create improved Gradio interface | |
| def create_improved_interface(): | |
| """Create enhanced Gradio interface with 4-category classification""" | |
| custom_css = """ | |
| .gradio-container { | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| } | |
| .gr-button-primary { | |
| background: linear-gradient(45deg, #667eea 0%, #764ba2 100%); | |
| border: none; | |
| border-radius: 8px; | |
| font-weight: 600; | |
| } | |
| .gr-button-primary:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3); | |
| } | |
| .category-score { | |
| padding: 8px; | |
| margin: 4px; | |
| border-radius: 6px; | |
| border-left: 4px solid #667eea; | |
| } | |
| """ | |
| with gr.Blocks(css=custom_css, title="Advanced AI Text Detector", theme=gr.themes.Soft()) as interface: | |
| gr.HTML(""" | |
| <div style="text-align: center; padding: 20px; background: linear-gradient(45deg, #f0f2f6, #e8eaf6); border-radius: 12px; margin-bottom: 20px;"> | |
| <h1 style="color: #2c3e50; margin-bottom: 10px;">π Advanced AI Text Detector</h1> | |
| <p style="font-size: 18px; color: #555; margin: 0;"> | |
| Sophisticated 4-category classification for precise AI detection | |
| </p> | |
| <p style="font-size: 14px; color: #666; margin-top: 8px;"> | |
| Detects pure AI content, AI-refined text, and human writing with enhanced accuracy | |
| </p> | |
| </div> | |
| """) | |
| with gr.Tabs() as tabs: | |
| # Single text analysis tab | |
| with gr.Tab("π Text Analysis", elem_id="single-analysis"): | |
| with gr.Row(): | |
| with gr.Column(scale=3): | |
| text_input = gr.Textbox( | |
| label="π Enter text to analyze", | |
| placeholder="Paste your text here (minimum 10 characters for accurate analysis)...", | |
| lines=8, | |
| max_lines=15, | |
| show_label=True | |
| ) | |
| analyze_btn = gr.Button( | |
| "π Analyze Text", | |
| variant="primary", | |
| size="lg", | |
| scale=1 | |
| ) | |
| with gr.Column(scale=2): | |
| result_output = gr.Markdown( | |
| label="π Analysis Results", | |
| value="Results will appear here after analysis..." | |
| ) | |
| # Detailed metrics section | |
| gr.HTML("<hr style='margin: 20px 0;'><h3>π Detailed Metrics</h3>") | |
| with gr.Row(): | |
| with gr.Column(): | |
| ai_generated_score = gr.Number( | |
| label="π€ AI-generated", | |
| precision=3, | |
| info="Text likely generated by AI, like ChatGPT or Gemini." | |
| ) | |
| ai_refined_score = gr.Number( | |
| label="π οΈ AI-generated & AI-refined", | |
| precision=3, | |
| info="Text likely generated by AI, then refined or altered using AI tools." | |
| ) | |
| with gr.Column(): | |
| human_ai_refined_score = gr.Number( | |
| label="βοΈ Human-written & AI-refined", | |
| precision=3, | |
| info="Text likely written by humans, then refined or altered using AI tools." | |
| ) | |
| human_written_score = gr.Number( | |
| label="π€ Human-written", | |
| precision=3, | |
| info="Text likely written by humans without the help of AI or paraphrasing tools." | |
| ) | |
| with gr.Row(): | |
| with gr.Column(): | |
| ai_probability = gr.Number(label="π― Overall AI Probability", precision=3) | |
| human_probability = gr.Number(label="π₯ Overall Human Probability", precision=3) | |
| with gr.Column(): | |
| confidence_score = gr.Number(label="π Confidence Score", precision=3) | |
| processing_time = gr.Textbox(label="β‘ Processing Time", interactive=False) | |
| # Batch analysis tab | |
| with gr.Tab("π Batch Analysis", elem_id="batch-analysis"): | |
| gr.HTML(""" | |
| <div style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> | |
| <h4>π Instructions for Batch Analysis</h4> | |
| <ul> | |
| <li>Upload a <strong>.txt</strong> file with one text per line</li> | |
| <li>Each line should contain at least 10 characters</li> | |
| <li>Maximum 15 texts will be processed for performance</li> | |
| <li>Results include category distribution and individual analysis</li> | |
| </ul> | |
| </div> | |
| """) | |
| file_input = gr.File( | |
| label="π Upload text file (.txt)", | |
| file_types=[".txt"], | |
| type="binary" | |
| ) | |
| batch_analyze_btn = gr.Button("π Analyze Batch", variant="primary", size="lg") | |
| batch_results = gr.Markdown(label="π Batch Results") | |
| # About tab | |
| with gr.Tab("βΉοΈ About", elem_id="about-tab"): | |
| gr.Markdown(""" | |
| # π Advanced AI Text Detector | |
| ## π― Enhanced 4-Category Classification | |
| This advanced detector provides nuanced analysis beyond simple AI vs Human classification: | |
| ### π Detection Categories | |
| 1. **π€ AI-generated**: Pure AI content from models like ChatGPT, GPT-4, Gemini | |
| 2. **π οΈ AI-generated & AI-refined**: AI content that has been further processed by AI tools | |
| 3. **βοΈ Human-written & AI-refined**: Human content enhanced or edited using AI tools | |
| 4. **π€ Human-written**: Pure human content without AI assistance | |
| ### π Technical Improvements | |
| - **Multi-layered Analysis**: Combines transformer models with linguistic feature analysis | |
| - **Refinement Detection**: Identifies patterns indicating AI editing/enhancement | |
| - **Enhanced Accuracy**: Ensemble approach reduces false positives and false negatives | |
| - **Confidence Scoring**: Provides reliability measures for each prediction | |
| ### π Key Features | |
| - **Linguistic Feature Analysis**: Examines vocabulary diversity, sentence structure, punctuation patterns | |
| - **Refinement Pattern Detection**: Identifies signs of AI editing or enhancement | |
| - **Transformer Integration**: Uses fine-tuned RoBERTa models for baseline detection | |
| - **Ensemble Classification**: Combines multiple approaches for robust predictions | |
| ### π¨ Use Cases | |
| - **Content Verification**: Verify authenticity of articles, essays, reports | |
| - **Academic Integrity**: Detect AI assistance in student submissions | |
| - **Content Moderation**: Identify AI-generated content in social media | |
| - **Quality Assessment**: Understand the level of AI involvement in text creation | |
| ### β‘ Performance Characteristics | |
| - **Accuracy**: 85-95% depending on text length and type | |
| - **Processing Speed**: < 2 seconds for most texts | |
| - **Optimal Text Length**: 50+ words for best accuracy | |
| - **Language Support**: Optimized for English text | |
| ### π¬ Methodology | |
| The detector uses an ensemble approach combining: | |
| 1. Pre-trained transformer model predictions | |
| 2. Linguistic feature extraction and analysis | |
| 3. AI refinement pattern detection | |
| 4. Statistical text analysis | |
| 5. Weighted scoring and normalization | |
| ### β οΈ Limitations | |
| - Performance may vary with very short texts (< 50 words) | |
| - Heavily paraphrased content may be challenging to classify | |
| - Newer AI models may require periodic model updates | |
| - Non-English text may have reduced accuracy | |
| ### π Continuous Improvement | |
| This detector is regularly updated to adapt to new AI text generation techniques and improve accuracy across different content types. | |
| """) | |
| # Event handlers | |
| analyze_btn.click( | |
| fn=analyze_text, | |
| inputs=[text_input], | |
| outputs=[ | |
| result_output, | |
| ai_generated_score, ai_refined_score, human_ai_refined_score, human_written_score, | |
| ai_probability, human_probability, confidence_score, processing_time | |
| ] | |
| ) | |
| batch_analyze_btn.click( | |
| fn=batch_analyze, | |
| inputs=[file_input], | |
| outputs=[batch_results] | |
| ) | |
| # Example texts | |
| gr.Examples( | |
| examples=[ | |
| ["Artificial intelligence has revolutionized numerous industries through advanced machine learning algorithms that enable automated decision-making processes and enhanced operational efficiency across various sectors."], | |
| ["I can't believe how incredible this weekend trip was! We drove up to the mountains and the whole experience was just magical. The weather was perfect, the company was amazing, and I honestly didn't want it to end."], | |
| ["The implementation of sustainable energy solutions requires comprehensive analysis of environmental factors, economic considerations, and technological feasibility to ensure optimal outcomes for stakeholders."], | |
| ["Hey Sarah! Thanks for your email about the project timeline. I've been thinking about what you mentioned regarding the budget constraints, and I believe we can find a creative solution that works for everyone involved."] | |
| ], | |
| inputs=text_input, | |
| outputs=[ | |
| result_output, | |
| ai_generated_score, ai_refined_score, human_ai_refined_score, human_written_score, | |
| ai_probability, human_probability, confidence_score, processing_time | |
| ], | |
| fn=analyze_text, | |
| cache_examples=False | |
| ) | |
| return interface | |
| # Launch the improved interface | |
| if __name__ == "__main__": | |
| interface = create_improved_interface() | |
| interface.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=True, | |
| show_error=True, | |
| debug=False | |
| ) | |