Update app.py
Browse files
app.py
CHANGED
|
@@ -29,11 +29,56 @@ qa_pipeline = pipeline(
|
|
| 29 |
st.markdown(
|
| 30 |
"""
|
| 31 |
<style>
|
| 32 |
-
|
| 33 |
-
.
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
</style>
|
| 38 |
""",
|
| 39 |
unsafe_allow_html=True
|
|
@@ -81,15 +126,110 @@ if uploaded_file:
|
|
| 81 |
result = qa_pipeline(question=question, context=context)
|
| 82 |
st.success(f"π Answer: {result['answer']}")
|
| 83 |
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 93 |
|
| 94 |
# ----------------- Footer -----------------
|
| 95 |
st.markdown("---")
|
|
|
|
| 29 |
st.markdown(
|
| 30 |
"""
|
| 31 |
<style>
|
| 32 |
+
/* Main background and text colors */
|
| 33 |
+
.main {
|
| 34 |
+
background-color: #f4f4f4;
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
/* Text input boxes - light blue theme */
|
| 38 |
+
.stTextInput>div>div>input,
|
| 39 |
+
.stTextArea>div>div>textarea {
|
| 40 |
+
background-color: #e6f2ff;
|
| 41 |
+
border: 1px solid #b3d1ff;
|
| 42 |
+
border-radius: 8px;
|
| 43 |
+
color: #003366;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
/* File uploader - matching style */
|
| 47 |
+
.stFileUploader>div>div {
|
| 48 |
+
background-color: #e6f2ff;
|
| 49 |
+
border: 1px solid #b3d1ff;
|
| 50 |
+
border-radius: 8px;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
/* Buttons - keeping your original style */
|
| 54 |
+
.stButton>button {
|
| 55 |
+
background-color: #ff4b4b;
|
| 56 |
+
color: white;
|
| 57 |
+
border-radius: 10px;
|
| 58 |
+
border: none;
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
.stDownloadButton>button {
|
| 62 |
+
background-color: #4CAF50;
|
| 63 |
+
color: white;
|
| 64 |
+
border-radius: 10px;
|
| 65 |
+
border: none;
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
/* Text colors */
|
| 69 |
+
h1, h2, h3, h4, h5, h6 {
|
| 70 |
+
color: #003366; /* Dark blue for headers */
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
p {
|
| 74 |
+
color: #336699; /* Medium blue for paragraphs */
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
/* Dataframe styling */
|
| 78 |
+
.dataframe {
|
| 79 |
+
background-color: #e6f2ff;
|
| 80 |
+
border: 1px solid #b3d1ff;
|
| 81 |
+
}
|
| 82 |
</style>
|
| 83 |
""",
|
| 84 |
unsafe_allow_html=True
|
|
|
|
| 126 |
result = qa_pipeline(question=question, context=context)
|
| 127 |
st.success(f"π Answer: {result['answer']}")
|
| 128 |
|
| 129 |
+
# ----------------- Visualization Section -----------------
|
| 130 |
+
|
| 131 |
+
st.subheader("π Data Visualizations")
|
| 132 |
+
|
| 133 |
+
# Create two main columns (60/40 split)
|
| 134 |
+
main_col1, main_col2 = st.columns([3, 2])
|
| 135 |
+
|
| 136 |
+
with main_col1:
|
| 137 |
+
# ----------------- Topic Distribution -----------------
|
| 138 |
+
st.markdown("*Topic Distribution*")
|
| 139 |
+
|
| 140 |
+
# Create sub-columns for the charts
|
| 141 |
+
chart_col1, chart_col2 = st.columns(2)
|
| 142 |
+
|
| 143 |
+
with chart_col1:
|
| 144 |
+
# Compact Pie Chart
|
| 145 |
+
fig1, ax1 = plt.subplots(figsize=(4, 4))
|
| 146 |
+
df['class'].value_counts().plot.pie(
|
| 147 |
+
autopct='%1.1f%%',
|
| 148 |
+
startangle=90,
|
| 149 |
+
ax=ax1,
|
| 150 |
+
colors=['#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#c2c2f0'],
|
| 151 |
+
wedgeprops={'linewidth': 0.5, 'edgecolor': 'white'}
|
| 152 |
+
)
|
| 153 |
+
ax1.set_ylabel('')
|
| 154 |
+
st.pyplot(fig1, use_container_width=True)
|
| 155 |
+
|
| 156 |
+
with chart_col2:
|
| 157 |
+
# Compact Bar Chart
|
| 158 |
+
fig2, ax2 = plt.subplots(figsize=(4, 4))
|
| 159 |
+
df['class'].value_counts().plot.bar(
|
| 160 |
+
color=['#ff9999', '#66b3ff', '#99ff99', '#ffcc99', '#c2c2f0'],
|
| 161 |
+
ax=ax2,
|
| 162 |
+
width=0.7
|
| 163 |
+
)
|
| 164 |
+
ax2.set_xlabel('')
|
| 165 |
+
ax2.set_ylabel('Count')
|
| 166 |
+
plt.xticks(rotation=45, ha='right')
|
| 167 |
+
st.pyplot(fig2, use_container_width=True)
|
| 168 |
+
|
| 169 |
+
with main_col2:
|
| 170 |
+
# ----------------- Compact Word Cloud -----------------
|
| 171 |
+
st.markdown("*Word Cloud*")
|
| 172 |
+
text = " ".join(df['content'].tolist())
|
| 173 |
+
wordcloud = WordCloud(
|
| 174 |
+
width=300,
|
| 175 |
+
height=200,
|
| 176 |
+
background_color="white",
|
| 177 |
+
collocations=False,
|
| 178 |
+
max_words=100
|
| 179 |
+
).generate(text)
|
| 180 |
+
|
| 181 |
+
fig3, ax3 = plt.subplots(figsize=(4, 3))
|
| 182 |
+
ax3.imshow(wordcloud, interpolation="bilinear")
|
| 183 |
+
ax3.axis("off")
|
| 184 |
+
st.pyplot(fig3, use_container_width=True)
|
| 185 |
+
|
| 186 |
+
# ----------------- Detailed Stats (below) -----------------
|
| 187 |
+
with st.expander("π Detailed Statistics", expanded=False):
|
| 188 |
+
stats_col1, stats_col2 = st.columns(2)
|
| 189 |
+
|
| 190 |
+
with stats_col1:
|
| 191 |
+
st.write("*Category Breakdown:*")
|
| 192 |
+
stats_df = df['class'].value_counts().reset_index()
|
| 193 |
+
stats_df.columns = ['Category', 'Count']
|
| 194 |
+
stats_df['Percentage'] = (stats_df['Count'] / stats_df['Count'].sum() * 100).round(1)
|
| 195 |
+
st.dataframe(stats_df, height=200)
|
| 196 |
+
|
| 197 |
+
with stats_col2:
|
| 198 |
+
if 'date' in df.columns:
|
| 199 |
+
try:
|
| 200 |
+
st.write("*Monthly Trends*")
|
| 201 |
+
df['date'] = pd.to_datetime(df['date'])
|
| 202 |
+
trends = df.groupby([df['date'].dt.to_period('M'), 'class']).size().unstack()
|
| 203 |
+
st.line_chart(trends)
|
| 204 |
+
except:
|
| 205 |
+
st.warning("Date parsing failed")
|
| 206 |
+
|
| 207 |
+
# ----------------- News Category Explorer -----------------
|
| 208 |
+
st.subheader("π Explore News by Category")
|
| 209 |
+
|
| 210 |
+
# Get unique categories
|
| 211 |
+
categories = df['class'].unique()
|
| 212 |
+
|
| 213 |
+
# Create 5 columns for category buttons
|
| 214 |
+
cols = st.columns(5)
|
| 215 |
+
|
| 216 |
+
# Create a dictionary to store category articles
|
| 217 |
+
category_articles = {category: df[df['class'] == category] for category in categories}
|
| 218 |
+
|
| 219 |
+
# Place each category button in its own column
|
| 220 |
+
for i, category in enumerate(categories):
|
| 221 |
+
with cols[i]:
|
| 222 |
+
if st.button(category, key=f"btn_{category}"):
|
| 223 |
+
# Create pop-up window
|
| 224 |
+
with st.popover(f"π° Articles in {category}", use_container_width=True):
|
| 225 |
+
st.markdown(f"### {category} Articles")
|
| 226 |
+
articles = category_articles[category]
|
| 227 |
+
|
| 228 |
+
# Display articles with expandable content
|
| 229 |
+
for idx, row in articles.iterrows():
|
| 230 |
+
with st.expander(f"Article {idx + 1}: {row['content'][:50]}...", expanded=False):
|
| 231 |
+
st.write(row['content'])
|
| 232 |
+
st.caption(f"Classification confidence: {classifier(row['content'])[0]['score']:.2f}")
|
| 233 |
|
| 234 |
# ----------------- Footer -----------------
|
| 235 |
st.markdown("---")
|