dotoking commited on
Commit
af57a2e
Β·
verified Β·
1 Parent(s): b3dd450

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +177 -131
app.py CHANGED
@@ -1,141 +1,187 @@
1
  import gradio as gr
2
- from cear_model import CEARModel
3
  import pandas as pd
4
- import numpy as np # Used for consistency, though cear_model uses it
5
 
6
- # Initialize Model
7
  cear_analyzer = CEARModel()
8
 
9
- # --- Configuration: Default Values ---
10
- DEFAULT_DATA = [
11
- ["TikTok", 0],
12
- ["Instagram", 0],
13
- ["YouTube", 0],
14
- ["X/Twitter", 0],
15
- ["Reddit", 0],
16
- ["Facebook", 0],
17
- ["LinkedIn", 0]
18
- ]
19
-
20
- def interpret_scores(c_score, a_risk, d_index):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  """
22
- Converts raw numbers into human-readable context with thresholds.
 
 
23
  """
24
- # --- 1. Interpret Algorithmic Risk (A-Risk) ---
25
- # Thresholds: <150 (Low), 150-500 (Medium), >500 (High)
26
- if a_risk < 150:
27
- a_status = "🟒 Low Risk"
28
- a_desc = "Your usage is within a safe range, likely minimizing algorithmic manipulation."
29
- elif a_risk < 500:
30
- a_status = "🟑 Moderate Risk"
31
- a_desc = "You have significant exposure to algorithmic feeds. Be mindful of 'rabbit holes'."
32
- else:
33
- a_status = "πŸ”΄ High Risk"
34
- a_desc = "Your attention is heavily concentrated in high-risk algorithmic environments."
35
-
36
- # --- 2. Interpret Cultural Connectedness (C-Score) ---
37
- # Thresholds: <2.0 (Disconnected), 2.0-5.0 (Connected), >5.0 (Very High)
38
- if c_score < 2.0:
39
- c_status = "βšͺ Low Exposure"
40
- c_desc = "You likely miss many viral trends, which protects focus but reduces cultural sync."
41
- elif c_score < 5.0:
42
- c_status = "πŸ”΅ Balanced Exposure"
43
- c_desc = "You are plugged into main trends without being overwhelmed."
44
- else:
45
- c_status = "🟣 High Saturation"
46
- c_desc = "You are extremely plugged in. Ensure this doesn't lead to information overload."
47
-
48
- # --- 3. Interpret Diversity (D-Index) ---
49
- # Thresholds: 1.0 (Monoculture) to >3.0 (Diverse)
50
- if d_index < 1.5:
51
- d_status = "⚠️ Concentrated"
52
- d_desc = "Your time is spent almost entirely on one platform (Echo Chamber risk)."
53
- elif d_index < 3.0:
54
- d_status = "βš–οΈ Moderate Spread"
55
- d_desc = "You split time across a few apps, offering some variety."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  else:
57
- d_status = "🌐 High Diversity"
58
- d_desc = "Your usage is well-distributed, reducing reliance on any single algorithm."
59
-
60
- return {
61
- "A_Status": a_status, "A_Desc": a_desc,
62
- "C_Status": c_status, "C_Desc": c_desc,
63
- "D_Status": d_status, "D_Desc": d_desc
64
- }
65
-
66
- def analyze_user_data(input_table, variety_rating, fomo_rating):
67
- # 1. Process Input
68
- user_data_df = pd.DataFrame(input_table, columns=['platform_name', 'minutes_per_week'])
69
- user_data_df['minutes_per_week'] = pd.to_numeric(user_data_df['minutes_per_week'], errors='coerce').fillna(0)
70
-
71
- # 2. Run Model
72
- raw_scores = cear_analyzer.calculate_scores(user_data_df)
73
-
74
- # 3. Get Interpretation
75
- context = interpret_scores(raw_scores['C_Score'], raw_scores['A_Risk'], raw_scores['D_Index'])
76
-
77
- # 4. Generate Rich Markdown Output
78
  summary = f"""
79
- ## πŸ“Š Analysis Results
80
-
81
- ### 1. Algorithmic Risk: {context['A_Status']}
82
- *Score: {raw_scores['A_Risk']:.0f}*
83
- > {context['A_Desc']}
84
-
85
- ### 2. Cultural Connectedness: {context['C_Status']}
86
- *Score: {raw_scores['C_Score']:.2f}*
87
- > {context['C_Desc']}
88
-
89
- ### 3. Platform Diversity: {context['D_Status']}
90
- *Index: {raw_scores['D_Index']:.2f}*
91
- > {context['D_Desc']}
92
-
93
- ---
94
- ### πŸ—£οΈ Self-Reported Context
95
- * **Perceived Variety:** {variety_rating}/5
96
- * **FOMO Intensity:** {fomo_rating}/5
97
- """
98
 
