Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import spacy
|
| 3 |
+
from transformers import pipeline
|
| 4 |
+
import json
|
| 5 |
+
|
| 6 |
+
# Load models once at startup
|
| 7 |
+
nlp = spacy.load("en_core_web_sm")
|
| 8 |
+
classifier = pipeline("zero-shot-classification")
|
| 9 |
+
|
| 10 |
+
def analyze_sentence_purposes(script):
|
| 11 |
+
purposes = []
|
| 12 |
+
doc = nlp(script)
|
| 13 |
+
for sent in doc.sents:
|
| 14 |
+
if any(token.text in ['?', 'how', 'why', 'what'] for token in sent):
|
| 15 |
+
purposes.append(("QUESTION", "Engages curiosity"))
|
| 16 |
+
elif any(token.lemma_ in ['show', 'teach', 'explain'] for token in sent):
|
| 17 |
+
purposes.append(("INSTRUCTION", "Provides guidance"))
|
| 18 |
+
elif any(token.lemma_ in ['discover', 'find', 'reveal'] for token in sent):
|
| 19 |
+
purposes.append(("REVELATION", "Shares discovery"))
|
| 20 |
+
elif any(token.lemma_ in ['struggle', 'problem', 'difficult'] for token in sent):
|
| 21 |
+
purposes.append(("CONFLICT", "Presents challenge"))
|
| 22 |
+
elif any(token.lemma_ in ['result', 'success', 'transform'] for token in sent):
|
| 23 |
+
purposes.append(("RESOLUTION", "Shows payoff"))
|
| 24 |
+
else:
|
| 25 |
+
purposes.append(("CONTEXT", "Sets scene"))
|
| 26 |
+
return purposes
|
| 27 |
+
|
| 28 |
+
def map_emotional_arc(script):
|
| 29 |
+
emotional_phases = []
|
| 30 |
+
doc = nlp(script)
|
| 31 |
+
emotional_indicators = {
|
| 32 |
+
'struggle': ['frustrat', 'difficult', 'struggle', 'problem', 'failed'],
|
| 33 |
+
'curiosity': ['wonder', 'curious', 'question', 'mystery', 'secret'],
|
| 34 |
+
'discovery': ['find', 'discover', 'learn', 'realize', 'figure out'],
|
| 35 |
+
'transformation': ['change', 'transform', 'better', 'improve', 'success'],
|
| 36 |
+
'satisfaction': ['happy', 'proud', 'excited', 'amazing', 'awesome']
|
| 37 |
+
}
|
| 38 |
+
for sent in doc.sents:
|
| 39 |
+
sentence_emotion = "NEUTRAL"
|
| 40 |
+
max_strength = 0
|
| 41 |
+
for emotion, keywords in emotional_indicators.items():
|
| 42 |
+
strength = sum(1 for token in sent if token.lemma_ in keywords)
|
| 43 |
+
if strength > max_strength:
|
| 44 |
+
max_strength = strength
|
| 45 |
+
sentence_emotion = emotion.upper()
|
| 46 |
+
emotional_phases.append(sentence_emotion)
|
| 47 |
+
return emotional_phases
|
| 48 |
+
|
| 49 |
+
def detect_narrative_pattern(semantic_analysis):
|
| 50 |
+
purposes = [p[0] for p in semantic_analysis['purposes']]
|
| 51 |
+
emotions = semantic_analysis['emotional_arc']
|
| 52 |
+
pattern_signatures = {
|
| 53 |
+
'TRANSFORMATION': [
|
| 54 |
+
['CONFLICT', 'REVELATION', 'RESOLUTION'],
|
| 55 |
+
['struggle', 'discovery', 'transformation']
|
| 56 |
+
],
|
| 57 |
+
'INVESTIGATION': [
|
| 58 |
+
['QUESTION', 'REVELATION', 'RESOLUTION'],
|
| 59 |
+
['curiosity', 'discovery', 'satisfaction']
|
| 60 |
+
],
|
| 61 |
+
'STORYTELLING': [
|
| 62 |
+
['CONTEXT', 'CONFLICT', 'RESOLUTION'],
|
| 63 |
+
['neutral', 'struggle', 'satisfaction']
|
| 64 |
+
],
|
| 65 |
+
'EXPLANATION': [
|
| 66 |
+
['QUESTION', 'INSTRUCTION', 'RESOLUTION'],
|
| 67 |
+
['curiosity', 'neutral', 'satisfaction']
|
| 68 |
+
]
|
| 69 |
+
}
|
| 70 |
+
best_pattern = None
|
| 71 |
+
highest_match = 0
|
| 72 |
+
for pattern_name, signature in pattern_signatures.items():
|
| 73 |
+
purpose_match = sum(1 for i, purpose in enumerate(purposes)
|
| 74 |
+
if i < len(signature[0]) and purpose == signature[0][i])
|
| 75 |
+
emotion_match = sum(1 for i, emotion in enumerate(emotions)
|
| 76 |
+
if i < len(signature[1]) and emotion.lower() == signature[1][i])
|
| 77 |
+
total_match = purpose_match + emotion_match
|
| 78 |
+
if total_match > highest_match:
|
| 79 |
+
highest_match = total_match
|
| 80 |
+
best_pattern = pattern_name
|
| 81 |
+
return best_pattern, highest_match / (len(purposes) + len(emotions))
|
| 82 |
+
|
| 83 |
+
def analyze_creator_intent(script, semantic_analysis):
|
| 84 |
+
doc = nlp(script)
|
| 85 |
+
intent_indicators = {
|
| 86 |
+
'EDUCATE': ['teach', 'explain', 'show', 'learn', 'understand'],
|
| 87 |
+
'ENTERTAIN': ['funny', 'hilarious', 'entertain', 'enjoy', 'laugh'],
|
| 88 |
+
'INSPIRE': ['motivate', 'inspire', 'empower', 'transform', 'change'],
|
| 89 |
+
'PERSUADE': ['should', 'must', 'need to', 'recommend', 'best'],
|
| 90 |
+
'DOCUMENT': ['experience', 'journey', 'story', 'happened', 'went']
|
| 91 |
+
}
|
| 92 |
+
intent_scores = {intent: 0 for intent in intent_indicators.keys()}
|
| 93 |
+
for token in doc:
|
| 94 |
+
for intent, keywords in intent_indicators.items():
|
| 95 |
+
if token.lemma_ in keywords:
|
| 96 |
+
intent_scores[intent] += 1
|
| 97 |
+
if any(p[0] == 'INSTRUCTION' for p in semantic_analysis['purposes']):
|
| 98 |
+
intent_scores['EDUCATE'] += 2
|
| 99 |
+
if 'struggle' in semantic_analysis['emotional_arc']:
|
| 100 |
+
intent_scores['INSPIRE'] += 2
|
| 101 |
+
primary_intent = max(intent_scores.items(), key=lambda x: x[1])
|
| 102 |
+
return primary_intent[0], intent_scores
|
| 103 |
+
|
| 104 |
+
def detect_contextual_domain(script):
|
| 105 |
+
doc = nlp(script)
|
| 106 |
+
domain_indicators = {
|
| 107 |
+
'TECHNOLOGY': ['software', 'app', 'code', 'digital', 'algorithm'],
|
| 108 |
+
'HEALTH': ['energy', 'health', 'body', 'mind', 'wellness'],
|
| 109 |
+
'BUSINESS': ['money', 'business', 'market', 'profit', 'investment'],
|
| 110 |
+
'CREATIVE': ['design', 'create', 'art', 'build', 'make'],
|
| 111 |
+
'ACADEMIC': ['research', 'study', 'theory', 'data', 'analysis']
|
| 112 |
+
}
|
| 113 |
+
domain_scores = {domain: 0 for domain in domain_indicators.keys()}
|
| 114 |
+
for token in doc:
|
| 115 |
+
for domain, terms in domain_indicators.items():
|
| 116 |
+
if token.lemma_ in terms:
|
| 117 |
+
domain_scores[domain] += 1
|
| 118 |
+
primary_domain = max(domain_scores.items(), key=lambda x: x[1])
|
| 119 |
+
sentence_complexity = sum(len(list(sent.root.children)) for sent in doc.sents) / len(list(doc.sents))
|
| 120 |
+
sophistication = "ADVANCED" if sentence_complexity > 5 else "INTERMEDIATE" if sentence_complexity > 3 else "BEGINNER"
|
| 121 |
+
return primary_domain[0], sophistication, domain_scores
|
| 122 |
+
|
| 123 |
+
def analyze_script(script):
|
| 124 |
+
"""NLP-First Universal Script Analysis"""
|
| 125 |
+
if not script.strip():
|
| 126 |
+
return "β Please enter a script to analyze"
|
| 127 |
+
|
| 128 |
+
try:
|
| 129 |
+
# Layer 1: Semantic Understanding
|
| 130 |
+
semantic_results = {
|
| 131 |
+
'purposes': analyze_sentence_purposes(script),
|
| 132 |
+
'emotional_arc': map_emotional_arc(script)
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
# Layer 2: Narrative Pattern Detection
|
| 136 |
+
pattern, pattern_confidence = detect_narrative_pattern(semantic_results)
|
| 137 |
+
|
| 138 |
+
# Layer 3: Intent & Domain Intelligence
|
| 139 |
+
primary_intent, intent_scores = analyze_creator_intent(script, semantic_results)
|
| 140 |
+
primary_domain, sophistication, domain_scores = detect_contextual_domain(script)
|
| 141 |
+
|
| 142 |
+
# Format results
|
| 143 |
+
result = f"""
|
| 144 |
+
π― **UNIVERSAL SCRIPT ANALYSIS**
|
| 145 |
+
|
| 146 |
+
π§ **SEMANTIC UNDERSTANDING:**
|
| 147 |
+
- Sentence Purposes: {', '.join([p[0] for p in semantic_results['purposes']])}
|
| 148 |
+
- Emotional Arc: {', '.join(semantic_results['emotional_arc'])}
|
| 149 |
+
|
| 150 |
+
π **NARRATIVE PATTERN:**
|
| 151 |
+
- Primary Pattern: {pattern} ({pattern_confidence:.1%} confidence)
|
| 152 |
+
|
| 153 |
+
π― **CREATOR INTENT:**
|
| 154 |
+
- Primary Intent: {primary_intent}
|
| 155 |
+
- Intent Breakdown: {', '.join([f'{k}:{v}' for k,v in intent_scores.items() if v > 0])}
|
| 156 |
+
|
| 157 |
+
π **DOMAIN INTELLIGENCE:**
|
| 158 |
+
- Primary Domain: {primary_domain}
|
| 159 |
+
- Sophistication: {sophistication}
|
| 160 |
+
- Domain Scores: {', '.join([f'{k}:{v}' for k,v in domain_scores.items() if v > 0])}
|
| 161 |
+
|
| 162 |
+
π **CONTENT BLUEPRINT:** {pattern} + {primary_domain} Domain
|
| 163 |
+
"""
|
| 164 |
+
return result
|
| 165 |
+
|
| 166 |
+
except Exception as e:
|
| 167 |
+
return f"β Error analyzing script: {str(e)}"
|
| 168 |
+
|
| 169 |
+
# Create Gradio interface
|
| 170 |
+
demo = gr.Interface(
|
| 171 |
+
fn=analyze_script,
|
| 172 |
+
inputs=gr.Textbox(lines=10, placeholder="Paste your script here...", label="Script"),
|
| 173 |
+
outputs=gr.Textbox(label="Analysis Results"),
|
| 174 |
+
title="π€ Universal Script Analyzer Pro",
|
| 175 |
+
description="NLP-First Analysis: Semantic Understanding β Narrative Patterns β Intent & Domain"
|
| 176 |
+
)
|
| 177 |
+
|
| 178 |
+
# For API access
|
| 179 |
+
def api_analyze(script):
|
| 180 |
+
return analyze_script(script)
|
| 181 |
+
|
| 182 |
+
if __name__ == "__main__":
|
| 183 |
+
demo.launch(share=True)
|