File size: 5,411 Bytes
458a1a0 1acf258 d0fc808 458a1a0 1acf258 458a1a0 1acf258 c19c925 1acf258 458a1a0 |
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 |
import gradio as gr
import requests
import json
import os
import time
from collections import defaultdict
from PIL import Image
import io
import pandas as pd
BASE_URL = "https://api.jigsawstack.com/v1"
headers = {
"x-api-key":os.getenv("JIGSAWSTACK_API_KEY")
}
# Rate limiting configuration
request_times = defaultdict(list)
MAX_REQUESTS = 20 # Maximum requests per time window
TIME_WINDOW = 3600 # Time window in seconds (1 hour)
def get_real_ip(request: gr.Request):
"""Extract real IP address using x-forwarded-for header or fallback"""
if not request:
return "unknown"
forwarded = request.headers.get("x-forwarded-for")
if forwarded:
ip = forwarded.split(",")[0].strip() # First IP in the list is the client's
else:
ip = request.client.host # fallback
return ip
def check_rate_limit(request: gr.Request):
"""Check if the current request exceeds rate limits"""
if not request:
return True, "Rate limit check failed - no request info"
ip = get_real_ip(request)
now = time.time()
# Clean up old timestamps outside the time window
request_times[ip] = [t for t in request_times[ip] if now - t < TIME_WINDOW]
# Check if rate limit exceeded
if len(request_times[ip]) >= MAX_REQUESTS:
time_remaining = int(TIME_WINDOW - (now - request_times[ip][0]))
time_remaining_minutes = round(time_remaining / 60, 1)
time_window_minutes = round(TIME_WINDOW / 60, 1)
return False, f"Rate limit exceeded. You can make {MAX_REQUESTS} requests per {time_window_minutes} minutes. Try again in {time_remaining_minutes} minutes."
# Add current request timestamp
request_times[ip].append(now)
return True, ""
def analyze_sentiment(text, request: gr.Request):
rate_limit_ok, rate_limit_msg = check_rate_limit(request)
if not rate_limit_ok:
return f"β {rate_limit_msg}", None, None, None, None
if not text or not text.strip():
return "Error: Text input is required.", None, None, None, None
try:
response = requests.post(
f"{BASE_URL}/ai/sentiment",
headers=headers,
json={"text": text.strip()}
)
response.raise_for_status()
result = response.json()
if not result.get("success"):
error_msg = f"Error: API call failed - {result.get('message', 'Unknown error')}"
return error_msg, None, None, None, None
sentiment_data = result.get("sentiment", {})
overall_emotion = sentiment_data.get("emotion", "N/A")
overall_sentiment = sentiment_data.get("sentiment", "N/A")
overall_score = sentiment_data.get("score", "N/A")
sentences = sentiment_data.get("sentences", [])
if sentences:
sentence_df = pd.DataFrame(sentences)
sentence_df = sentence_df[['text', 'emotion', 'sentiment', 'score']]
sentence_df.rename(columns={'text': 'Sentence', 'emotion': 'Emotion', 'sentiment': 'Sentiment', 'score': 'Score'}, inplace=True)
else:
sentence_df = pd.DataFrame(columns=['Sentence', 'Emotion', 'Sentiment', 'Score'])
status_message = "β
Sentiment analysis complete."
return status_message, overall_emotion, overall_sentiment, str(overall_score), sentence_df
except requests.exceptions.RequestException as e:
return f"Request failed: {str(e)}", None, None, None, None
except Exception as e:
return f"An unexpected error occurred: {str(e)}", None, None, None, None
with gr.Blocks() as demo:
gr.Markdown("""
<div style='text-align: center; margin-bottom: 24px;'>
<h1 style='font-size:2.2em; margin-bottom: 0.2em;'>π§© Analyze Sentiment</h1>
<p style='font-size:1.2em; margin-top: 0;'>Perform line-by-line sentiment analysis on any text with detailed emotion detection.</p>
<p style='font-size:1em; margin-top: 0.5em;'>For more details and API usage, see the <a href='https://jigsawstack.com/docs/api-reference/ai/sentiment' target='_blank'>documentation</a>.</p>
</div>
""")
with gr.Row():
with gr.Column():
gr.Markdown("#### Input Text")
sentiment_text = gr.Textbox(
label="Text to Analyze",
lines=8,
placeholder="Enter the text you want to analyze here..."
)
sentiment_btn = gr.Button("Analyze Sentiment", variant="primary")
with gr.Column():
gr.Markdown("#### Overall Analysis")
sentiment_status = gr.Textbox(label="Status", interactive=False)
sentiment_emotion = gr.Textbox(label="Overall Emotion", interactive=False)
sentiment_sentiment = gr.Textbox(label="Overall Sentiment", interactive=False)
sentiment_score = gr.Textbox(label="Overall Score", interactive=False)
gr.Markdown("#### Sentence-Level Breakdown")
sentiment_sentences_df = gr.DataFrame(label="Sentence Analysis")
sentiment_btn.click(
analyze_sentiment,
inputs=[sentiment_text],
outputs=[sentiment_status, sentiment_emotion, sentiment_sentiment, sentiment_score, sentiment_sentences_df]
)
demo.launch()
|