Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,147 +1,107 @@
|
|
1 |
-
import io
|
2 |
-
import random
|
3 |
-
from typing import List, Tuple
|
4 |
-
|
5 |
-
import aiohttp
|
6 |
import panel as pn
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
pn.extension(design="bootstrap", sizing_mode="stretch_width")
|
11 |
-
|
12 |
-
ICON_URLS = {
|
13 |
-
"brand-github": "https://github.com/holoviz/panel",
|
14 |
-
"brand-twitter": "https://twitter.com/Panel_Org",
|
15 |
-
"brand-linkedin": "https://www.linkedin.com/company/panel-org",
|
16 |
-
"message-circle": "https://discourse.holoviz.org/",
|
17 |
-
"brand-discord": "https://discord.gg/AXRHnJU6sP",
|
18 |
-
}
|
19 |
-
|
20 |
-
|
21 |
-
async def random_url(_):
|
22 |
-
pet = random.choice(["cat", "dog"])
|
23 |
-
api_url = f"https://api.the{pet}api.com/v1/images/search"
|
24 |
-
async with aiohttp.ClientSession() as session:
|
25 |
-
async with session.get(api_url) as resp:
|
26 |
-
return (await resp.json())[0]["url"]
|
27 |
-
|
28 |
-
|
29 |
-
@pn.cache
|
30 |
-
def load_processor_model(
|
31 |
-
processor_name: str, model_name: str
|
32 |
-
) -> Tuple[CLIPProcessor, CLIPModel]:
|
33 |
-
processor = CLIPProcessor.from_pretrained(processor_name)
|
34 |
-
model = CLIPModel.from_pretrained(model_name)
|
35 |
-
return processor, model
|
36 |
-
|
37 |
-
|
38 |
-
async def open_image_url(image_url: str) -> Image:
|
39 |
-
async with aiohttp.ClientSession() as session:
|
40 |
-
async with session.get(image_url) as resp:
|
41 |
-
return Image.open(io.BytesIO(await resp.read()))
|
42 |
-
|
43 |
-
|
44 |
-
def get_similarity_scores(class_items: List[str], image: Image) -> List[float]:
|
45 |
-
processor, model = load_processor_model(
|
46 |
-
"openai/clip-vit-base-patch32", "openai/clip-vit-base-patch32"
|
47 |
-
)
|
48 |
-
inputs = processor(
|
49 |
-
text=class_items,
|
50 |
-
images=[image],
|
51 |
-
return_tensors="pt", # pytorch tensors
|
52 |
-
)
|
53 |
-
outputs = model(**inputs)
|
54 |
-
logits_per_image = outputs.logits_per_image
|
55 |
-
class_likelihoods = logits_per_image.softmax(dim=1).detach().numpy()
|
56 |
-
return class_likelihoods[0]
|
57 |
|
58 |
-
|
59 |
-
async def process_inputs(class_names: List[str], image_url: str):
|
60 |
-
"""
|
61 |
-
High level function that takes in the user inputs and returns the
|
62 |
-
classification results as panel objects.
|
63 |
-
"""
|
64 |
-
try:
|
65 |
-
main.disabled = True
|
66 |
-
if not image_url:
|
67 |
-
yield "##### ⚠️ Provide an image URL"
|
68 |
-
return
|
69 |
-
|
70 |
-
yield "##### ⚙ Fetching image and running model..."
|
71 |
-
try:
|
72 |
-
pil_img = await open_image_url(image_url)
|
73 |
-
img = pn.pane.Image(pil_img, height=400, align="center")
|
74 |
-
except Exception as e:
|
75 |
-
yield f"##### 😔 Something went wrong, please try a different URL!"
|
76 |
-
return
|
77 |
|
78 |
-
|
79 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
|
81 |
-
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
)
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
)
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
for icon, url in ICON_URLS.items():
|
129 |
-
href_button = pn.widgets.Button(icon=icon, width=35, height=35)
|
130 |
-
href_button.js_on_click(code=f"window.open('{url}')")
|
131 |
-
footer_row.append(href_button)
|
132 |
-
footer_row.append(pn.Spacer())
|
133 |
-
|
134 |
-
# create dashboard
|
135 |
-
main = pn.WidgetBox(
|
136 |
-
input_widgets,
|
137 |
-
interactive_result,
|
138 |
-
footer_row,
|
139 |
-
)
|
140 |
-
|
141 |
-
title = "Panel Demo - Image Classification"
|
142 |
-
pn.template.BootstrapTemplate(
|
143 |
-
title=title,
|
144 |
-
main=main,
|
145 |
-
main_max_width="min(50%, 698px)",
|
146 |
-
header_background="#F08080",
|
147 |
-
).servable(title=title)
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import panel as pn
|
2 |
+
import plotly.graph_objects as go
|
3 |
+
pn.extension('plotly')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
+
def create_sankey(player='Human', initial_decision='Cooperate'):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
7 |
+
source = [0, 0, 1, 1]
|
8 |
+
target = [2, 3, 2, 3]
|
9 |
+
|
10 |
+
# based on the stats above and the current type of player, we get the following value arrays.
|
11 |
+
if player == 'Human':
|
12 |
+
if initial_decision == 'Cooperate':
|
13 |
+
value = [12035, 3173, 4963, 8440]
|
14 |
+
else:
|
15 |
+
value = [3821, 7686, 3635, 10584]
|
16 |
+
elif player == 'ChatGPT-4':
|
17 |
+
if initial_decision == 'Cooperate':
|
18 |
+
value = [29, 0, 0, 1]
|
19 |
+
else:
|
20 |
+
value = [0, 26, 1, 3]
|
21 |
+
else: # ChatGPT-3
|
22 |
+
if initial_decision == 'Cooperate':
|
23 |
+
value = [21, 3, 3, 3]
|
24 |
+
else:
|
25 |
+
value = [7, 15, 4, 4]
|
26 |
|
27 |
+
link_percentages = [value[0]/(value[0]+value[1])*100, value[1]/(value[0]+value[1])*100, value[2]/(value[2]+value[3])*100, value[3]/(value[2]+value[3])*100]
|
28 |
+
node_percentages = [(value[0]+value[1])/sum(value)*100, (value[2]+value[3])/sum(value)*100, (value[0]+value[2])/sum(value)*100, (value[1]+value[3])/sum(value)*100]
|
29 |
+
node_customdata = [("Cooperate in Round 1", node_percentages[0]), ("Defect in Round 1", node_percentages[1]),
|
30 |
+
("Cooperate in Round 2", node_percentages[2]), ("Defect in Round 2", node_percentages[3])]
|
31 |
+
|
32 |
+
# Create sankey diagram
|
33 |
+
fig = go.Figure(data=[go.Sankey(
|
34 |
+
node = dict(
|
35 |
+
pad = 15,
|
36 |
+
thickness = 20,
|
37 |
+
label = ["Cooperate", "Defect", "Cooperate", "Defect"],
|
38 |
+
color = ["#B0C5A4", "#D37676", "#B0C5A4", "#D37676"],
|
39 |
+
# customdata = ["Cooperate in Round 1", "Defect in Round 1", "Cooperate in Round 2", "Defect in Round 2"],
|
40 |
+
customdata = node_customdata,
|
41 |
+
hovertemplate='%{value:.0f} players (%{customdata[1]:.02f}%) chose to %{customdata[0]}<extra></extra>',
|
42 |
+
),
|
43 |
+
link = dict(
|
44 |
+
source = source,
|
45 |
+
target = target,
|
46 |
+
value = value,
|
47 |
+
customdata = link_percentages,
|
48 |
+
hovertemplate='Of the %{source.value} players who chose to <br />'+
|
49 |
+
'%{source.customdata[0]}, %{value:.0f} (%{customdata:.02f}%) <br />'+
|
50 |
+
'chose to %{target.customdata[0]}<extra></extra>',
|
51 |
+
color = ["#B0C5A4", "#B0C5A4", "#D37676", "#D37676"],
|
52 |
+
),
|
53 |
+
)])
|
54 |
+
|
55 |
+
annotations=[
|
56 |
+
dict(x=0, y=-0.2, xref='paper', yref='paper', showarrow=False,
|
57 |
+
text="Round 1"),
|
58 |
+
dict(x=0.5, y=-0.2, xref='paper', yref='paper', showarrow=False,
|
59 |
+
text="Other Player Defects in Round 1" if initial_decision == "Defect" else "Other Player Cooperates in Round 1", font=dict(size=14, color='grey')),
|
60 |
+
dict(x=1, y=-0.2, xref='paper', yref='paper', showarrow=False,
|
61 |
+
text="2")
|
62 |
+
]
|
63 |
|
64 |
+
fig.update_layout(hovermode='x', title="Prisoner's Dilemma Decision Flows", annotations=annotations, font_size=14, title_x=0.5)
|
65 |
+
return fig
|
66 |
+
|
67 |
+
|
68 |
+
# Interactive widgets for filtering
|
69 |
+
select_player = pn.widgets.Select(name='Type of Player', options=['Human', 'ChatGPT-4', 'ChatGPT-3'])
|
70 |
+
select_decision = pn.widgets.Select(name='Round 1 Decision by Other Player', options=['Cooperate', 'Defect'])
|
71 |
+
|
72 |
+
# Textual explanation of each chart based on type of player and round 1 decision (should have 6 scenarios!)
|
73 |
+
# https://panel.holoviz.org/reference/widgets/StaticText.html
|
74 |
+
|
75 |
+
|
76 |
+
# Dynamic binding of the sankey diagram function to the widgets' values
|
77 |
+
@pn.depends(select_player.param.value, select_decision.param.value)
|
78 |
+
def interactive_sankey(chatgpt_version, initial_decision):
|
79 |
+
return create_sankey(chatgpt_version, initial_decision)
|
80 |
+
|
81 |
+
@pn.depends(select_player.param.value, select_decision.param.value)
|
82 |
+
def setup_description(chatgpt_version, initial_decision):
|
83 |
+
if chatgpt_version == 'Human':
|
84 |
+
if initial_decision == 'Cooperate':
|
85 |
+
scenario_desc="Here's what happens <b>in reality</b> (for us humans) when the other player <b>cooperates</b> in Round 1! We can see that about 50% of the people start on either side of the coin (cooperate or defect) and then the numbers lean more heavily (around 60%) onto the cooperate side by Round 2. This shows that humans would more naturally lean towards cooperation if the other player does the same. Check out what happens when the other player defects in Round 1 by selecting the <b>Defect</b> option above!"
|
86 |
+
else:
|
87 |
+
scenario_desc="Here's what happens <b>for humans</b> when the other player <b>defects</b> in Round 1! Just like in the first scenario (other player cooperates) we see that about 50% of the people start on either side of the coin (cooperate or defect). This time, however, the numbers lean MUCH more heavily (around 70%) onto the defect side by Round 2 (especially coming from those who initially cooperated). This shows that humans would more naturally lean towards defecting (moreso than cooperation) if the other player does the same. Now check out how AI would make this decision by selecting either <b>ChatGPT-3 or ChatGPT-4</b> in the options above!"
|
88 |
+
elif chatgpt_version == 'ChatGPT-4':
|
89 |
+
if initial_decision == 'Cooperate':
|
90 |
+
scenario_desc="Here's a peek into <b>ChatGPT-4's</b> world when faced with a <b>cooperating</b> partner in Round 1! ChatGPT-4 shows a strong tendency towards reciprocating cooperation, with ALL of the players who decided to cooperate in the first place (95%) choosing to cooperate again. It appears to demonstrate a high capacity for trust and cooperative behavior, mirroring an ideal strategic participant who values mutual benefit over individual gain. Curious about how ChatGPT-4 reacts to a defect? Switch to the <b>Defect</b> option above to explore further!"
|
91 |
+
else:
|
92 |
+
scenario_desc="Exploring <b>ChatGPT-4's</b> strategy when the other player decides to <b>defect</b> in Round 1 unveils an interesting approach! Just like humans, when ChatGPT-4 is 'betrayed' in a sense, it goes HEAVILY into defecting (with a total table turning 96% defecting in the second round). It's an intriguing stance that differs only in terms of extremeties compared to human reaction patterns. Now, check how <b>ChatGPT-3</b> handles this by selecting it in the options above!"
|
93 |
+
else:
|
94 |
+
if initial_decision == 'Cooperate':
|
95 |
+
scenario_desc="Diving into <b>ChatGPT-3's</b> choices when the game starts with <b>cooperation</b>, it shows something in between both humans and ChatGPT-4; the exact same amount of responses (80%) end up in cooperation despite there having been some players changing to defecting and some initial defectors changing to cooperation. It is fascinating to see how this earlier version of ChatGPT balances trust and strategy. Want to see what happens when the start is less friendly? Choose the <b>Defect</b> option to discover."
|
96 |
+
else:
|
97 |
+
scenario_desc="When the initial move is to <b>defect</b>, <b>ChatGPT-3</b> displays a mixed strategy (again, in between humans and ChatGPT-4). Despite starting with more on the cooperation side (~70%), they end up with the majority of players defecting by the second round (63% - which is much closer to the humans which were at 70%). This variance from ChatGPT-4's strategy offers a glimpse into the evolution and differences in approach between the two AI versions. Toggle to <b>ChatGPT-4 or Human</b> to compare both of these to what you found out about ChatGPT-3!"
|
98 |
+
|
99 |
+
static_text = pn.widgets.StaticText(name='Description', value=f"{scenario_desc}")
|
100 |
+
static_text.value = f"{scenario_desc}"
|
101 |
+
return static_text
|
102 |
+
|
103 |
+
|
104 |
+
# Layout
|
105 |
+
layout = pn.Column(pn.Row(select_player, select_decision), interactive_sankey, setup_description)
|
106 |
+
|
107 |
+
layout.servable()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|