gmedin commited on
Commit
7d63ff8
·
verified ·
1 Parent(s): 13ffb43

connect to pw-recsys to get rankings for user

Browse files
Files changed (1) hide show
  1. app.py +90 -16
app.py CHANGED
@@ -4,6 +4,8 @@ from pyvis.network import Network
4
  import pickle
5
  import math
6
  import random
 
 
7
 
8
  # Dictionary to map brands to their respective pickle files
9
  BRAND_GRAPHS = {
@@ -13,18 +15,18 @@ BRAND_GRAPHS = {
13
  'guitareo': 'guitareo_pop_items_labels.pkl'
14
  }
15
 
 
 
 
 
 
 
16
  @st.cache_resource
17
  def load_graph(brand):
18
- """
19
- Load the graph for the selected brand.
20
- """
21
  with open(BRAND_GRAPHS[brand], 'rb') as f:
22
  return pickle.load(f)
23
 
24
  def filter_graph(graph, node_threshold=10, edge_threshold=5):
25
- """
26
- Filters the graph to include only popular nodes and edges.
27
- """
28
  popular_nodes = [
29
  node for node in graph.nodes
30
  if graph.degree(node) >= node_threshold
@@ -38,7 +40,49 @@ def filter_graph(graph, node_threshold=10, edge_threshold=5):
38
 
39
  return filtered_graph
40
 
41
- def dynamic_visualize_graph(graph, start_node, layers=3, top_k=5, show_titles=False):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  net = Network(notebook=False, width="100%", height="600px", directed=True)
43
  net.set_options("""
44
  var options = {
@@ -55,18 +99,27 @@ def dynamic_visualize_graph(graph, start_node, layers=3, top_k=5, show_titles=Fa
55
  added_edges = set()
56
  current_nodes = [int(start_node)]
57
 
 
 
58
  # Add the starting node, color it red, and include a tooltip
59
  start_title = graph.nodes[int(start_node)].get('title', 'No title available')
60
  start_in_degree = graph.in_degree(int(start_node))
61
  start_out_degree = graph.out_degree(int(start_node))
62
  start_node_size = (start_in_degree + start_out_degree) * 0.15
63
- label = str(start_node) if not show_titles else f"{str(start_node)}: {start_title[:15]}..." # Adjust title length
 
 
 
 
 
64
  net.add_node(
65
  int(start_node),
66
  label=label,
67
- color="darkblue",
68
- title=f"{start_title} In-degree: {start_in_degree}, Out-degree: {start_out_degree}",
69
- size=start_node_size
 
 
70
  )
71
  visited_nodes.add(int(start_node))
72
 
@@ -85,15 +138,24 @@ def dynamic_visualize_graph(graph, start_node, layers=3, top_k=5, show_titles=Fa
85
  neighbor_in_degree = graph.in_degree(neighbor)
86
  neighbor_out_degree = graph.out_degree(neighbor)
87
  neighbor_size = (neighbor_in_degree + neighbor_out_degree) * 0.15
 
 
88
  node_color = 'red' if neighbor_in_degree > neighbor_out_degree * 1.5 else \
89
- 'green' if neighbor_out_degree > neighbor_in_degree * 1.5 else 'lightblue'
 
 
 
 
 
90
  label = str(neighbor) if not show_titles else f"{str(neighbor)}: {neighbor_title[:15]}..."
91
  net.add_node(
92
  neighbor,
93
  label=label,
94
- title=f"{neighbor_title} In-degree: {neighbor_in_degree}, Out-degree: {neighbor_out_degree}",
95
  size=neighbor_size,
96
- color=node_color
 
 
97
  )
98
  edge = (node, neighbor)
99
  if edge not in added_edges:
@@ -109,7 +171,7 @@ def dynamic_visualize_graph(graph, start_node, layers=3, top_k=5, show_titles=Fa
109
  st.components.v1.html(html_content, height=600, scrolling=False)
110
 
111
 
112
- st.title("Popular Path Expansion")
113
 
114
  # Brand Selection
115
  selected_brand = st.selectbox("Select a brand:", options=list(BRAND_GRAPHS.keys()))
@@ -136,6 +198,10 @@ start_node = st.number_input(
136
  step=1
137
  )
138
 
 
 
 
 
139
  # Toggle for showing content titles
140
  show_titles = st.checkbox("Show content titles", value=False)
141
 
@@ -144,11 +210,19 @@ node_degree_threshold = 1
144
  edge_weight_threshold = 1
145
  G_filtered = filter_graph(G, node_threshold=node_degree_threshold, edge_threshold=edge_weight_threshold)
146
 
 
 
 
 
 
 
 
 
147
  layers = st.slider("Depth to explore:", 1, 6, value=3)
148
  top_k = st.slider("Branching factor (per node):", 1, 6, value=3)
149
 
150
  if st.button("Expand Graph"):
151
  if start_node in G_filtered:
152
- dynamic_visualize_graph(G_filtered, start_node, layers=layers, top_k=top_k, show_titles=show_titles)
153
  else:
154
  st.error("The starting node is not in the graph!")
 
4
  import pickle
5
  import math
6
  import random
7
+ import requests
8
+ import os
9
 
10
  # Dictionary to map brands to their respective pickle files
11
  BRAND_GRAPHS = {
 
15
  'guitareo': 'guitareo_pop_items_labels.pkl'
16
  }
17
 
18
+ # API Authorization Token
19
+ AUTH_TOKEN = os.getenv('HF_TOKEN')
20
+
21
+ API_URL = "https://MusoraProductDepartment-PWGenerator.hf.space/rank_items/"
22
+
23
+
24
  @st.cache_resource
25
  def load_graph(brand):
 
 
 
26
  with open(BRAND_GRAPHS[brand], 'rb') as f:
27
  return pickle.load(f)
28
 
29
  def filter_graph(graph, node_threshold=10, edge_threshold=5):
 
 
 
30
  popular_nodes = [
31
  node for node in graph.nodes
32
  if graph.degree(node) >= node_threshold
 
40
 
41
  return filtered_graph
42
 
43
+ def get_rankings_from_api(brand, user_id, content_ids):
44
+ """
45
+ Call the rank_items API to fetch rankings for the given user and content IDs.
46
+ """
47
+ try:
48
+ payload = {
49
+ "brand": brand.upper(),
50
+ "user_id": user_id,
51
+ "content_ids": content_ids
52
+ }
53
+ headers = {
54
+ "Authorization": f"Bearer {AUTH_TOKEN}",
55
+ "accept": "application/json",
56
+ "Content-Type": "application/json"
57
+ }
58
+ response = requests.post(API_URL, json=payload, headers=headers)
59
+ response.raise_for_status()
60
+ rankings = response.json()
61
+ return rankings
62
+ except Exception as e:
63
+ st.error(f"Error calling rank_items API: {e}")
64
+ return {}
65
+
66
+
67
+ def rank_to_color(rank, max_rank):
68
+ """
69
+ Map a rank to a grayscale color, where dark gray indicates high relevance (low rank),
70
+ and light gray indicates low relevance (high rank).
71
+
72
+ Parameters:
73
+ rank (int): The rank of the item.
74
+ max_rank (int): The maximum rank (for normalizing the gradient).
75
+
76
+ Returns:
77
+ str: Hex color code for the grayscale shade.
78
+ """
79
+ if rank > max_rank: # Handle items without ranking
80
+ return "#E8E8E8" # Very light gray for unranked items
81
+ intensity = int(55 + (rank / max_rank) * 200) # Scale intensity (darker for lower ranks)
82
+ return f"rgb({intensity}, {intensity}, {intensity})" # Grayscale
83
+
84
+
85
+ def dynamic_visualize_graph(graph, start_node, layers=3, top_k=5, show_titles=False, rankings=None):
86
  net = Network(notebook=False, width="100%", height="600px", directed=True)
87
  net.set_options("""
88
  var options = {
 
99
  added_edges = set()
100
  current_nodes = [int(start_node)]
101
 
102
+ max_rank = len(rankings) if rankings else 0
103
+
104
  # Add the starting node, color it red, and include a tooltip
105
  start_title = graph.nodes[int(start_node)].get('title', 'No title available')
106
  start_in_degree = graph.in_degree(int(start_node))
107
  start_out_degree = graph.out_degree(int(start_node))
108
  start_node_size = (start_in_degree + start_out_degree) * 0.15
109
+ start_rank = rankings.index(int(start_node)) if rankings and int(start_node) in rankings else max_rank + 1
110
+ if rankings:
111
+ start_border_color = rank_to_color(start_rank, max_rank)
112
+ else:
113
+ start_border_color = 'darkblue'
114
+ label = str(start_node) if not show_titles else f"{str(start_node)}: {start_title[:15]}..."
115
  net.add_node(
116
  int(start_node),
117
  label=label,
118
+ color={"background": "darkblue", "border": start_border_color},
119
+ title=f"{start_title}, In-degree: {start_in_degree}, Out-degree: {start_out_degree}, Rank: {start_rank}",
120
+ size=start_node_size,
121
+ borderWidth=3,
122
+ borderWidthSelected=6
123
  )
124
  visited_nodes.add(int(start_node))
125
 
 
138
  neighbor_in_degree = graph.in_degree(neighbor)
139
  neighbor_out_degree = graph.out_degree(neighbor)
140
  neighbor_size = (neighbor_in_degree + neighbor_out_degree) * 0.15
141
+ neighbor_rank = rankings.index(neighbor) if rankings and neighbor in rankings else max_rank + 1
142
+
143
  node_color = 'red' if neighbor_in_degree > neighbor_out_degree * 1.5 else \
144
+ 'green' if neighbor_out_degree > neighbor_in_degree * 1.5 else 'lightblue'
145
+ if rankings:
146
+ neighbor_border_color = rank_to_color(neighbor_rank, max_rank)
147
+ else:
148
+ neighbor_border_color = node_color
149
+
150
  label = str(neighbor) if not show_titles else f"{str(neighbor)}: {neighbor_title[:15]}..."
151
  net.add_node(
152
  neighbor,
153
  label=label,
154
+ title=f"{neighbor_title}, In-degree: {neighbor_in_degree}, Out-degree: {neighbor_out_degree}, Rank: {neighbor_rank}",
155
  size=neighbor_size,
156
+ color={"background": node_color, "border": neighbor_border_color},
157
+ borderWidth=3,
158
+ borderWidthSelected=6
159
  )
160
  edge = (node, neighbor)
161
  if edge not in added_edges:
 
171
  st.components.v1.html(html_content, height=600, scrolling=False)
172
 
173
 
174
+ st.title("Popular Path Expansion + Personalization")
175
 
176
  # Brand Selection
177
  selected_brand = st.selectbox("Select a brand:", options=list(BRAND_GRAPHS.keys()))
 
198
  step=1
199
  )
200
 
201
+ # Input: Student ID
202
+ student_id = st.text_input("Enter a student ID (optional):", value="")
203
+
204
+
205
  # Toggle for showing content titles
206
  show_titles = st.checkbox("Show content titles", value=False)
207
 
 
210
  edge_weight_threshold = 1
211
  G_filtered = filter_graph(G, node_threshold=node_degree_threshold, edge_threshold=edge_weight_threshold)
212
 
213
+ # Fetch rankings if student ID is provided
214
+ rankings = {}
215
+ if student_id:
216
+ content_ids = list(G_filtered.nodes)
217
+ rankings = get_rankings_from_api(selected_brand, int(student_id), content_ids)
218
+ if rankings:
219
+ rankings = rankings['ranked_content_ids']
220
+ #print(rankings)
221
  layers = st.slider("Depth to explore:", 1, 6, value=3)
222
  top_k = st.slider("Branching factor (per node):", 1, 6, value=3)
223
 
224
  if st.button("Expand Graph"):
225
  if start_node in G_filtered:
226
+ dynamic_visualize_graph(G_filtered, start_node, layers=layers, top_k=top_k, show_titles=show_titles, rankings=rankings)
227
  else:
228
  st.error("The starting node is not in the graph!")