Spaces:
Runtime error
Runtime error
from dash import Dash, dcc, html, Input, Output, State | |
import dash.dependencies as dd | |
import plotly.express as px | |
import pandas as pd | |
# Load DataFrame from CSV | |
df_result_bad_distil_2 = df = pd.read_csv( | |
"hf://datasets/Jbddai/customer_reviews/bad_distil_2_with_cluster_labels_cleaned_company.csv" | |
) | |
df_result_good_distil_2 = df = pd.read_csv( | |
"hf://datasets/Jbddai/customer_reviews/good_distil_2_with_cluster_labels_cleaned_company.csv" | |
) | |
def preprocess_data_for_slider_marks(df): | |
min_label = df["labels"].min() | |
max_label = df["labels"].max() | |
min_cluster_rank = df["cluster_rank"].min() | |
max_cluster_rank = df["cluster_rank"].max() | |
label_marks = {i: str(i + 1) for i in range(min_label, max_label + 1, 10)} | |
cluster_rank_marks = {i: str(i + 1) for i in range(min_cluster_rank, max_cluster_rank + 1, 10)} | |
return label_marks, min_label, max_label, cluster_rank_marks, min_cluster_rank, max_cluster_rank | |
label_marks, min_label, max_label, cluster_rank_marks, min_cluster_rank, max_cluster_rank = ( | |
preprocess_data_for_slider_marks(df_result_good_distil_2) | |
) | |
sentiment_options = [ | |
{"label": "gut", "value": "gut"}, | |
{"label": "schlecht", "value": "schlecht"}, | |
] | |
app = Dash(__name__) | |
app.layout = html.Div( | |
[ | |
html.Div( | |
[ | |
html.H4("Interactive Plot of Customer Reviews"), | |
html.Div( | |
[ | |
html.P("Select sentiment:"), | |
dcc.Dropdown( | |
id="sentiment-dropdown", | |
options=sentiment_options, | |
value="gut", | |
style={"width": "50%", "margin": "auto"}, | |
clearable=False, | |
multi=False, | |
), | |
], | |
style={"width": "50%", "margin": "auto"}, | |
), | |
html.Div( | |
[ | |
html.P("Select range of labels:"), | |
dcc.RangeSlider( | |
id="label-range-slider", | |
min=df_result_good_distil_2["labels"].min(), | |
max=df_result_good_distil_2["labels"].max(), | |
step=1, | |
value=[ | |
df_result_good_distil_2["labels"].min(), | |
df_result_good_distil_2["labels"].max(), | |
], | |
marks={ | |
i: str(i + 1) | |
for i in range( | |
df_result_good_distil_2["labels"].min(), | |
df_result_good_distil_2["labels"].max() + 1, | |
10, | |
) | |
}, | |
tooltip={"always_visible": True, "placement": "bottom"}, | |
), | |
html.Button("Reset Range", id="reset-button", n_clicks=0), | |
], | |
style={"width": "50%", "margin": "auto"}, | |
), | |
html.Div( | |
[ | |
html.P("Select range of cluster by rank/popularity (by number of reviews descending):"), | |
dcc.RangeSlider( | |
id="cluster-rank-slider", | |
min=df_result_good_distil_2["cluster_rank"].min(), | |
max=df_result_good_distil_2["cluster_rank"].max(), | |
step=1, | |
value=[ | |
df_result_good_distil_2["cluster_rank"].min(), | |
df_result_good_distil_2["cluster_rank"].max(), | |
], | |
marks={ | |
i: str(i + 1) | |
for i in range( | |
df_result_good_distil_2["cluster_rank"].min(), | |
df_result_good_distil_2["cluster_rank"].max() + 1, | |
10, | |
) | |
}, | |
tooltip={"always_visible": True, "placement": "bottom"}, | |
), | |
html.Button("Reset Cluster Rank", id="reset-cluster-button", n_clicks=0), | |
], | |
style={"width": "50%", "margin": "auto"}, | |
), | |
html.Div( | |
[ | |
html.P("Show Cluster Labels:"), | |
dcc.Checklist( | |
id="show-cluster-labels", | |
options=[{"label": "Show", "value": "on"}], | |
value=["off"], | |
), | |
], | |
style={"width": "50%", "margin": "auto"}, | |
), | |
], | |
style={"position": "relative", "zIndex": "1001", "marginBottom": "20px"}, | |
), | |
dcc.Graph( | |
id="scatter-plot", | |
style={ | |
"height": "80vh", | |
"width": "90vw", | |
"position": "relative", | |
"zIndex": "999", | |
}, | |
), | |
html.Div( | |
[html.Button("Generate LLM Prompt from current selection", id="generate-cluster-button", n_clicks=0)], | |
style={"width": "50%", "margin": "auto"}, | |
), | |
html.Div( | |
[ | |
html.P("Prompt for LLM:"), | |
dcc.Textarea( | |
id="cluster-text-output", | |
style={"width": "100%", "height": "200px", "display": "none"}, | |
value="", | |
), | |
], | |
style={"width": "50%", "margin": "auto"}, | |
), | |
] | |
) | |
def update_scatter_plot(label_range, cluster_rank_range, selected_sentiment, show_cluster_labels): | |
show_labels = "on" in show_cluster_labels | |
if selected_sentiment == "gut": | |
df_filtered = df_result_good_distil_2 | |
else: | |
df_filtered = df_result_bad_distil_2 | |
df_filtered = df_filtered[ | |
(df_filtered["labels"].between(label_range[0], label_range[1])) | |
& (df_filtered["cluster_rank"].between(cluster_rank_range[0], cluster_rank_range[1])) | |
] | |
outliers = df_filtered[df_filtered.labels == -1] | |
clustered = df_filtered[df_filtered.labels != -1] | |
fig = px.scatter( | |
clustered, | |
x="x", | |
y="y", | |
hover_data=[ | |
"summary_good_bad", | |
"sentiment", | |
"cluster_rank", | |
"cluster_count", | |
"clean_review_br", | |
], | |
hover_name="cluster_label", | |
color="labels", | |
color_continuous_scale="rainbow", | |
opacity=0.7, | |
) | |
if show_labels: | |
centroids = clustered.groupby("labels", sort=False).agg( | |
{ | |
"x": "mean", | |
"y": "mean", | |
"cluster_label": "first", | |
"cluster_count": "count", | |
} | |
) | |
for row in centroids.itertuples(): | |
fig.add_annotation( | |
x=row.x, | |
y=row.y, | |
text=f"{row.cluster_label}, #reviews: {row.cluster_count}", | |
showarrow=False, | |
) | |
fig.add_scatter( | |
x=outliers["x"], | |
y=outliers["y"], | |
mode="markers", | |
marker=dict(color="lightgray", opacity=0.5, size=5.0), | |
name="No cluster", | |
selectedpoints=False, | |
hoverinfo="skip", | |
) | |
fig.update_layout(coloraxis_colorbar=dict(len=0.9, x=1.0), height=600) | |
fig.update_traces(marker=dict(size=3), selector=dict(mode="markers")) | |
return fig | |
def update_slider_marks(selected_sentiment): | |
if selected_sentiment == "gut": | |
df_filtered = df_result_good_distil_2 | |
else: | |
df_filtered = df_result_bad_distil_2 | |
label_marks, min_label, max_label, cluster_rank_marks, min_cluster_rank, max_cluster_rank = ( | |
preprocess_data_for_slider_marks(df_filtered) | |
) | |
return ( | |
label_marks, | |
min_label, | |
max_label, | |
cluster_rank_marks, | |
min_cluster_rank, | |
max_cluster_rank, | |
) | |
def reset_label_slider(n_clicks, min_val, max_val): | |
return [min_val, max_val] | |
def reset_cluster_slider(n_clicks, min_val, max_val): | |
return [min_val, max_val] | |
def show_cluster_text_output(n_clicks): | |
if n_clicks > 0: | |
return {"width": "100%", "height": "200px", "display": "block"} | |
else: | |
return {"width": "100%", "height": "200px", "display": "none"} | |
def update_cluster_text_output(n_clicks, cluster_rank_range, selected_sentiment): | |
if n_clicks > 0: | |
if selected_sentiment == "gut": | |
df_text_outp = df_result_good_distil_2 | |
else: | |
df_text_outp = df_result_bad_distil_2 | |
df_text_outp = df_text_outp[ | |
(df_text_outp["cluster_rank"] <= cluster_rank_range[1]) | |
& (df_text_outp["cluster_rank"] >= cluster_rank_range[0]) | |
] | |
df_text_outp["summary_good_bad"] = df_text_outp["summary_good_bad"].fillna("").astype(str) | |
sampled_data = df_text_outp.sample(frac=0.1, random_state=42) | |
grouped_data = ( | |
sampled_data.groupby("cluster_label", sort=False)["summary_good_bad"].agg("\n".join).reset_index() | |
) | |
prompt_instruction = """Analysiere die nach ### folgenden CLUSTER "Clustertitel", die einzelene Bestandteile von Bewertungen erhalten\nund leite pro Cluster eine Business Massnahme ab um das Hauptproblem des Clusters zu lösen oder zu Verbessern.\nGib das Cluster mit seinem "Clustertitel" sowie die dazugehörige Maßnahme zurück.\n###""" | |
cluster_texts = prompt_instruction + "\n\n".join( | |
f"\nCLUSTER - {row['cluster_label']}\n{row['summary_good_bad']}" for _, row in grouped_data.iterrows() | |
) | |
return cluster_texts | |
else: | |
return "" | |
if __name__ == "__main__": | |
app.run_server(debug=True, host="0.0.0.0", port=7860) | |