99
- return summary, pd.DataFrame(raw_scores['Per_Platform_Efficiency'])
100
-
101
- # --- Interface Definition (FIXED: theme removed) ---
102
- # Removed: theme=gr.themes.Soft()
103
- with gr.Blocks(title="CEAR Model") as demo:
104
- gr.Markdown("# 🧭 Cultural Exposure & Algorithmic Risk (CEAR) Model")
105
- gr.Markdown("""
106
- **Instructions:**
107
- 1. Enter your estimated **minutes per week** for each app (e.g., check your phone's Screen Time).
108
- 2. Adjust the sliders for your personal experience.
109
- 3. Click **Analyze** to see if your habits align with your goals.
110
- """)
111
-
112
- with gr.Row():
113
- with gr.Column(scale=2):
114
- input_table = gr.Dataframe(
115
- headers=['platform_name', 'minutes_per_week'],
116
- value=DEFAULT_DATA,
117
- datatype=["str", "number"],
118
- row_count=7,
119
- col_count=(2, 'fixed'),
120
- label="Weekly Screen Time Inputs"
121
- )
122
-
123
- with gr.Column(scale=1):
124
- gr.Markdown("### 🧠 Self-Reflection")
125
- variety_slider = gr.Slider(1, 5, step=1, value=3, label="Perceived Variety (1=Samey, 5=Diverse)")
126
- fomo_slider = gr.Slider(1, 5, step=1, value=3, label="FOMO Intensity (1=None, 5=High)")
127
-
128
- analyze_btn = gr.Button("πŸ” Analyze Risks", variant="primary")
129
-
130
- with gr.Row():
131
- output_text = gr.Markdown(label="Detailed Report")
132
- output_table = gr.Dataframe(label="Cultural Efficiency (Score per Minute)")
133
-
134
- analyze_btn.click(
135
- fn=analyze_user_data,
136
- inputs=[input_table, variety_slider, fomo_slider],
137
- outputs=[output_text, output_table]
138
- )
139
-
140
- if __name__ == "__main__":
141
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
 
 
 
1
  import gradio as gr
 
2
  import pandas as pd
3
+ from cear_model import CEARModel
4
 
5
+ # Instantiate the core model once
6
  cear_analyzer = CEARModel()
7
 
8
+ # Supported canonical platform names (must match what CEARModel expects)
9
+ SUPPORTED_PLATFORMS = {
10
+ "tiktok",
11
+ "instagram",
12
+ "youtube",
13
+ "twitter",
14
+ "reddit",
15
+ "facebook",
16
+ "other",
17
+ }
18
+
19
+ # Simple alias map for common variations typed by users
20
+ PLATFORM_ALIASES = {
21
+ "tik tok": "tiktok",
22
+ "tt": "tiktok",
23
+
24
+ "ig": "instagram",
25
+ "insta": "instagram",
26
+
27
+ "yt": "youtube",
28
+ "you tube": "youtube",
29
+
30
+ "x": "twitter",
31
+
32
+ "fb": "facebook",
33
+ "face book": "facebook",
34
+ }
35
+
36
+
37
+ def normalize_platform_name(name: str) -> str:
38
  """
39
+ Normalize free-text platform names to the canonical set:
40
+ tiktok, instagram, youtube, twitter, reddit, facebook, other.
41
+ Unknown entries are mapped to 'other'.
42
  """
