Prak2005 commited on
Commit
f042c7f
Β·
verified Β·
1 Parent(s): 81af9a9

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +477 -0
app.py ADDED
@@ -0,0 +1,477 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ import os
3
+ import json
4
+ import logging
5
+ import random
6
+ from datetime import datetime, timedelta
7
+ from typing import Dict, Any, List, Optional
8
+ from pydantic import BaseModel, Field
9
+ import gradio as gr
10
+ from crewai import Agent, Crew, Process, Task, LLM
11
+ from crewai.agent import agent
12
+ from crewai.task import task
13
+ from crewai.crew import crew, CrewBase
14
+
15
+ # Setup logging
16
+ logging.basicConfig(
17
+ level=logging.INFO,
18
+ format="%(asctime)s [%(levelname)s] %(message)s",
19
+ )
20
+ logger = logging.getLogger(__name__)
21
+
22
+ # Initialize LLM (will use environment variable)
23
+ llm = LLM(
24
+ model="gemini/gemini-2.0-flash-exp", # or any other model
25
+ api_key=os.getenv("GEMINI_API_KEY", "dummy-key-for-testing"),
26
+ )
27
+
28
+ # ========== DATA MODELS ==========
29
+ class UserVerification(BaseModel):
30
+ user_id: str = Field(..., description="User ID")
31
+ name: str = Field(..., description="User name")
32
+ email: str = Field(..., description="User email")
33
+ is_verified: bool = Field(..., description="KYC verification status")
34
+ verification_level: str = Field(..., description="Verification level: basic, standard, premium")
35
+ risk_score: float = Field(..., description="Risk score 0-1")
36
+
37
+ class ScalpingDetection(BaseModel):
38
+ is_scalper: bool = Field(..., description="Whether user is detected as scalper")
39
+ confidence: float = Field(..., description="Detection confidence 0-1")
40
+ flags: List[str] = Field(..., description="Suspicious activity flags")
41
+ purchase_velocity: int = Field(..., description="Number of purchases in last hour")
42
+ ip_duplicates: int = Field(..., description="Number of accounts from same IP")
43
+
44
+ class PricingRecommendation(BaseModel):
45
+ original_price: float = Field(..., description="Original ticket price")
46
+ recommended_resale_price: float = Field(..., description="Recommended resale price")
47
+ demand_level: str = Field(..., description="Current demand level")
48
+ price_adjustment_reason: str = Field(..., description="Reason for price adjustment")
49
+ profit_margin: Optional[float] = Field(None, description="Profit margin percentage")
50
+ loss_percentage: Optional[float] = Field(None, description="Loss percentage if selling below cost")
51
+
52
+ class ResaleCompliance(BaseModel):
53
+ is_compliant: bool = Field(..., description="Whether resale is policy compliant")
54
+ violations: List[str] = Field(..., description="List of policy violations")
55
+ resale_allowed: bool = Field(..., description="Whether resale is allowed")
56
+ max_allowed_price: float = Field(..., description="Maximum allowed resale price")
57
+ recommendation: str = Field(..., description="Compliance recommendation")
58
+
59
+ class TicketingSystemReport(BaseModel):
60
+ verification: UserVerification
61
+ scalping_detection: ScalpingDetection
62
+ pricing: PricingRecommendation
63
+ compliance: ResaleCompliance
64
+ final_decision: str = Field(..., description="Final system decision")
65
+ action_items: List[str] = Field(..., description="Recommended actions")
66
+
67
+ # ========== MOCK DATA STORE ==========
68
+ class MockDatabase:
69
+ """Simulates a database for the MVP"""
70
+ def __init__(self):
71
+ self.user_purchase_history = {}
72
+ self.ip_addresses = {}
73
+ self.resale_history = {}
74
+
75
+ def get_user_purchases(self, user_id: str) -> int:
76
+ """Get number of recent purchases for a user"""
77
+ return self.user_purchase_history.get(user_id, random.randint(0, 5))
78
+
79
+ def get_ip_accounts(self, user_id: str) -> int:
80
+ """Get number of accounts from same IP"""
81
+ return random.randint(1, 4)
82
+
83
+ def get_resale_frequency(self, user_id: str) -> int:
84
+ """Get user's resale frequency"""
85
+ return self.resale_history.get(user_id, random.randint(0, 10))
86
+
87
+ # Initialize mock database
88
+ mock_db = MockDatabase()
89
+
90
+ # ========== CREW CLASS ==========
91
+ class AntiScalpingCrew(CrewBase):
92
+ """Anti-Scalping Ticketing System Crew"""
93
+
94
+ @agent
95
+ def user_verification_agent(self) -> Agent:
96
+ return Agent(
97
+ role="User Verification Specialist",
98
+ goal="Verify user identity and assess verification level for ticket purchases",
99
+ backstory="""You are an expert in Know Your Customer (KYC) processes and identity
100
+ verification. You assess user documentation, verify identities, and assign risk scores
101
+ based on user history and verification completeness. You ensure only legitimate users
102
+ can purchase tickets while maintaining a smooth user experience.""",
103
+ llm=llm,
104
+ verbose=True
105
+ )
106
+
107
+ @agent
108
+ def scalping_detection_agent(self) -> Agent:
109
+ return Agent(
110
+ role="Scalping Detection Analyst",
111
+ goal="Detect and prevent ticket scalping through behavioral analysis",
112
+ backstory="""You are a specialized analyst focused on identifying scalping patterns.
113
+ You analyze purchase velocity, IP addresses, buying patterns, and other behavioral
114
+ indicators to detect potential scalpers. Your expertise helps maintain fair ticket
115
+ distribution and prevents automated bot purchases.""",
116
+ llm=llm,
117
+ verbose=True
118
+ )
119
+
120
+ @agent
121
+ def dynamic_pricing_agent(self) -> Agent:
122
+ return Agent(
123
+ role="Dynamic Pricing Strategist",
124
+ goal="Calculate fair resale prices based on demand while preventing price gouging",
125
+ backstory="""You are an expert in market dynamics and pricing strategies. You analyze
126
+ demand levels, market conditions, and event popularity to recommend fair resale prices.
127
+ You balance market forces with consumer protection, ensuring prices reflect true demand
128
+ without enabling exploitative pricing.""",
129
+ llm=llm,
130
+ verbose=True
131
+ )
132
+
133
+ @agent
134
+ def resale_monitor_agent(self) -> Agent:
135
+ return Agent(
136
+ role="Resale Compliance Officer",
137
+ goal="Monitor and enforce resale policies to ensure fair ticket distribution",
138
+ backstory="""You are responsible for ensuring all ticket resales comply with platform
139
+ policies and local regulations. You monitor resale prices, frequency, and patterns to
140
+ prevent policy violations. Your work ensures the secondary ticket market remains fair
141
+ and accessible to genuine fans.""",
142
+ llm=llm,
143
+ verbose=True
144
+ )
145
+
146
+ @task
147
+ def verify_user_task(self) -> Task:
148
+ return Task(
149
+ description="""Verify the user with the following details:
150
+ - Name: {name}
151
+ - Email: {email}
152
+ - User ID: {user_id}
153
+
154
+ Perform KYC verification checks:
155
+ 1. Validate email format and domain
156
+ 2. Check if name appears legitimate
157
+ 3. Assign verification level (basic/standard/premium)
158
+ 4. Calculate risk score (0-1) based on user patterns
159
+ 5. Determine if user is verified for ticket purchase
160
+
161
+ Consider factors like email domain reputation, name consistency, and any red flags.""",
162
+ agent=self.user_verification_agent(),
163
+ expected_output="UserVerification model with complete verification details"
164
+ )
165
+
166
+ @task
167
+ def detect_scalping_task(self) -> Task:
168
+ return Task(
169
+ description="""Analyze user behavior for scalping indicators:
170
+ - User ID: {user_id}
171
+ - Current purchase attempt for event: {event_name}
172
+ - Ticket quantity requested: {ticket_quantity}
173
+
174
+ Check for scalping patterns:
175
+ 1. Purchase velocity (multiple purchases in short time)
176
+ 2. IP address duplication (multiple accounts from same IP)
177
+ 3. Unusual buying patterns
178
+ 4. Bot-like behavior indicators
179
+ 5. Historical resale frequency
180
+
181
+ Use the user's purchase history and behavioral data to determine scalping likelihood.""",
182
+ agent=self.scalping_detection_agent(),
183
+ expected_output="ScalpingDetection model with detection results and confidence score"
184
+ )
185
+
186
+ @task
187
+ def calculate_pricing_task(self) -> Task:
188
+ return Task(
189
+ description="""Calculate recommended resale price for:
190
+ - Event: {event_name}
191
+ - Original ticket price: ${original_price}
192
+ - Current demand level: {demand_level}
193
+ - Ticket type: {ticket_type}
194
+
195
+ Pricing guidelines:
196
+ - Low demand: Allow 10-20% below original price (acknowledge loss)
197
+ - Medium demand: Allow up to 25% markup
198
+ - High demand: Allow up to 50% markup (with profit margin note)
199
+
200
+ Consider market factors and ensure pricing remains fair while reflecting demand.""",
201
+ agent=self.dynamic_pricing_agent(),
202
+ expected_output="PricingRecommendation model with price calculations and justification"
203
+ )
204
+
205
+ @task
206
+ def monitor_compliance_task(self) -> Task:
207
+ return Task(
208
+ description="""Evaluate resale compliance for:
209
+ - User ID: {user_id}
210
+ - Proposed resale price: ${proposed_resale_price}
211
+ - Original price: ${original_price}
212
+ - User's resale history from scalping detection
213
+
214
+ Check against policies:
215
+ 1. Maximum 2x original price cap
216
+ 2. No more than 4 resales per month
217
+ 3. No bulk resales (>4 tickets at once)
218
+ 4. Cooling period between purchases and resales
219
+
220
+ Determine if resale should be allowed and provide recommendations.""",
221
+ agent=self.resale_monitor_agent(),
222
+ context=[self.detect_scalping_task(), self.calculate_pricing_task()],
223
+ expected_output="ResaleCompliance model with compliance decision and violations"
224
+ )
225
+
226
+ @task
227
+ def final_report_task(self) -> Task:
228
+ return Task(
229
+ description="""Create comprehensive system report combining all findings:
230
+ 1. User verification results
231
+ 2. Scalping detection analysis
232
+ 3. Pricing recommendations
233
+ 4. Compliance evaluation
234
+
235
+ Provide final decision on whether to:
236
+ - Allow ticket purchase
237
+ - Allow ticket resale
238
+ - Apply any restrictions
239
+ - Recommend specific actions
240
+
241
+ Ensure report is clear and actionable.""",
242
+ agent=self.resale_monitor_agent(),
243
+ context=[
244
+ self.verify_user_task(),
245
+ self.detect_scalping_task(),
246
+ self.calculate_pricing_task(),
247
+ self.monitor_compliance_task()
248
+ ],
249
+ expected_output="Complete TicketingSystemReport with all components and final decision"
250
+ )
251
+
252
+ @crew
253
+ def crew(self) -> Crew:
254
+ return Crew(
255
+ agents=self.agents,
256
+ tasks=self.tasks,
257
+ process=Process.sequential,
258
+ verbose=True
259
+ )
260
+
261
+ # ========== MAIN APPLICATION ==========
262
+ class AntiScalpingSystem:
263
+ def __init__(self):
264
+ self.crew_instance = AntiScalpingCrew()
265
+
266
+ def process_ticket_transaction(
267
+ self,
268
+ name: str,
269
+ email: str,
270
+ user_id: str,
271
+ event_name: str,
272
+ ticket_type: str,
273
+ ticket_quantity: int,
274
+ original_price: float,
275
+ demand_level: str,
276
+ proposed_resale_price: float
277
+ ) -> Dict[str, Any]:
278
+ """Process a ticket transaction through the anti-scalping system"""
279
+
280
+ # Simulate some purchase history for the user
281
+ purchase_count = mock_db.get_user_purchases(user_id)
282
+ mock_db.user_purchase_history[user_id] = purchase_count + 1
283
+
284
+ inputs = {
285
+ "name": name,
286
+ "email": email,
287
+ "user_id": user_id,
288
+ "event_name": event_name,
289
+ "ticket_type": ticket_type,
290
+ "ticket_quantity": ticket_quantity,
291
+ "original_price": original_price,
292
+ "demand_level": demand_level,
293
+ "proposed_resale_price": proposed_resale_price
294
+ }
295
+
296
+ try:
297
+ result = self.crew_instance.crew().kickoff(inputs=inputs)
298
+
299
+ # Parse the result and create a structured response
300
+ if hasattr(result, 'dict'):
301
+ return result.dict()
302
+ else:
303
+ # Create a mock response for demo purposes
304
+ return self._create_mock_response(inputs)
305
+ except Exception as e:
306
+ logger.error(f"Error processing transaction: {e}")
307
+ return self._create_mock_response(inputs)
308
+
309
+ def _create_mock_response(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
310
+ """Create a mock response for demo purposes"""
311
+ is_scalper = random.random() > 0.7
312
+ price_ratio = inputs["proposed_resale_price"] / inputs["original_price"]
313
+
314
+ return {
315
+ "verification": {
316
+ "user_id": inputs["user_id"],
317
+ "name": inputs["name"],
318
+ "email": inputs["email"],
319
+ "is_verified": not is_scalper,
320
+ "verification_level": "standard" if not is_scalper else "basic",
321
+ "risk_score": 0.3 if not is_scalper else 0.8
322
+ },
323
+ "scalping_detection": {
324
+ "is_scalper": is_scalper,
325
+ "confidence": 0.85 if is_scalper else 0.15,
326
+ "flags": ["rapid_purchases", "multiple_ips"] if is_scalper else [],
327
+ "purchase_velocity": random.randint(1, 10),
328
+ "ip_duplicates": random.randint(1, 5)
329
+ },
330
+ "pricing": {
331
+ "original_price": inputs["original_price"],
332
+ "recommended_resale_price": inputs["proposed_resale_price"],
333
+ "demand_level": inputs["demand_level"],
334
+ "price_adjustment_reason": f"Based on {inputs['demand_level']} demand",
335
+ "profit_margin": (price_ratio - 1) * 100 if price_ratio > 1 else None,
336
+ "loss_percentage": (1 - price_ratio) * 100 if price_ratio < 1 else None
337
+ },
338
+ "compliance": {
339
+ "is_compliant": price_ratio <= 2 and not is_scalper,
340
+ "violations": ["price_exceeds_2x"] if price_ratio > 2 else [],
341
+ "resale_allowed": price_ratio <= 2 and not is_scalper,
342
+ "max_allowed_price": inputs["original_price"] * 2,
343
+ "recommendation": "Proceed with resale" if price_ratio <= 2 and not is_scalper else "Block transaction"
344
+ },
345
+ "final_decision": "APPROVED" if price_ratio <= 2 and not is_scalper else "DENIED",
346
+ "action_items": [
347
+ "Process ticket resale" if price_ratio <= 2 and not is_scalper else "Block transaction",
348
+ "Monitor future activity" if is_scalper else "No additional action required"
349
+ ]
350
+ }
351
+
352
+ # ========== GRADIO INTERFACE ==========
353
+ def create_interface():
354
+ system = AntiScalpingSystem()
355
+
356
+ def process_transaction(
357
+ name, email, user_id, event_name, ticket_type,
358
+ ticket_quantity, original_price, demand_level, proposed_resale_price
359
+ ):
360
+ """Process the transaction and return formatted results"""
361
+
362
+ # Validate inputs
363
+ if not all([name, email, user_id, event_name]):
364
+ return "Please fill in all required fields"
365
+
366
+ try:
367
+ original_price = float(original_price)
368
+ proposed_resale_price = float(proposed_resale_price)
369
+ ticket_quantity = int(ticket_quantity)
370
+ except ValueError:
371
+ return "Please enter valid numbers for prices and quantity"
372
+
373
+ # Process through the system
374
+ result = system.process_ticket_transaction(
375
+ name=name,
376
+ email=email,
377
+ user_id=user_id,
378
+ event_name=event_name,
379
+ ticket_type=ticket_type,
380
+ ticket_quantity=ticket_quantity,
381
+ original_price=original_price,
382
+ demand_level=demand_level,
383
+ proposed_resale_price=proposed_resale_price
384
+ )
385
+
386
+ # Format the output
387
+ output = f"""
388
+ # 🎫 Anti-Scalping System Report
389
+
390
+ ## πŸ‘€ User Verification
391
+ - **User ID**: {result['verification']['user_id']}
392
+ - **Verified**: {'βœ… Yes' if result['verification']['is_verified'] else '❌ No'}
393
+ - **Risk Score**: {result['verification']['risk_score']:.2f}
394
+ - **Verification Level**: {result['verification']['verification_level']}
395
+
396
+ ## πŸ” Scalping Detection
397
+ - **Scalper Detected**: {'🚨 Yes' if result['scalping_detection']['is_scalper'] else 'βœ… No'}
398
+ - **Confidence**: {result['scalping_detection']['confidence']:.2%}
399
+ - **Purchase Velocity**: {result['scalping_detection']['purchase_velocity']} purchases/hour
400
+ - **IP Duplicates**: {result['scalping_detection']['ip_duplicates']}
401
+ - **Flags**: {', '.join(result['scalping_detection']['flags']) if result['scalping_detection']['flags'] else 'None'}
402
+
403
+ ## πŸ’° Pricing Analysis
404
+ - **Original Price**: ${result['pricing']['original_price']:.2f}
405
+ - **Proposed Resale**: ${result['pricing']['recommended_resale_price']:.2f}
406
+ - **Demand Level**: {result['pricing']['demand_level']}
407
+ - **Price Ratio**: {result['pricing']['recommended_resale_price']/result['pricing']['original_price']:.2f}x
408
+ """
409
+
410
+ if result['pricing'].get('profit_margin'):
411
+ output += f"- **Profit Margin**: {result['pricing']['profit_margin']:.1f}%\n"
412
+ elif result['pricing'].get('loss_percentage'):
413
+ output += f"- **Loss**: {result['pricing']['loss_percentage']:.1f}%\n"
414
+
415
+ output += f"""
416
+ ## βœ… Compliance Check
417
+ - **Compliant**: {'βœ… Yes' if result['compliance']['is_compliant'] else '❌ No'}
418
+ - **Resale Allowed**: {'βœ… Yes' if result['compliance']['resale_allowed'] else '❌ No'}
419
+ - **Max Allowed Price**: ${result['compliance']['max_allowed_price']:.2f}
420
+ - **Violations**: {', '.join(result['compliance']['violations']) if result['compliance']['violations'] else 'None'}
421
+
422
+ ## πŸ“‹ Final Decision: **{result['final_decision']}**
423
+
424
+ ### Action Items:
425
+ """
426
+ for action in result['action_items']:
427
+ output += f"- {action}\n"
428
+
429
+ return output
430
+
431
+ # Create Gradio interface
432
+ interface = gr.Interface(
433
+ fn=process_transaction,
434
+ inputs=[
435
+ gr.Textbox(label="Full Name", placeholder="John Doe"),
436
+ gr.Textbox(label="Email", placeholder="john@example.com"),
437
+ gr.Textbox(label="User ID", placeholder="USER123"),
438
+ gr.Textbox(label="Event Name", placeholder="Taylor Swift - Eras Tour"),
439
+ gr.Dropdown(
440
+ label="Ticket Type",
441
+ choices=["General Admission", "VIP", "Premium", "Standard"],
442
+ value="Standard"
443
+ ),
444
+ gr.Number(label="Ticket Quantity", value=1, minimum=1, maximum=10),
445
+ gr.Number(label="Original Ticket Price ($)", value=100),
446
+ gr.Radio(
447
+ label="Current Demand Level",
448
+ choices=["low", "medium", "high"],
449
+ value="medium"
450
+ ),
451
+ gr.Number(label="Proposed Resale Price ($)", value=150)
452
+ ],
453
+ outputs=gr.Markdown(),
454
+ title="🎫 Anti-Scalping Ticketing System",
455
+ description="""
456
+ This AI-powered system helps prevent ticket scalping by:
457
+ - Verifying user identity and history
458
+ - Detecting scalping patterns and behaviors
459
+ - Recommending fair resale prices based on demand
460
+ - Ensuring compliance with anti-scalping policies
461
+
462
+ Enter the ticket transaction details below to see if it should be approved.
463
+ """,
464
+ examples=[
465
+ ["John Smith", "john@gmail.com", "USER001", "Taylor Swift - Eras Tour", "VIP", 2, 500, "high", 750],
466
+ ["Jane Doe", "jane@company.com", "USER002", "NBA Finals Game 7", "Premium", 4, 300, "high", 1200],
467
+ ["Bob Wilson", "bob@email.com", "USER003", "Local Concert", "General Admission", 1, 50, "low", 40],
468
+ ],
469
+ theme=gr.themes.Soft()
470
+ )
471
+
472
+ return interface
473
+
474
+ # Main execution
475
+ if __name__ == "__main__":
476
+ interface = create_interface()
477
+ interface.launch(share=True)