cryptopond commited on
Commit
aae34a7
·
1 Parent(s): ad025b2

feat: add demo app

Browse files
Files changed (1) hide show
  1. app.py +153 -0
app.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+ from typing import List, Dict
4
+ import os
5
+
6
+ API_URL = os.getenv('POND_API_URL')
7
+ API_TOKEN = os.getenv('POND_API_TOKEN')
8
+
9
+ st.title('🌊 Pond Model Demo')
10
+
11
+ st.sidebar.header('Model Selection')
12
+ model_info = {
13
+ 1: {
14
+ 'name': 'Security Model',
15
+ 'description': 'Analyze whether an account is secure by detecting and examining malicious activities within complex blockchain data structures.'
16
+ },
17
+ 2: {
18
+ 'name': 'Sybil Model',
19
+ 'description': 'An model aims to detect on-chain "Sybil Attacks"'
20
+ },
21
+ 3: {
22
+ 'name': 'ZORA NFT Recommendation',
23
+ 'description': 'On-Chain Recommendation System: Making Discoveries & Spread Easier for Everyone'
24
+ }
25
+ }
26
+
27
+ selected_model = st.sidebar.selectbox(
28
+ 'Choose a model',
29
+ list(model_info.keys()),
30
+ format_func=lambda x: model_info[x]['name']
31
+ )
32
+
33
+ # Show model description
34
+ st.markdown(f"### {model_info[selected_model]['name']}")
35
+ st.markdown(model_info[selected_model]['description'])
36
+
37
+ # Input section
38
+ st.header('Input Wallet Addresses')
39
+ wallet_input = st.text_area(
40
+ 'Enter wallet addresses (one per line)',
41
+ height=100,
42
+ help='Enter wallet addresses, one per line'
43
+ )
44
+
45
+ def predict(addresses: List[str], model_id: int) -> Dict:
46
+ """
47
+ Make prediction using the Pond API
48
+ """
49
+ if not API_URL:
50
+ st.error('API URL is not configured. Please set POND_API_URL environment variable.')
51
+ return None
52
+
53
+ headers = {
54
+ "Content-Type": "application/json"
55
+ }
56
+
57
+ try:
58
+ payload = {
59
+ "req_type": "1",
60
+ "access_token": API_TOKEN,
61
+ "input_keys": addresses,
62
+ "model_id": model_id
63
+ }
64
+
65
+ headers = {
66
+ "Content-Type": "application/json"
67
+ }
68
+
69
+ # Make the API call with explicit method
70
+ session = requests.Session()
71
+ req = requests.Request('POST',
72
+ API_URL,
73
+ json=payload,
74
+ headers=headers)
75
+ prepped = req.prepare()
76
+
77
+ response = session.send(prepped,
78
+ allow_redirects=True)
79
+
80
+ # Check response
81
+ if response.status_code != 200:
82
+ st.error(f"API Error: {response.status_code}")
83
+ st.error(f"Response: {response.text}")
84
+ return None
85
+
86
+ return response.json()
87
+ except Exception as e:
88
+ st.error(f"Error making prediction: {str(e)}")
89
+ return None
90
+
91
+ def display_results(response: Dict, model_id: int):
92
+ """
93
+ Display the results based on model type
94
+ """
95
+ if not response or 'resp_items' not in response:
96
+ return
97
+
98
+ if model_id in [1, 2]: # Security and Sybil models
99
+ st.header('Results')
100
+ for item in response['resp_items']:
101
+ score = item['score']
102
+ address = item['input_key']
103
+
104
+ # Create color coding based on score
105
+ if score < 0.3:
106
+ color = 'green'
107
+ elif score < 0.7:
108
+ color = 'orange'
109
+ else:
110
+ color = 'red'
111
+
112
+ st.markdown(f"""
113
+ **Address**: `{address}`
114
+ **Score**: <span style='color: {color}'>{score:.4f}</span>
115
+ """, unsafe_allow_html=True)
116
+ st.markdown("")
117
+
118
+ elif model_id == 3: # NFT Recommendation model
119
+ st.header('NFT Recommendations')
120
+ for item in response['resp_items']:
121
+ address = item['input_key']
122
+ st.subheader(f'Recommendations for: `{address}`')
123
+
124
+ if 'candidates' in item:
125
+ for idx, candidate in enumerate(item['candidates'][:5], 1):
126
+ st.markdown(f"""
127
+ **{idx}. NFT ID**: `{candidate['item_id']}`
128
+ **Score**: {candidate['score']:.4f}
129
+ """)
130
+ st.markdown("")
131
+
132
+ # Process button
133
+ if st.button('Get Predictions'):
134
+ if wallet_input:
135
+ # Process input addresses
136
+ addresses = [addr.strip() for addr in wallet_input.split('\n') if addr.strip()]
137
+
138
+ # Validate addresses
139
+ valid_addresses = [addr for addr in addresses if addr.startswith('0x')]
140
+
141
+ if not valid_addresses:
142
+ st.error('Please enter valid Ethereum addresses (starting with 0x)')
143
+ else:
144
+ with st.spinner('Making predictions...'):
145
+ response = predict(valid_addresses, selected_model)
146
+ if response:
147
+ display_results(response, selected_model)
148
+ else:
149
+ st.warning('Please enter at least one wallet address')
150
+
151
+ # Footer
152
+ st.markdown("---")
153
+ st.markdown("ℹ️ This is a demo interface for the Pond Model API. For production use, please refer to the official documentation.")