43
+ if not isinstance(name, str):
44
+ return "other"
45
+
46
+ cleaned = name.strip().lower()
47
+ if cleaned == "":
48
+ return ""
49
+
50
+ # Apply alias map
51
+ cleaned = PLATFORM_ALIASES.get(cleaned, cleaned)
52
+
53
+ # If not in supported set, bucket into 'other'
54
+ if cleaned not in SUPPORTED_PLATFORMS:
55
+ return "other"
56
+
57
+ return cleaned
58
+
59
+
60
+ def analyze_user_data(input_table):
61
+ """
62
+ Gradio callback for CEAR.
63
+
64
+ input_table: list of lists from gr.Dataframe, e.g.
65
+ [
66
+ ["tiktok", 240],
67
+ ["instagram", 180],
68
+ ...
69
+ ]
70
+ Returns:
71
+ summary_markdown (str), efficiency_dataframe (pd.DataFrame)
72
+ """
73
+
74
+ # 1. Basic validation: something must be entered
75
+ if not input_table:
76
+ return "Please enter at least one platform and its weekly minutes.", pd.DataFrame()
77
+
78
+ # Convert raw table to DataFrame with fixed columns
79
+ df = pd.DataFrame(input_table, columns=["platform_name", "minutes_per_week"])
80
+
81
+ # Handle types and trim garbage rows
82
+ df["platform_name"] = df["platform_name"].astype(str)
83
+ df["minutes_per_week"] = pd.to_numeric(df["minutes_per_week"], errors="coerce")
84
+
85
+ # Drop rows where both are missing/empty
86
+ df = df.dropna(how="all")
87
+ if df.empty:
88
+ return "Please provide at least one platform with some minutes.", pd.DataFrame()
89
+
90
+ # Normalize names and minutes
91
+ df["platform_name"] = df["platform_name"].apply(normalize_platform_name)
92
+ df["minutes_per_week"] = df["minutes_per_week"].fillna(0).clip(lower=0)
93
+
94
+ # Drop rows with blank platform names
95
+ df = df[df["platform_name"] != ""]
96
+ if df.empty:
97
+ return "Please provide at least one platform with some minutes.", pd.DataFrame()
98
+
99
+ # 2. Call the core CEAR model
100
+ raw_scores = cear_analyzer.calculate_scores(df)
101
+
102
+ c = float(raw_scores.get("C_Score", 0.0))
103
+ a = float(raw_scores.get("A_Risk", 0.0))
104
+ d = float(raw_scores.get("D_Index", 0.0))
105
+ per_eff = raw_scores.get("Per_Platform_Efficiency", {})
106
+
107
+ # 3. Build a human-readable profile based on score bands
108
+ if c >= 70 and a >= 70:
109
+ profile = (
110
+ "You are highly plugged into online culture, but that comes with high "
111
+ "algorithmic risk and a heavy concentration of attention."
112
+ )
113
+ elif c >= 70 and a < 70:
114
+ profile = (
115
+ "You are well-connected to online culture without extreme algorithmic concentration. "
116
+ "Your usage is relatively efficient for staying up to date."
117
+ )
118
+ elif c < 40 and a >= 70:
119
+ profile = (
120
+ "You give a lot of attention to a narrow set of feeds without gaining much cultural exposure. "
121
+ "This is a classic high-risk, low-benefit pattern."
122
+ )
123
  else:
124
+ profile = (
125
+ "You currently have relatively low exposure to viral trends and also keep algorithmic risk low. "
126
+ "You are either deliberately detached or under-invested in highly trend-dense platforms."
127
+ )
128
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  summary = f"""
130
+ ## πŸ“Š CEAR Analysis Summary
131
+
132
+ - **Cultural Connectedness Score (C-Score):** **{c:.2f}**
133
+ - **Algorithmic Risk Score (A-Risk):** **{a:.2f}**
134
+ - **Platform Diversity Index (D-Index):** **{d:.2f}**
135
+
136
+ ### πŸ“ Interpretation
 
 
 
 
 
 
 
 
 
 
 
 
137
 
138
+ {profile}
139
+
140
+ The C-Score is based on a logarithmic transform of your weekly minutes, which bakes in diminishing returns as time increases.
141
+ A-Risk reflects your raw time investment and how concentrated it is on a small set of high-weight platforms.
142
+ D-Index captures how spread out your usage is across different platforms.
143
+ """.strip()
144
+
145
+ # 4. Turn per-platform efficiency into a tidy table
146
+ if isinstance(per_eff, dict) and per_eff:
147
+ eff_df = pd.DataFrame(
148
+ sorted(per_eff.items(), key=lambda kv: kv[1], reverse=True),
149
+ columns=["platform", "efficiency_score"],
150
+ )
151
+ else:
152
+ eff_df = pd.DataFrame(columns=["platform", "efficiency_score"])
153
+
154
+ return summary, eff_df
155
+
156
+
157
+ # ---------- Gradio app definition ----------
158
+
159
+ demo = gr.Interface(
160
+ fn=analyze_user_data,
161
+ inputs=gr.Dataframe(
162
+ headers=["platform_name", "minutes_per_week"],
163
+ row_count=5,
164
+ col_count=(2, "fixed"),
165
+ label="Weekly screen time (by platform)",
166
+ value=[
167
+ ["tiktok", 240],
168
+ ["instagram", 180],
169
+ ["youtube", 120],
170
+ ["twitter", 60],
171
+ ["reddit", 90],
172
+ ],
173
+ ),
174
+ outputs=[
175
+ gr.Markdown(label="Score Results"),
176
+ gr.Dataframe(label="Per-platform Cultural Efficiency"),
177
+ ],
178
+ title="CEAR – Cultural Exposure & Algorithmic Risk Analyzer",
179
+ description=(
180
+ "Enter your weekly screen time per platform to estimate your cultural connectedness, "
181
+ "algorithmic risk, and per-platform efficiency."
182
+ ),
183
+ )
184
+
185
+
186
+ if __name__ == "__main__":
187
+ demo.launch()