Spaces:
Sleeping
Sleeping
File size: 4,679 Bytes
cdb73a8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 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 129 130 131 132 133 134 135 136 137 138 139 140 | import logging
import os
import pandas as pd
import plotly.express as px
import streamlit as st
import sys
import os
# Add the project root to the Python path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../..")))
from src.book_recommender.core.logging_config import configure_logging
from src.book_recommender.ml.feedback import get_all_feedback
configure_logging(log_file="analytics.log", log_level=os.getenv("LOG_LEVEL", "INFO"))
logger = logging.getLogger(__name__)
st.set_page_config(
page_title="DeepShelf Analytics Dashboard", page_icon="📊", layout="wide", initial_sidebar_state="collapsed"
)
st.title("DeepShelf Analytics Dashboard")
@st.cache_data
def load_feedback_data():
"""Load and process feedback data."""
logger.info("Loading feedback data for analytics...")
feedback_entries = get_all_feedback()
if not feedback_entries:
logger.warning("No feedback data found.")
return pd.DataFrame()
df = pd.DataFrame(feedback_entries)
df["timestamp"] = pd.to_datetime(df["timestamp"])
df["date"] = df["timestamp"].dt.date
logger.info(f"Loaded {len(df)} feedback entries.")
return df
feedback_df = load_feedback_data()
if feedback_df.empty:
st.info("No feedback data available yet to display analytics.")
else:
st.header("Key Metrics")
total_feedback = len(feedback_df)
positive_feedback = len(feedback_df[feedback_df["feedback"] == "positive"])
negative_feedback = len(feedback_df[feedback_df["feedback"] == "negative"])
satisfaction_percentage = (positive_feedback / total_feedback * 100) if total_feedback > 0 else 0
col1, col2, col3, col4 = st.columns(4)
with col1:
st.metric("Total Feedback", total_feedback)
with col2:
st.metric("Positive Feedback", positive_feedback)
with col3:
st.metric("Negative Feedback", negative_feedback)
with col4:
st.metric("Satisfaction Rate", f"{satisfaction_percentage:.1f}%")
st.markdown("---")
st.header("Feedback Over Time")
feedback_by_date = feedback_df.groupby(["date", "feedback"]).size().unstack(fill_value=0)
fig_time = px.line(
feedback_by_date,
x=feedback_by_date.index,
y=feedback_by_date.columns,
title="Feedback Count Over Time",
labels={"value": "Count", "date": "Date", "variable": "Feedback Type"},
color_discrete_map={"positive": "green", "negative": "red"},
)
st.plotly_chart(fig_time, use_container_width=True)
st.markdown("---")
st.header("Top Queries")
top_queries = feedback_df["query"].value_counts().reset_index()
top_queries.columns = ["Query", "Count"]
fig_queries = px.bar(
top_queries.head(10),
x="Query",
y="Count",
title="Top 10 Most Frequent Queries",
labels={"Count": "Number of Times Queried"},
color_discrete_sequence=px.colors.qualitative.Pastel,
)
st.plotly_chart(fig_queries, use_container_width=True)
st.markdown("---")
st.header("Most Liked / Disliked Books")
book_feedback_counts = feedback_df.groupby(["book_title", "feedback"]).size().unstack(fill_value=0)
book_feedback_counts["net_positive"] = book_feedback_counts.get("positive", 0) - book_feedback_counts.get(
"negative", 0
)
most_liked_books = book_feedback_counts.sort_values(by="net_positive", ascending=False).head(5)
most_disliked_books = book_feedback_counts.sort_values(by="net_positive", ascending=True).head(5)
col_liked, col_disliked = st.columns(2)
with col_liked:
st.subheader("Top 5 Most Liked Books (Net Positive)")
if not most_liked_books.empty:
st.dataframe(
most_liked_books[["positive", "negative", "net_positive"]].rename(
columns={"positive": "👍", "negative": "👎", "net_positive": "Net Score"}
)
)
else:
st.info("No liked book data.")
with col_disliked:
st.subheader("Top 5 Most Disliked Books (Net Negative)")
if not most_disliked_books.empty:
st.dataframe(
most_disliked_books[["positive", "negative", "net_positive"]].rename(
columns={"positive": "👍", "negative": "👎", "net_positive": "Net Score"}
)
)
else:
st.info("No disliked book data.")
st.markdown("---")
if st.checkbox("Show Raw Feedback Data"):
st.subheader("Raw Feedback Data")
st.dataframe(feedback_df)
def main():
"""Entry point for analytics dashboard"""
pass
if __name__ == "__main__":
main()
|