Spaces:
Sleeping
Sleeping
Create algorithm.py
Browse files- algorithm.py +281 -0
algorithm.py
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import random
|
| 3 |
+
from typing import List, Dict, Union, Tuple
|
| 4 |
+
|
| 5 |
+
# --- Configuration Constants (Normalized to 0-100 Scale) ---
|
| 6 |
+
# Weighting for the Final Content Score (CS)
|
| 7 |
+
W1_PREDICTION = 0.50
|
| 8 |
+
W2_TALENT = 0.15
|
| 9 |
+
W3_PROGRESS = 0.15
|
| 10 |
+
W4_QUALITY = 0.15
|
| 11 |
+
# Dynamic Allocation
|
| 12 |
+
MAX_DYNAMIC_BOOST = 0.05 # Max 5% of CS allowed via dynamic boosts/penalties
|
| 13 |
+
SUPPRESSION_PENALTY = 0.60 # Penalty multiplier for high ESR content
|
| 14 |
+
FOLLOW_THRESHOLD = 1000 # Max followers for Small-Creator Advantage
|
| 15 |
+
|
| 16 |
+
# --- Score Scaling and Clamping Constants ---
|
| 17 |
+
PS_FLAT_PROGRESS = 50.0 # PS score when a creator has 0% improvement
|
| 18 |
+
NETWORK_AVG_ESR = 0.10 # Network average Early Skip Rate (0-1)
|
| 19 |
+
|
| 20 |
+
class UpnisoAlgorithmPipeline:
|
| 21 |
+
"""
|
| 22 |
+
Upniso Merit-Based Recommendation Algorithm Pipeline (V2.0).
|
| 23 |
+
|
| 24 |
+
Encapsulates the 6-stage architecture: Analyze, Score, Predict, Test,
|
| 25 |
+
Distribute, and Learn. All core scores are normalized to a 0-100 scale.
|
| 26 |
+
"""
|
| 27 |
+
|
| 28 |
+
def __init__(self, avg_esr: float = NETWORK_AVG_ESR, avg_ts: float = 50.0, avg_wtpu: float = 0.50):
|
| 29 |
+
"""Initializes the pipeline with network baseline averages for comparison."""
|
| 30 |
+
self.avg_esr = avg_esr
|
| 31 |
+
self.avg_ts = avg_ts
|
| 32 |
+
self.avg_wtpu = avg_wtpu
|
| 33 |
+
self.creators = {}
|
| 34 |
+
self.content_queue = {}
|
| 35 |
+
|
| 36 |
+
# --- Stage 1: Analyze (Data Ingestion and Cleanup) ---
|
| 37 |
+
def analyze(self, creator_id: str, creator_data: dict, content_id: str, content_data: dict):
|
| 38 |
+
"""
|
| 39 |
+
Ingests, sanitizes, and verifies raw data from the database/API.
|
| 40 |
+
Adds fallbacks for missing historical data.
|
| 41 |
+
"""
|
| 42 |
+
# Guard against division by zero and provide sensible fallbacks (Task B.3)
|
| 43 |
+
creator_data['ts_90_days_ago'] = max(creator_data.get('ts_90_days_ago', self.avg_ts), 1.0)
|
| 44 |
+
creator_data['avg_wtpu_month1'] = max(creator_data.get('avg_wtpu_month1', self.avg_wtpu), 0.01)
|
| 45 |
+
creator_data['ts_14_days_ago'] = creator_data.get('ts_14_days_ago', creator_data['ts_90_days_ago'])
|
| 46 |
+
creator_data['stdev_upload_days'] = creator_data.get('stdev_upload_days', 4.0)
|
| 47 |
+
|
| 48 |
+
content_data['wtpu_current'] = np.clip(content_data.get('wtpu_current', 0.0), 0.0, 1.0).item()
|
| 49 |
+
content_data['nvr'] = np.clip(content_data.get('nvr', 0.0), 0.0, 1.0).item()
|
| 50 |
+
# MIS is 1.0 for compliance (True), 0.5 otherwise (False/Missing)
|
| 51 |
+
content_data['mis_score'] = 1.0 if content_data.get('mis_compliance', False) else 0.5
|
| 52 |
+
content_data['esr_current'] = np.clip(content_data.get('esr_current', 0.5), 0.0, 1.0).item()
|
| 53 |
+
content_data['prediction_score_p_hva'] = content_data.get('prediction_score_p_hva', 0.5)
|
| 54 |
+
|
| 55 |
+
self.creators[creator_id] = creator_data
|
| 56 |
+
self.content_queue[content_id] = content_data
|
| 57 |
+
self.content_queue[content_id]['creator_id'] = creator_id
|
| 58 |
+
|
| 59 |
+
# --- Stage 2: Score (Creator Profile Merit Calculation) ---
|
| 60 |
+
def score(self, creator_id: str) -> Dict[str, float]:
|
| 61 |
+
"""
|
| 62 |
+
Calculates the creator's persistent Talent Score (TS) and Progress Score (PS).
|
| 63 |
+
Both scores are normalized to 0-100.
|
| 64 |
+
"""
|
| 65 |
+
creator_data = self.creators.get(creator_id)
|
| 66 |
+
if not creator_data: return {'TS': self.avg_ts, 'PS': PS_FLAT_PROGRESS}
|
| 67 |
+
|
| 68 |
+
# 1. Talent Score (TS) Calculation (0-100, Normalized)
|
| 69 |
+
wtpu_norm = creator_data['wtpu_last_10_avg']
|
| 70 |
+
hva_norm = creator_data.get('avg_hva_rate', 0.05)
|
| 71 |
+
# Consistency Factor: Closer to 1.0 is better (lower stdev)
|
| 72 |
+
consistency = 1.0 / (creator_data['stdev_upload_days'] + 1.0)
|
| 73 |
+
|
| 74 |
+
# TS = 100 * (0.5 * WTPU + 0.3 * HVA + 0.2 * Consistency)
|
| 75 |
+
ts_merit = 100 * (0.5 * wtpu_norm + 0.3 * hva_norm + 0.2 * consistency)
|
| 76 |
+
ts_today = np.clip(ts_merit, 0, 100).item()
|
| 77 |
+
self.creators[creator_id]['ts_today'] = ts_today
|
| 78 |
+
|
| 79 |
+
# 2. Progress Score (PS) Calculation (0-100, 50=Flat)
|
| 80 |
+
ts_90_days_ago = creator_data['ts_90_days_ago']
|
| 81 |
+
wtpu_m1 = creator_data['avg_wtpu_month1']
|
| 82 |
+
wtpu_m3 = creator_data.get('avg_wtpu_month3', wtpu_m1)
|
| 83 |
+
|
| 84 |
+
# PS_Raw = 50 + [Delta TS * 50] + [Delta WTPU * 50]
|
| 85 |
+
ts_delta_contribution = ((ts_today / ts_90_days_ago) - 1.0) * 50
|
| 86 |
+
wtpu_delta_contribution = ((wtpu_m3 / wtpu_m1) - 1.0) * 50
|
| 87 |
+
|
| 88 |
+
ps_raw = PS_FLAT_PROGRESS + ts_delta_contribution + wtpu_delta_contribution
|
| 89 |
+
|
| 90 |
+
# Forgiveness Boost Check (Task A.10: If TS improved >= 20% in 14 days)
|
| 91 |
+
ts_14_days_ago = creator_data['ts_14_days_ago']
|
| 92 |
+
ts_14_day_improvement = (ts_today - ts_14_days_ago) / ts_14_days_ago
|
| 93 |
+
|
| 94 |
+
forgiveness_boost = 0
|
| 95 |
+
if ts_14_day_improvement >= 0.20:
|
| 96 |
+
forgiveness_boost = 15 # +15 score for demonstrated momentum
|
| 97 |
+
|
| 98 |
+
# Clamping PS score (0-100)
|
| 99 |
+
ps_score = np.clip(ps_raw + forgiveness_boost, 0, 100).item()
|
| 100 |
+
|
| 101 |
+
return {'TS': ts_today, 'PS': ps_score}
|
| 102 |
+
|
| 103 |
+
# --- Stage 3: Predict (Affinity Model Simulation) ---
|
| 104 |
+
def predict(self, content_id: str) -> float:
|
| 105 |
+
"""
|
| 106 |
+
Simulates the Prediction Score (P(HVA)) based on user affinity.
|
| 107 |
+
Returns score (0-100).
|
| 108 |
+
"""
|
| 109 |
+
content_data = self.content_queue.get(content_id)
|
| 110 |
+
if not content_data: return PS_FLAT_PROGRESS
|
| 111 |
+
|
| 112 |
+
prediction_raw = content_data['prediction_score_p_hva'] * 100
|
| 113 |
+
return np.clip(prediction_raw, 0, 100).item()
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
# --- Stage 4: Test (Fair Exposure Engine - FEE) ---
|
| 117 |
+
def test(self, content_id: str, merit_scores: Dict[str, float]) -> Tuple[float, float]:
|
| 118 |
+
"""
|
| 119 |
+
Calculates the Quality Score (QS) and the dynamic boost/penalty flag
|
| 120 |
+
based on initial T0/T1 micro-test results.
|
| 121 |
+
Returns QS (0-100) and Dynamic Factor (0 to 5%).
|
| 122 |
+
"""
|
| 123 |
+
content_data = self.content_queue.get(content_id)
|
| 124 |
+
creator_data = self.creators.get(content_data['creator_id'])
|
| 125 |
+
if not content_data or not creator_data: return PS_FLAT_PROGRESS, 0.0
|
| 126 |
+
|
| 127 |
+
# 1. Quality Score (QS) Calculation (0-100, Normalized)
|
| 128 |
+
wtpu = content_data['wtpu_current']
|
| 129 |
+
nvr = content_data['nvr']
|
| 130 |
+
mis = content_data['mis_score']
|
| 131 |
+
|
| 132 |
+
# QS = 100 * (0.6 * WTPU + 0.3 * NVR + 0.1 * MIS)
|
| 133 |
+
qs_score = 100 * (0.6 * wtpu + 0.3 * nvr + 0.1 * mis)
|
| 134 |
+
qs_score = np.clip(qs_score, 0, 100).item()
|
| 135 |
+
|
| 136 |
+
# 2. Dynamic Boost Calculation (5% Max)
|
| 137 |
+
dynamic_factor = 0.0
|
| 138 |
+
|
| 139 |
+
# Small-Creator Advantage (1.5x Multiplier to Merit in Test Phase)
|
| 140 |
+
if creator_data['follower_count'] < FOLLOW_THRESHOLD:
|
| 141 |
+
# Merit component calculation (normalized to 0-1)
|
| 142 |
+
merit_value_norm = (W2_TALENT * merit_scores['TS'] + W3_PROGRESS * merit_scores['PS'] + W4_QUALITY * qs_score) / 100
|
| 143 |
+
|
| 144 |
+
# 1.5x multiplier means adding 50% of the calculated merit value (45% weight)
|
| 145 |
+
boost_value = merit_value_norm * 0.5
|
| 146 |
+
|
| 147 |
+
# Clamp the boost to the allocated 5% maximum dynamic weight
|
| 148 |
+
dynamic_factor += np.clip(boost_value, 0, MAX_DYNAMIC_BOOST).item()
|
| 149 |
+
|
| 150 |
+
# 3. Negative Signal Suppression Flag (ESR >= 5x Avg)
|
| 151 |
+
esr_ratio = content_data['esr_current'] / self.avg_esr if self.avg_esr > 0 else 1.0
|
| 152 |
+
penalty_flag = False
|
| 153 |
+
if esr_ratio >= 5.0:
|
| 154 |
+
penalty_flag = True
|
| 155 |
+
|
| 156 |
+
self.content_queue[content_id]['penalty_flag'] = penalty_flag
|
| 157 |
+
self.content_queue[content_id]['QS'] = qs_score
|
| 158 |
+
|
| 159 |
+
return qs_score, dynamic_factor
|
| 160 |
+
|
| 161 |
+
# --- Stage 5: Distribute (Final Content Score Ranking) ---
|
| 162 |
+
def distribute(self, content_id: str, merit_scores: Dict[str, float], pred_score: float, qs_score: float, dynamic_factor: float) -> float:
|
| 163 |
+
"""
|
| 164 |
+
Calculates the Final Content Score (CS, 0-1.0) used for feed ranking.
|
| 165 |
+
"""
|
| 166 |
+
|
| 167 |
+
# Convert 0-100 scores to 0-1 for weighting
|
| 168 |
+
ts_norm = merit_scores['TS'] / 100
|
| 169 |
+
ps_norm = merit_scores['PS'] / 100
|
| 170 |
+
qs_norm = qs_score / 100
|
| 171 |
+
pred_norm = pred_score / 100
|
| 172 |
+
|
| 173 |
+
# Baseline CS (95% weight) = (50% Pred) + (45% Merit)
|
| 174 |
+
cs_baseline = (W1_PREDICTION * pred_norm) + \
|
| 175 |
+
(W2_TALENT * ts_norm) + \
|
| 176 |
+
(W3_PROGRESS * ps_norm) + \
|
| 177 |
+
(W4_QUALITY * qs_norm)
|
| 178 |
+
|
| 179 |
+
# Final Content Score (Max 1.0)
|
| 180 |
+
final_cs = cs_baseline + dynamic_factor
|
| 181 |
+
|
| 182 |
+
# Apply Suppression Penalty if flagged
|
| 183 |
+
if self.content_queue.get(content_id, {}).get('penalty_flag', False):
|
| 184 |
+
final_cs *= SUPPRESSION_PENALTY
|
| 185 |
+
|
| 186 |
+
return np.clip(final_cs, 0, 1).item()
|
| 187 |
+
|
| 188 |
+
# --- Stage 6: Learn (Feedback Loop Simulation) ---
|
| 189 |
+
def learn(self, creator_id: str, content_id: str, final_cs: float):
|
| 190 |
+
"""
|
| 191 |
+
Simulates updating the creator's profile data based on content performance (Offline Job).
|
| 192 |
+
"""
|
| 193 |
+
# In a real system, this would run daily to update ts_90_days_ago, ts_14_days_ago, etc.
|
| 194 |
+
# For simulation, we just record results.
|
| 195 |
+
self.content_queue[content_id]['final_cs'] = final_cs
|
| 196 |
+
self.content_queue[content_id]['PS'] = self.content_queue[content_id].get('PS', 0)
|
| 197 |
+
self.content_queue[content_id]['TS'] = self.content_queue[content_id].get('TS', 0)
|
| 198 |
+
|
| 199 |
+
|
| 200 |
+
# --- Simulation Mode (Task B.6 / D) ---
|
| 201 |
+
def run_simulation(self, creators_data: Dict[str, Dict], contents_data: Dict[str, Dict]):
|
| 202 |
+
"""Runs a competition simulation for all provided content and returns the ranked list."""
|
| 203 |
+
results = []
|
| 204 |
+
|
| 205 |
+
print("="*80)
|
| 206 |
+
print("UPNISO ALGORITHM SIMULATION (V2.0)")
|
| 207 |
+
print("="*80)
|
| 208 |
+
|
| 209 |
+
for content_id, content_input in contents_data.items():
|
| 210 |
+
creator_id = content_input['creator_id']
|
| 211 |
+
creator_input = creators_data[creator_id]
|
| 212 |
+
|
| 213 |
+
# --- Pipeline Execution ---
|
| 214 |
+
self.analyze(creator_id, creator_input, content_id, content_input)
|
| 215 |
+
|
| 216 |
+
merit = self.score(creator_id)
|
| 217 |
+
pred = self.predict(content_id)
|
| 218 |
+
qs, dynamic_boost = self.test(content_id, merit)
|
| 219 |
+
|
| 220 |
+
# Store scores for reporting
|
| 221 |
+
self.content_queue[content_id]['QS'] = qs
|
| 222 |
+
self.content_queue[content_id]['PS'] = merit['PS']
|
| 223 |
+
self.content_queue[content_id]['TS'] = merit['TS']
|
| 224 |
+
self.content_queue[content_id]['Pred'] = pred
|
| 225 |
+
self.content_queue[content_id]['dynamic_boost'] = dynamic_boost
|
| 226 |
+
|
| 227 |
+
final_cs = self.distribute(content_id, merit, pred, qs, dynamic_boost)
|
| 228 |
+
self.learn(creator_id, content_id, final_cs)
|
| 229 |
+
|
| 230 |
+
# --- Reporting ---
|
| 231 |
+
penalty = "APPLIED" if self.content_queue[content_id].get('penalty_flag') else "None"
|
| 232 |
+
|
| 233 |
+
results.append({
|
| 234 |
+
'content_id': content_id,
|
| 235 |
+
'creator_id': creator_id,
|
| 236 |
+
'CS': final_cs,
|
| 237 |
+
'TS': merit['TS'],
|
| 238 |
+
'PS': merit['PS'],
|
| 239 |
+
'QS': qs,
|
| 240 |
+
'Pred': pred,
|
| 241 |
+
'Dynamic_Boost': dynamic_boost,
|
| 242 |
+
'Penalty': penalty
|
| 243 |
+
})
|
| 244 |
+
|
| 245 |
+
# Final Ranking
|
| 246 |
+
results.sort(key=lambda x: x['CS'], reverse=True)
|
| 247 |
+
|
| 248 |
+
print("\n" + "="*80)
|
| 249 |
+
print("FINAL RANKED ORDER (Rank #1 is highest CS)")
|
| 250 |
+
print("="*80)
|
| 251 |
+
|
| 252 |
+
for i, r in enumerate(results):
|
| 253 |
+
print(f"RANK {i+1:2}: CS={r['CS']:.4f} | TS={r['TS']:.1f} | PS={r['PS']:.1f} | QS={r['QS']:.1f} | Pred={r['Pred']:.1f} | ID={r['content_id']} ({r['creator_id']})")
|
| 254 |
+
|
| 255 |
+
return results
|
| 256 |
+
|
| 257 |
+
# --- Simulation Data and Execution (Task D) ---
|
| 258 |
+
|
| 259 |
+
# 1. Creator Data (Pre-calculated and Denormalized inputs)
|
| 260 |
+
CREATORS_DATA = {
|
| 261 |
+
'C1': {'follower_count': 500, 'ts_90_days_ago': 20.0, 'ts_14_days_ago': 28.0, 'wtpu_last_10_avg': 0.85, 'avg_hva_rate': 0.15, 'stdev_upload_days': 0.5, 'avg_wtpu_month1': 0.2, 'avg_wtpu_month3': 0.4}, # Small/High-Skill: TS up 40% in 14 days
|
| 262 |
+
'C2': {'follower_count': 15000, 'ts_90_days_ago': 70.0, 'ts_14_days_ago': 70.0, 'wtpu_last_10_avg': 0.65, 'avg_hva_rate': 0.05, 'stdev_upload_days': 4.0, 'avg_wtpu_month1': 0.6, 'avg_wtpu_month3': 0.6}, # Luck-Focused: Stagnant, inconsistent
|
| 263 |
+
'C3': {'follower_count': 5000, 'ts_90_days_ago': 50.0, 'ts_14_days_ago': 45.0, 'wtpu_last_10_avg': 0.50, 'avg_hva_rate': 0.08, 'stdev_upload_days': 2.5, 'avg_wtpu_month1': 0.5, 'avg_wtpu_month3': 0.4}, # Mid-Stagnant: Regressing
|
| 264 |
+
'C4': {'follower_count': 100000, 'ts_90_days_ago': 85.0, 'ts_14_days_ago': 88.0, 'wtpu_last_10_avg': 0.80, 'avg_hva_rate': 0.20, 'stdev_upload_days': 1.0, 'avg_wtpu_month1': 0.7, 'avg_wtpu_month3': 0.77}, # Large/Consistent: Elite skill, steady improvement
|
| 265 |
+
'C5': {'follower_count': 50, 'ts_90_days_ago': 10.0, 'ts_14_days_ago': 11.0, 'wtpu_last_10_avg': 0.70, 'avg_hva_rate': 0.10, 'stdev_upload_days': 3.0, 'avg_wtpu_month1': 0.1, 'avg_wtpu_month3': 0.3}, # Micro/Improving: Huge WTPU progress, TS up 25% in 14 days
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
# 2. Content Data (Micro-Test results and Model Predictions)
|
| 269 |
+
CONTENTS_DATA = {
|
| 270 |
+
'CN1': {'creator_id': 'C1', 'wtpu_current': 0.95, 'nvr': 0.20, 'mis_compliance': True, 'esr_current': 0.08, 'prediction_score_p_hva': 0.30}, # Niche, High Quality
|
| 271 |
+
'CN2': {'creator_id': 'C2', 'wtpu_current': 0.15, 'nvr': 0.05, 'mis_compliance': False, 'esr_current': 0.55, 'prediction_score_p_hva': 0.90}, # Clickbait, Low Quality (ESR 5.5x Avg)
|
| 272 |
+
'CN3': {'creator_id': 'C3', 'wtpu_current': 0.50, 'nvr': 0.10, 'mis_compliance': True, 'esr_current': 0.10, 'prediction_score_p_hva': 0.50}, # Average
|
| 273 |
+
'CN4': {'creator_id': 'C4', 'wtpu_current': 0.80, 'nvr': 0.30, 'mis_compliance': True, 'esr_current': 0.12, 'prediction_score_p_hva': 0.85}, # Elite, High Affinity
|
| 274 |
+
'CN5': {'creator_id': 'C5', 'wtpu_current': 0.75, 'nvr': 0.15, 'mis_compliance': True, 'esr_current': 0.05, 'prediction_score_p_hva': 0.20}, # High Progress, Unknown Affinity
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
if __name__ == '__main__':
|
| 278 |
+
pipeline = UpnisoAlgorithmPipeline()
|
| 279 |
+
pipeline.run_simulation(CREATORS_DATA, CONTENTS_DATA)
|
| 280 |
+
def run_demo():
|
| 281 |
+
return "Algorithm connected successfully"
|