diff --git a/src/streamlit_app.py b/src/streamlit_app.py
index dc785b7..c47d9d4 100644
--- a/src/streamlit_app.py
+++ b/src/streamlit_app.py
@@ -12,81 +12,257 @@ from src.models import train_model, save_model, load_model, compare_models
# 设置页面配置
st.set_page_config(
- page_title="垃圾短信分类系统",
- page_icon="📱",
+ page_title="垃圾短信分类器",
+ page_icon="�️",
layout="wide",
initial_sidebar_state="expanded"
)
-# 应用标题
-st.title("📱 垃圾短信分类系统")
+# 自定义CSS - 欧洲中世纪风格
+st.markdown("""""", unsafe_allow_html=True)
+
+# 应用标题 - 中世纪风格
+st.markdown("""
+
+
+ ⚔️ 中世纪垃圾短信分类器
+
+
+ 保护您的通信,抵御垃圾信息的入侵
+
+
+""", unsafe_allow_html=True)
+
st.markdown("---")
-# 侧边栏
+# 侧边栏 - 中世纪风格
with st.sidebar:
- st.header("系统配置")
+ st.markdown("""
+
+
+ 🛡️ 骑士工坊
+
+
+ 系统配置
+
+
+ """, unsafe_allow_html=True)
+
+ # 模型选择 - 中世纪风格
+ st.markdown("""
+
+
+ ⚔️ 选择武器
+
+
+ 选择用于抵御垃圾信息的武器
+
+
+ """, unsafe_allow_html=True)
- # 模型选择
model_option = st.selectbox(
- "选择模型",
+ label="",
options=["lightgbm", "logistic_regression"],
index=0,
- help="选择用于分类的机器学习模型"
+ format_func=lambda x: "圣光使者 (LightGBM)" if x == "lightgbm" else "智慧之剑 (Logistic Regression)"
)
- # 语言选择
+ # 语言选择 - 中世纪风格
+ st.markdown("""
+
+
+ 📜 选择语言
+
+
+ 选择预言师的语言
+
+
+ """, unsafe_allow_html=True)
+
lang_option = st.selectbox(
- "输出语言",
+ label="",
options=["中文", "英文"],
- index=0,
- help="选择分类结果和解释的输出语言"
+ index=0
)
- # 系统说明
+ # 系统说明 - 中世纪风格
st.markdown("---")
- st.header("关于系统")
- st.info(
- "这是一个基于传统机器学习 + LLM + Agent的垃圾短信分类系统。\n"\
- "- 使用LightGBM和Logistic Regression进行分类\n"\
- "- 利用DeepSeek LLM解释分类结果\n"\
- "- 通过Agent实现工具调用和结果整合"
- )
+ st.markdown("""
+
+
+ 🏰 关于城堡
+
+
+ """, unsafe_allow_html=True)
+
+ st.markdown("""
+
+
🛡️ 城堡防御系统
+
这是一座由现代魔法和古老智慧构建的防御城堡:
+
+ - 💫 使用圣光使者 (LightGBM) 和智慧之剑 (Logistic Regression) 守护
+ - 🧙 由DeepSeek预言师提供智慧解释
+ - 🤖 通过魔法使者 (Agent) 整合所有力量
+
+
+ 保护您的通信不受垃圾信息的侵袭!
+
+
+ """, unsafe_allow_html=True)
-# 主内容区域
+# 主内容区域 - 中世纪风格
col1, col2 = st.columns([1, 1], gap="large")
with col1:
- # 短信输入
- st.header("输入短信")
+ # 短信输入 - 中世纪风格
+ st.markdown("""
+
+
+ 📜 信件输入
+
+
+ 输入需要检查的信件内容
+
+
+ """, unsafe_allow_html=True)
# 单条短信输入
sms_input = st.text_area(
- "请输入要分类的短信",
+ label="",
height=200,
- placeholder="例如:WINNER!! As a valued network customer you have been selected to receivea £900 prize reward!"
+ placeholder="例如:WINNER!! As a valued network customer you have been selected to receivea £900 prize reward!",
+ help="输入需要分类的短信内容"
)
- # 分类按钮
+ # 分类按钮 - 中世纪风格
classify_button = st.button(
- "📊 开始分类",
+ "⚔️ 开始检查",
type="primary",
use_container_width=True,
disabled=sms_input.strip() == ""
)
- # 批量上传功能
+ # 批量上传功能 - 中世纪风格
st.markdown("---")
- st.header("批量分类")
+ st.markdown("""
+
+
+ 📦 批量检查
+
+
+ 上传多封信件进行批量检查
+
+
+ """, unsafe_allow_html=True)
+
uploaded_file = st.file_uploader(
- "上传CSV文件(包含text列)",
+ label="",
type=["csv"],
- help="上传包含短信文本的CSV文件,系统将自动分类"
+ help="上传包含短信文本的CSV文件(需要包含text列)"
)
- # 模型训练功能(可选)
- with st.expander("🔧 模型训练", expanded=False):
- if st.button("重新训练模型"):
- with st.spinner("正在训练模型..."):
+ # 模型训练功能(可选) - 中世纪风格
+ with st.expander("🔧 锻造武器", expanded=False):
+ st.markdown("""
+
+
+ 铁匠工坊
+
+
+ 重新锻造您的武器,提升防御能力
+
+
+ """, unsafe_allow_html=True)
+
+ if st.button("⚒️ 重新锻造武器"):
+ with st.spinner("🔨 铁匠正在锻造武器..."):
try:
# 加载和预处理数据
df = load_data("../data/spam.csv")
@@ -97,9 +273,25 @@ with col1:
model, params = train_model(train_df, model_type=model_option)
save_model(model, model_option)
- st.success(f"{model_option} 模型训练完成!")
+ st.markdown("""
+
+ ✨ 武器锻造完成!
+
+ 您的 {} 已准备好进行战斗!
+
+
+ """
+ .format("圣光使者 (LightGBM)" if model_option == "lightgbm" else "智慧之剑 (Logistic Regression)"), unsafe_allow_html=True)
except Exception as e:
- st.error(f"模型训练失败:{e}")
+ st.markdown("""
+
+ ❌ 锻造失败!
+
+ 铁匠遇到了问题:{}
+
+
+ """
+ .format(e), unsafe_allow_html=True)
with col2:
# 分类结果显示
@@ -115,54 +307,140 @@ with col2:
# 显示分类结果
st.subheader("📋 分类标签")
- # 根据标签显示不同的样式
+ # 根据标签显示不同的样式 - 中世纪风格
if result['classification']['label'] == "spam":
- st.error(f"⚠️ 这是一条**垃圾短信**")
+ st.markdown("""
+
+ ⚠️
这是一封**垃圾信件**!
+
+ 建议您谨慎对待此信件!
+
+
+ """, unsafe_allow_html=True)
else:
- st.success(f"✅ 这是一条**正常短信**")
+ st.markdown("""
+
+ ✅
这是一封**正常信件**
+
+ 此信件安全,可以放心阅读!
+
+
+ """, unsafe_allow_html=True)
- # 显示概率
- st.subheader("📊 分类概率")
+ # 显示概率 - 中世纪风格
+ st.markdown("""
+
+
+ 📊 预言概率
+
+
+ """, unsafe_allow_html=True)
prob_df = pd.DataFrame.from_dict(
result['classification']['probability'],
orient='index',
columns=['概率']
)
+ prob_df.index = ['垃圾信件', '正常信件'] if lang_option == '中文' else ['Spam', 'Ham']
st.bar_chart(prob_df)
- # 显示详细结果
- st.subheader("📝 详细结果")
+ # 显示详细结果 - 中世纪风格
+ st.markdown("""
+
+
+ � 详细预言
+
+
+ """, unsafe_allow_html=True)
+
with st.expander("查看详细分类结果", expanded=True):
st.json(result['classification'], expanded=False)
- # 显示解释和建议
- st.subheader("🤔 结果解释")
- with st.expander("查看分类解释", expanded=True):
- st.write(f"**内容摘要**:{result['explanation']['content_summary']}")
- st.write(f"**分类原因**:{result['explanation']['classification_reason']}")
- st.write(f"**可信度**:{result['explanation']['confidence_level']} - {result['explanation']['confidence_explanation']}")
+ # 显示解释和建议 - 中世纪风格
+ st.markdown("""
+
+
+ � 预言师的解释
+
+
+ """, unsafe_allow_html=True)
+
+ with st.expander("查看预言解释", expanded=True):
+ st.markdown("""
+
+
📝 内容摘要:{}
+
⚖️ 预言原因:{}
+
🔮 可信度:{} - {}
+
+ """
+ .format(
+ result['explanation']['content_summary'],
+ result['explanation']['classification_reason'],
+ result['explanation']['confidence_level'],
+ result['explanation']['confidence_explanation']
+ ), unsafe_allow_html=True)
+
+ st.markdown("""
+
+
+ 💡 行动建议
+
+
+ """, unsafe_allow_html=True)
+
+ suggestion_html = """
+
+
+ """
- st.subheader("💡 行动建议")
for i, suggestion in enumerate(result['explanation']['suggestions']):
- st.write(f"{i+1}. {suggestion}")
+ suggestion_html += f"- {suggestion}
"
+
+ suggestion_html += """
+
+
+ """
+
+ st.markdown(suggestion_html, unsafe_allow_html=True)
except Exception as e:
- st.error(f"分类失败:{e}")
+ st.markdown("""
+
+ ❌ 预言失败!
+
+ 预言师遇到了问题:{}
+
+
+ """
+ .format(e), unsafe_allow_html=True)
- # 批量分类结果
+ # 批量分类结果 - 中世纪风格
if uploaded_file is not None:
- with st.spinner("正在批量分类..."):
+ with st.spinner("🧙♂️ 预言师正在批量解析信件..."):
try:
# 读取上传的文件
df = pd.read_csv(uploaded_file)
if "text" not in df.columns:
- st.error("CSV文件必须包含'text'列")
+ st.markdown("""
+
+ ❌ 预言失败!
+
+ 信件文件必须包含'text'列
+
+
+ """, unsafe_allow_html=True)
else:
# 限制处理数量
max_rows = 100
if len(df) > max_rows:
- st.warning(f"文件包含 {len(df)} 条记录,仅处理前 {max_rows} 条")
+ st.markdown("""
+
+ ⚠️ 警告
+
+ 信件文件包含 {len(df)} 封信件,预言师将只解析前 {max_rows} 封
+
+
+ """, unsafe_allow_html=True)
df = df.head(max_rows)
# 批量分类
@@ -181,41 +459,63 @@ with col2:
# 转换为DataFrame
results_df = pd.DataFrame(results)
- # 显示结果统计
- st.subheader("📊 分类统计")
+ # 显示结果统计 - 中世纪风格
+ st.markdown("""
+
+
+ 📊 预言统计
+
+
+ """, unsafe_allow_html=True)
+
label_counts = results_df["label"].value_counts()
+ label_counts.index = label_counts.index.map({"spam": "垃圾信件", "ham": "正常信件"})
st.bar_chart(label_counts)
- # 显示结果表格
- st.subheader("📋 分类结果")
+ # 显示结果表格 - 中世纪风格
+ st.markdown("""
+
+
+ � 预言结果
+
+
+ """, unsafe_allow_html=True)
+
st.dataframe(
results_df,
use_container_width=True,
column_config={
- "text": st.column_config.TextColumn("短信内容", width="medium"),
- "label": st.column_config.TextColumn("分类标签"),
+ "text": st.column_config.TextColumn("信件内容", width="medium"),
+ "label": st.column_config.TextColumn("预言标签"),
"spam_probability": st.column_config.ProgressColumn(
- "垃圾短信概率",
+ "垃圾信件概率",
format="%.2f",
min_value=0.0,
max_value=1.0
),
"ham_probability": st.column_config.ProgressColumn(
- "正常短信概率",
+ "正常信件概率",
format="%.2f",
min_value=0.0,
max_value=1.0
),
"content_summary": st.column_config.TextColumn("内容摘要", width="medium"),
- "classification_reason": st.column_config.TextColumn("分类原因", width="medium")
+ "classification_reason": st.column_config.TextColumn("预言原因", width="medium")
}
)
- # 下载结果
- st.subheader("💾 下载结果")
+ # 下载结果 - 中世纪风格
+ st.markdown("""
+
+
+ 💾 保存预言
+
+
+ """, unsafe_allow_html=True)
+
csv = results_df.to_csv(index=False).encode('utf-8')
st.download_button(
- label="下载分类结果 (CSV)",
+ label="📄 下载预言结果",
data=csv,
file_name="spam_classification_results.csv",
mime="text/csv",
@@ -223,11 +523,28 @@ with col2:
)
except Exception as e:
- st.error(f"批量分类失败:{e}")
+ st.markdown("""
+
+ ❌ 预言失败!
+
+ 预言师遇到了问题:{}
+
+
+ """
+ .format(e), unsafe_allow_html=True)
-# 页脚
+# 页脚 - 中世纪风格
st.markdown("---")
-st.markdown(
- "© 2026 垃圾短信分类系统 | 基于传统机器学习 + LLM + Agent",
- unsafe_allow_html=True
-)
\ No newline at end of file
+st.markdown("""
+
+
+ 🏰 中世纪垃圾短信防御城堡
+
+
+ © 2026 由骑士团建造 | 基于传统魔法 + LLM 预言 + Agent 使者
+
+
+ 保护您的通信不受垃圾信息的侵袭!
+
+
+""", unsafe_allow_html=True)
\ No newline at end of file