trial / app.py
intrainmode's picture
Upload app.py
a0f5120 verified
Raw
History Blame Contribute Delete
11.1 kB
import os
import gradio as gr
from transformers import pipeline
# 1. Thread Optimization & GPU/CPU Configuration
# Force PyTorch to use 1 thread for CPU inference to avoid excessive context switching in constrained envs
import torch
torch.set_num_threads(1)
# Global lazy-loaded pipelines to minimize startup latency
_sentiment_pipeline = None
_zero_shot_pipeline = None
def get_sentiment_pipeline():
global _sentiment_pipeline
if _sentiment_pipeline is None:
# Using distilbert-base-uncased-finetuned-sst-2-english
# Extremely fast, highly accurate (~92% on SST-2), and highly efficient for production CPUs
_sentiment_pipeline = pipeline(
"sentiment-analysis",
model="distilbert-base-uncased-finetuned-sst-2-english",
revision="714eb0f"
)
return _sentiment_pipeline
def get_zero_shot_pipeline():
global _zero_shot_pipeline
if _zero_shot_pipeline is None:
# Using typeform/distilbert-base-uncased-mnli
# Extremely lightweight (~268MB), offering BART-like zero-shot capability at a fraction of the memory footprint
_zero_shot_pipeline = pipeline(
"zero-shot-classification",
model="typeform/distilbert-base-uncased-mnli"
)
return _zero_shot_pipeline
# 2. Main Logic Handlers
def analyze_sentiment(text):
if not text or not text.strip():
return {"Error": 1.0}, "Please enter valid text."
try:
classifier = get_sentiment_pipeline()
results = classifier(text)
# Format the output beautifully for Gradio's gr.Label
# e.g., {"POSITIVE": 0.999, "NEGATIVE": 0.001}
label = results[0]['label']
score = results[0]['score']
other_label = "NEGATIVE" if label == "POSITIVE" else "POSITIVE"
output_data = {
label: score,
other_label: 1.0 - score
}
emoji = "✨" if label == "POSITIVE" else "⚠️"
explanation = f"The model is **{score:.2%}** confident that this text has a **{label.lower()}** sentiment {emoji}."
return output_data, explanation
except Exception as e:
return {"Error": 1.0}, f"Inference Error: {str(e)}"
def classify_zero_shot(text, candidate_labels):
if not text or not text.strip():
return {"Error": 1.0}, "Please enter valid text."
if not candidate_labels or not candidate_labels.strip():
return {"Error": 1.0}, "Please enter at least one candidate label."
try:
# Clean and split the candidate labels
labels_list = [label.strip() for label in candidate_labels.split(",") if label.strip()]
if len(labels_list) == 0:
return {"Error": 1.0}, "Please provide valid comma-separated labels."
classifier = get_zero_shot_pipeline()
results = classifier(text, candidate_labels=labels_list)
# Gradio Label component expects a dict of {label_name: float_probability}
output_data = {label: score for label, score in zip(results['labels'], results['scores'])}
top_label = results['labels'][0]
top_score = results['scores'][0]
explanation = f"**Top Match**: classified as **'{top_label}'** with **{top_score:.1%}** confidence."
return output_data, explanation
except Exception as e:
return {"Error": 1.0}, f"Inference Error: {str(e)}"
# 3. Custom Theming & Premium Visual Layout
# Sleek, enterprise-grade Slate and Sapphire design with clean edges
theme = gr.themes.Soft(
primary_hue="indigo",
secondary_hue="blue",
neutral_hue="slate",
font=[gr.themes.GoogleFont("Inter"), "Helvetica Neue", "Arial", "sans-serif"]
).set(
body_background_fill="*neutral_50",
body_background_fill_dark="*neutral_950",
button_primary_background_fill="linear-gradient(135deg, #4f46e5 0%, #3b82f6 100%)",
button_primary_background_fill_hover="linear-gradient(135deg, #4338ca 0%, #2563eb 100%)",
button_primary_text_color="white",
block_title_text_weight="600",
block_border_width="1px",
block_shadow="rgba(0, 0, 0, 0.05) 0px 4px 12px"
)
# Custom CSS for glassmorphism headers and beautiful margins
custom_css = """
.header-container {
background: linear-gradient(135deg, #1e1b4b 0%, #0f172a 100%);
padding: 2.5rem;
border-radius: 12px;
margin-bottom: 2rem;
color: white;
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.15), 0 8px 10px -6px rgba(0, 0, 0, 0.15);
}
.header-title {
font-size: 2.5rem;
font-weight: 800;
letter-spacing: -0.025em;
margin: 0;
background: linear-gradient(to right, #a5b4fc, #818cf8, #60a5fa);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.header-subtitle {
font-size: 1.1rem;
opacity: 0.85;
margin-top: 0.5rem;
}
.footer-text {
text-align: center;
font-size: 0.85rem;
color: #64748b;
margin-top: 3rem;
}
"""
with gr.Blocks(title="NexusCorp AI Suite") as demo:
# 4. Premium Header Section
gr.HTML(
"""
<div class="header-container">
<h1 class="header-title">NexusCorp NLP Engine</h1>
<p class="header-subtitle">State-of-the-art NLP classification models optimized for instant pipeline inference</p>
</div>
"""
)
with gr.Tabs():
# Tab 1: Sentiment Analysis
with gr.Tab("Sentiment Intelligence"):
gr.Markdown(
"""
### 🎭 Real-Time Sentiment & Polarity Analysis
Detect emotional valence (Positive or Negative) in conversational copy, client feedback, or support tickets.
"""
)
with gr.Row():
with gr.Column(scale=5):
sentiment_input = gr.Textbox(
label="Analyze Copy",
placeholder="Type or paste your text here (e.g., 'The new service launch was absolutely stellar, we got incredible feedback!')...",
lines=5,
max_lines=12
)
# Examples for users to interact with immediately
gr.Examples(
examples=[
["The new update is absolute perfection! Visual design looks stunning and responsiveness is stellar."],
["I'm extremely disappointed with the delayed shipment, and the customer support was non-responsive."],
["The product works fine, although it has a few minor bugs that need to be patched in the next release."]
],
inputs=sentiment_input,
label="Pre-loaded Enterprise Scenarios"
)
sentiment_btn = gr.Button("Execute Analysis", variant="primary")
with gr.Column(scale=4):
sentiment_label = gr.Label(
label="Sentiment Distribution",
num_top_classes=2
)
sentiment_explanation = gr.Markdown("*Awaiting analysis request...*")
sentiment_btn.click(
fn=analyze_sentiment,
inputs=sentiment_input,
outputs=[sentiment_label, sentiment_explanation]
)
# Tab 2: Zero-Shot Classification
with gr.Tab("Zero-Shot Classification"):
gr.Markdown(
"""
### 🏷️ Zero-Shot Dynamic Categorizer
Classify any piece of copy into **custom labels** on the fly without any model re-training.
"""
)
with gr.Row():
with gr.Column(scale=5):
zero_shot_text = gr.Textbox(
label="Input Text",
placeholder="Type text to classify here...",
lines=4
)
zero_shot_labels = gr.Textbox(
label="Candidate Labels (Comma-Separated)",
placeholder="e.g. Finance, Technology, Health, Sports, Customer Support",
value="Finance, Technology, Support, Marketing"
)
gr.Examples(
examples=[
[
"We need to schedule a software patch rollout tonight to resolve the high CPU consumption on the database server.",
"Technology, Infrastructure, Finance, Urgent Operations"
],
[
"Our marketing campaign saw a 25% lift in click-through rates after changing the call-to-action button color.",
"Creative Design, Marketing Metrics, Legal, Engineering"
],
[
"Can I get a refund for my order? The invoice was generated with double the tax rate.",
"Billing Support, Bug Report, Sales Inquiries, Careers"
]
],
inputs=[zero_shot_text, zero_shot_labels],
label="Zero-Shot Use Cases"
)
zero_shot_btn = gr.Button("Categorize Copy", variant="primary")
with gr.Column(scale=4):
zero_shot_label = gr.Label(
label="Probability Distribution"
)
zero_shot_explanation = gr.Markdown("*Awaiting categorization request...*")
zero_shot_btn.click(
fn=classify_zero_shot,
inputs=[zero_shot_text, zero_shot_labels],
outputs=[zero_shot_label, zero_shot_explanation]
)
# Premium footer info
gr.HTML(
"""
<div class="footer-text">
<p>NexusCorp NLP Suite v1.2.0 • Powered by Hugging Face Transformers & Gradio</p>
<p style="font-size: 0.75rem; margin-top: 0.25rem; opacity: 0.8;">Configured for rapid containerized deployment</p>
</div>
"""
)
# 5. Local Running and Deployment Configuration
if __name__ == "__main__":
# Get port from environment variable (required for Hugging Face Spaces and other cloud runtimes)
port = int(os.environ.get("PORT", 7860))
# Launch Gradio interface.
# server_name="0.0.0.0" is critical for Docker/cloud environments to allow external requests
demo.queue().launch(
server_name="0.0.0.0",
server_port=port,
share=False,
theme=theme,
css=custom_css
)