Spaces:
Sleeping
Sleeping
File size: 5,810 Bytes
39a4dc6 7d7870d 39a4dc6 7d7870d 39a4dc6 7d7870d 39a4dc6 03a5c69 7d7870d 03a5c69 7d7870d 39a4dc6 03a5c69 7d7870d 39a4dc6 7d7870d 03a5c69 39a4dc6 7d7870d 39a4dc6 7d7870d 39a4dc6 03a5c69 7d7870d 39a4dc6 7d7870d 03a5c69 39a4dc6 03a5c69 7d7870d 39a4dc6 03a5c69 39a4dc6 7d7870d 39a4dc6 7d7870d 39a4dc6 03a5c69 39a4dc6 7d7870d 39a4dc6 03a5c69 39a4dc6 03a5c69 39a4dc6 7d7870d 39a4dc6 03a5c69 39a4dc6 03a5c69 39a4dc6 03a5c69 39a4dc6 03a5c69 39a4dc6 03a5c69 39a4dc6 03a5c69 02fd047 39a4dc6 03a5c69 39a4dc6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | # app.py - Audio & Text Sentiment Analyzer
# Transcription: openai/whisper-base.en (official HF version)
# Sentiment: nlptown/bert-base-multilingual-uncased-sentiment (5-star accurate model)
import gradio as gr
import torch
import numpy as np
import librosa
from transformers import (
AutoProcessor,
AutoModelForSpeechSeq2Seq,
AutoTokenizer,
AutoModelForSequenceClassification
)
import torch.nn.functional as F
print("Loading models... Please wait.")
# === Load Whisper exactly as requested ===
processor = AutoProcessor.from_pretrained("openai/whisper-base.en")
whisper_model = AutoModelForSpeechSeq2Seq.from_pretrained("openai/whisper-base.en")
whisper_model.eval()
device = "cuda" if torch.cuda.is_available() else "cpu"
whisper_model.to(device)
# === Load Sentiment model exactly as requested ===
sentiment_tokenizer = AutoTokenizer.from_pretrained('nlptown/bert-base-multilingual-uncased-sentiment')
sentiment_model = AutoModelForSequenceClassification.from_pretrained('nlptown/bert-base-multilingual-uncased-sentiment')
sentiment_model.eval()
sentiment_model.to(device)
print("All models loaded successfully!")
# Transcribe audio using official Whisper
def transcribe_audio(audio_path):
if audio_path is None:
return ""
try:
# Load and resample to 16kHz
speech, _ = librosa.load(audio_path, sr=16000)
# Process input
input_features = processor(speech, sampling_rate=16000, return_tensors="pt").input_features
input_features = input_features.to(device)
# Generate transcription
with torch.no_grad():
predicted_ids = whisper_model.generate(input_features)
transcription = processor.batch_decode(predicted_ids, skip_special_tokens=True)[0]
return transcription.strip()
except Exception as e:
print(f"Transcription error: {e}")
return "[Transcription failed]"
# Sentiment analysis with 5-star rating and confidence
def analyze_sentiment(text):
if not text.strip():
return "βββ Neutral", "0%"
inputs = sentiment_tokenizer(text[:512], return_tensors="pt", truncation=True).to(device)
with torch.no_grad():
logits = sentiment_model(**inputs).logits
probabilities = F.softmax(logits, dim=-1)[0]
predicted_class = torch.argmax(probabilities).item() + 1 # 1 to 5
confidence = probabilities[predicted_class - 1].item() * 100
conf_str = f"{confidence:.1f}%"
stars = "β" * predicted_class
if predicted_class == 1:
level = f"{stars} Very Negative"
elif predicted_class == 2:
level = f"{stars} Negative"
elif predicted_class == 3:
level = f"{stars} Neutral"
elif predicted_class == 4:
level = f"{stars} Positive"
else:
level = f"{stars} Very Positive"
return level, conf_str
# Main unified function
def analyze_input(audio_path, input_text):
# Use typed text if provided
if input_text and input_text.strip():
final_text = input_text.strip()
# Otherwise transcribe audio
elif audio_path is not None:
print("Transcribing audio...")
final_text = transcribe_audio(audio_path)
if not final_text or "failed" in final_text.lower():
return "Transcription failed or no speech detected.", "", "", "Please try again with clearer English audio."
else:
return "No input provided.", "", "", "Please type text or record/upload audio."
# Sentiment analysis
level, confidence = analyze_sentiment(final_text)
final_result = f"{level} (Confidence: {confidence})"
return final_text, level, confidence, final_result
# Gradio Interface
with gr.Blocks(title="Audio & Text Sentiment Analyzer", theme=gr.themes.Soft()) as demo:
gr.Markdown("# π€βοΈ Audio to Text + 5-Star Sentiment Analyzer")
gr.Markdown("""
- **Transcription**: OpenAI Whisper-base.en (excellent English accuracy)
- **Sentiment**: Multilingual BERT fine-tuned on reviews β accurate **1β5 star** ratings
- Record/upload audio **or** type text directly
""")
with gr.Row():
with gr.Column(scale=1):
audio_input = gr.Audio(
sources=["microphone", "upload"],
type="filepath",
label="Record or Upload Audio (English recommended)"
)
gr.Markdown("**OR**")
text_input = gr.Textbox(
label="Type or Paste Text",
placeholder="Enter your review, feedback, or transcribed text...",
lines=6
)
btn = gr.Button("Transcribe & Analyze Sentiment", variant="primary", size="lg")
with gr.Column():
gr.Markdown("### π Transcribed / Entered Text")
text_display = gr.Textbox(label="Text", lines=8, interactive=False)
gr.Markdown("### π Sentiment Result")
with gr.Row():
level_out = gr.Textbox(label="Sentiment Level", scale=2)
conf_out = gr.Textbox(label="Confidence", scale=1)
result_out = gr.Textbox(label="Final Verdict", lines=2, interactive=False)
btn.click(
fn=analyze_input,
inputs=[audio_input, text_input],
outputs=[text_display, level_out, conf_out, result_out]
)
# gr.Markdown("""
# ### Notes
# - Best performance with **clear English speech**
# - Sentiment model excels at review-style language (opinions, experiences)
# - Confidence >80% = very reliable prediction
# - Runs completely locally β perfect for privacy
# - Built with β€οΈ in Accra by Chris (@chrisbekor99)
# """)
# Run app
if __name__ == "__main__":
demo.launch() |