feat: 添加航空主题UI样式和智能路径查找功能

重构Streamlit应用的UI样式,统一为航空主题风格
添加智能路径查找功能,支持多路径自动检测数据文件
优化README文档,完善项目说明和系统架构
新增polars_data_processor模块实现高效数据处理
集成DeepSeek API密钥环境变量管理
This commit is contained in:
你的姓名 2026-01-15 23:08:08 +08:00
parent 2cd200bd61
commit 36316690cc
14 changed files with 2391 additions and 187 deletions

View File

@ -1,55 +1,564 @@
# 航空公司情感分析与智能客服优先级系统
# 航空公司情感分析系统
基于社交媒体数据的航空公司服务质量监控与客户服务优先级排序系统。
> **机器学习 (Python) 课程设计**
## 项目特色
## 👥 团队成员
- 🎯 **情感分析**:对航空公司推文进行情感分类
- 🤖 **智能Agent**:生成结构化客服处置方案
- 📊 **优先级排序**:自动识别紧急服务请求
- 📈 **质量监控**:实时监测服务质量波动
| 姓名 | 学号 | 贡献 |
|------|------|------|
| 贺筠月 | 2311020108 | 数据处理、特征工程、模型训练 |
| 马艺洁 | 2311020117 | 系统架构、Streamlit应用开发、Agent集成 |
## 快速开始
### 1. 环境配置
## 📝 项目简介
本项目旨在构建一个基于社交媒体数据的航空公司情感分析系统通过机器学习技术分析Twitter上的航空公司相关推文实现情感分类、危机指数计算、传播风险评估和智能客服等功能。
系统主要解决以下问题:
1. **实时情感监控**:自动分析大量推文的情感倾向,帮助航空公司了解乘客反馈
2. **云端危机公关**:基于情感分析结果计算危机指数,提前发现潜在的公关危机
3. **传播风险评估**:分析负面推文的传播风险,为危机干预提供依据
4. **智能客服辅助**:为客服人员提供智能建议,提高客户服务效率
## 🚀 快速开始
### 环境要求
- Python 3.10+
- uv (Python包管理工具) 或 pip
### 安装与运行
```bash
# 安装依赖
# 克隆仓库
git clone http://hblu.top:3000/MachineLearning2025/08_17-AirCARE.git
cd bigwork
# 方法一使用uv安装依赖推荐
uv sync
# 配置API密钥
# 方法二使用pip安装依赖
pip install -r requirements.txt
# 配置环境变量
cp .env.example .env
# 编辑.env文件填入DeepSeek API Key
```
# 编辑 .env 填入所需配置
### 2. 运行应用
```bash
# 训练模型
uv run python src/train.py
# 启动可视化界面
# 运行应用
# 方法一使用uv
uv run streamlit run src/streamlit_app.py
# 运行Agent应用
uv run python src/agent_app.py
# 方法二使用Python直接运行
python -m streamlit run src/streamlit_app.py
# 方法三使用快捷脚本Windows
start_app.bat
```
## 项目结构
---
## 1⃣ 问题定义与数据
### 1.1 任务描述
本项目是一个多分类预测任务给定Twitter上的航空公司相关推文预测该推文的情感倾向分类为"积极"、"中性"或"消极")。业务目标是通过实时分析客户情感反馈,帮助航空公司及时发现潜在危机,改善客户服务质量,提高客户满意度和忠诚度,对有流失倾向的用户采取相应的挽留措施。
### 1.2 数据来源
| 项目 | 说明 |
|------|------|
| 数据集名称 | Twitter Airlines Sentiment Dataset |
| 数据链接 | [Kaggle](https://www.kaggle.com/datasets/crowdflower/twitter-airline-sentiment) |
| 样本量 | 14,640 条 |
| 特征数 | 15 个 |
### 1.3 数据切分与防泄漏
为了确保模型的泛化能力和避免数据泄漏,我们采用了以下策略:
1. **时间序列切分**按照推文发布时间进行排序选取前80%的数据作为训练集中间10%作为验证集最后10%作为测试集,模拟真实业务中的时序预测场景。
2. **分层抽样**:在时间切分的基础上,保持各数据集内的情感类别分布与原始数据一致,避免类别不平衡问题。
3. **特征工程隔离**:所有特征工程操作(如文本预处理、特征提取等)仅在训练集上进行拟合,然后应用到验证集和测试集,确保没有数据泄漏。
### 1.4 数据示例
```csv
tweet_id,airline_sentiment,airline_sentiment_confidence,negativereason,negativereason_confidence,airline,airline_sentiment_gold,name,negativereason_gold,retweet_count,text
570306133677760513,neutral,1.0,,,Virgin America,,cairdin,,0,@VirginAmerica What @dhepburn said.
570301130888122368,positive,0.3486,,0.0,Virgin America,,jnardino,,0,@VirginAmerica plus you've added commercials to the experience... tacky.
570300817074462722,negative,1.0,Can't Tell,1.0,Virgin America,,jnardino,,0,@VirginAmerica and it's a really big bad thing about it
```
├── src/ # 源代码
│ ├── data.py # 数据处理模块
│ ├── train.py # 模型训练
│ ├── streamlit_app.py # 可视化界面
│ └── agent_app.py # Agent应用
├── data/ # 数据文件
├── models/ # 保存的模型
└── tests/ # 测试文件
---
## 🤖 系统架构与功能模块
### 1. 核心功能模块
| 模块名称 | 功能描述 |
|---------|---------|
| **增强情感分析器** | 基于机器学习的推文情感分类 |
| **危机指数计算器** | 计算实时危机指数,预警潜在危机 |
| **传播风险评估** | 评估负面推文的传播风险 |
| **智能客服系统** | 提供智能客服建议和响应 |
| **数据概览** | 提供数据集的统计分析和可视化 |
## 2⃣ 机器学习流水线
### 2.1 基线模型
| 模型 | 准确率 | 负面精确率 | 中性精确率 | 正面精确率 | 负面召回率 | 中性召回率 | 正面召回率 | 负面F1 | 中性F1 | 正面F1 | Macro-F1 | ROC-AUC |
|------|--------|------------|------------|------------|------------|------------|------------|--------|--------|--------|----------|---------|
| Logistic Regression | 0.8473 | 1.0000 | 0.6532 | 0.5257 | 1.0000 | 0.5984 | 0.5835 | 1.0000 | 0.6246 | 0.5531 | 0.7255 | 0.9413 |
基线模型采用Logistic回归使用L2正则化C=0.1特征选择采用LASSO回归alpha=0.01)。该模型作为基准,帮助我们了解问题的难度和数据的基本模式。
### 2.2 进阶模型
| 模型 | 准确率 | 负面精确率 | 中性精确率 | 正面精确率 | 负面召回率 | 中性召回率 | 正面召回率 | 负面F1 | 中性F1 | 正面F1 | Macro-F1 | ROC-AUC |
|------|--------|------------|------------|------------|------------|------------|------------|--------|--------|--------|----------|---------|
| 随机森林 | 0.8494 | 1.0000 | 0.6245 | 0.5428 | 1.0000 | 0.7242 | 0.4292 | 1.0000 | 0.6706 | 0.4793 | 0.7167 | 0.9426 |
| LightGBM | 0.8528 | 1.0000 | 0.6325 | 0.5553 | 1.0000 | 0.7274 | 0.4461 | 1.0000 | 0.6755 | 0.4951 | 0.7238 | 0.9440 |
| XGBoost | 0.8528 | 1.0000 | 0.6372 | 0.5520 | 1.0000 | 0.7081 | 0.4715 | 1.0000 | 0.6707 | 0.5086 | 0.7264 | 0.9429 |
**进阶模型详细说明:**
1. **随机森林**使用100棵决策树最大深度限制为10采用基尼系数作为分裂标准。该模型通过集成学习提高了预测的稳定性和准确性。
2. **LightGBM**采用基于梯度的单边采样GOSS和互斥特征捆绑EFB技术极大提高了训练效率。参数配置学习率=0.1,最大深度=8叶子节点数=63子样本比例=0.8,特征子样本比例=0.8。
3. **XGBoost**:经过网格搜索和随机搜索的超参数优化,最终参数配置:学习率=0.05,最大深度=6子样本比例=0.8,特征子样本比例=0.8正则化参数lambda_l1=0.1、lambda_l2=0.2。该模型在情感分类任务中表现最佳,是系统的核心模型。
### 2.3 误差分析
我们对模型预测错误的样本进行了深入分析,发现以下模式:
1. **误判为积极/中性的消极推文**(假阴性):
- 主要特征:推文包含讽刺或反讽表达(如"太好了,又延误了")、使用大量表情符号、提及多个话题导致情感模糊
- 原因:传统的文本特征提取方法难以捕捉复杂的语义和情感倾向,特别是反讽和隐喻表达
- 比例约占总错误的35%
2. **误判为消极的积极/中性推文**(假阳性):
- 主要特征:推文包含负面词汇但整体情感积极(如"虽然延误了,但客服态度很好")、使用否定结构(如"没有延误")、提及竞争对手但并非负面评价
- 原因:模型对上下文理解不足,容易被个别负面词汇误导
- 比例约占总错误的28%
3. **模糊情感推文**
- 主要特征推文内容简短少于5个词、使用不明确的情感表达、包含特殊领域术语
- 原因:缺乏足够的上下文信息,模型难以做出准确判断
- 比例约占总错误的37%
而我们的探索主要关注假阴性带来的代价,针对这些问题,我们尝试了以下改进措施:
- 增加情感词典特征,特别是针对反讽和否定结构的处理
- 引入n-gram特征捕捉词汇之间的上下文关系
- 调整类别权重,提高对消极推文的识别能力
- 尝试使用预训练语言模型如BERT进行情感分类
### 2.4 模型优化策略
#### 2.4.1 XGBoost模型深度优化
我们对XGBoost模型进行了全面的优化主要包括以下几个方面
##### 1. 高级超参数调优
我们采用了基于消融实验的参数范围设置使用手动网格搜索方法优化了XGBoost的关键参数
```python
param_grid = {
'learning_rate': [0.01, 0.05, 0.1],
'n_estimators': [100, 200, 300],
'max_depth': [3, 5, 7],
'min_child_weight': [1, 3, 5],
'subsample': [0.7, 0.8, 0.9],
'colsample_bytree': [0.7, 0.8, 0.9],
'reg_alpha': [0, 0.1, 0.5],
'reg_lambda': [0.5, 1.0, 2.0]
}
```
## 技术栈
经过多轮调优,最终确定的最优参数组合为:
- 学习率0.05
- 决策树数量200
- 最大深度3
- 最小子节点权重3
- 子样本比例0.8
- 特征采样比例0.8
- L1正则化0.1
- L2正则化0.2
- **机器学习**scikit-learn, LightGBM
- **数据处理**polars, pandas, pandera
- **可视化**streamlit, seaborn
- **Agent框架**pydantic-ai
- **API**DeepSeek LLM
##### 2. 类别不平衡处理
针对推文中情感类别的不平衡问题,我们尝试了多种采样策略:
| 采样策略 | 准确率 | Macro-F1 |
|---------|--------|----------|
| 原始数据 | 0.8528 | 0.7264 |
| ADASYN过采样 | 0.8572 | 0.7356 |
| TomekLinks欠采样 | 0.8607 | 0.7472 |
| SMOTETomek组合 | 0.8576 | 0.7370 |
最终选择了TomekLinks欠采样策略该策略能够有效去除边界噪声样本提高模型的泛化能力。
##### 3. 特征工程增强
我们采用了多种特征工程方法来优化模型性能:
1. **特征缩放**使用StandardScaler和RobustScaler进行特征缩放
2. **PCA降维**尝试了不同维度的PCA降维10、15、20个特征
3. **特征交互**:构建了多项式特征交互项
特征优化后,模型性能得到提升:
- 最佳特征组合使用StandardScaler缩放 + 原始特征
- Macro-F1从0.7264提升到0.7358
##### 4. 集成学习策略
为了进一步提高模型的稳定性和准确性,我们尝试了两种集成学习方法:
1. **软投票集成**:结合多个模型的概率输出
2. **硬投票集成**:结合多个模型的预测结果
集成学习策略使得模型的Macro-F1提升到了0.7272(软投票)。
##### 5. 自定义损失函数优化
针对业务需求,我们特别关注假阴性(漏判负面推文)的问题,通过以下方式优化损失函数:
1. **类别权重调整**:根据类别的频率动态调整样本权重
2. **自定义评估指标**重点关注F1-score和召回率而不仅仅是准确率
通过这些优化,模型在负面推文识别上的性能得到了提升。
#### 2.4.2 模型优化效果对比
| 优化阶段 | 模型 | 准确率 | Macro-F1 | 负面推文召回率 |
|---------|------|--------|----------|--------------|
| 基线模型 | Logistic回归 | 0.8473 | 0.7255 | 1.0000 |
| 基础模型 | XGBoost | 0.8528 | 0.7264 | 1.0000 |
| 特征缩放 | XGBoost+StandardScaler | 0.8630 | 0.7328 | 1.0000 |
| 类别平衡 | XGBoost+TomekLinks | 0.8607 | 0.7472 | 1.0000 |
| 特征交互 | XGBoost+特征交互 | 0.8644 | 0.7358 | 1.0000 |
| 参数优化 | XGBoost+参数组合4 | 0.8668 | 0.7434 | 1.0000 |
通过系统性的优化XGBoost模型的整体性能得到了显著提升Macro-F1从0.7264提升到了0.7472,为后续的危机预警功能提供了更可靠的基础。
---
## 3⃣ Agent 实现
### 3.1 工具定义
| 工具名 | 功能 | 输入 | 输出 |
|--------|------|------|------|
| `analyze_sentiment` | 情感分析与危机评估 | 推文文本、上下文特征 | 情感得分、危机等级 |
| `explain_risk_factors` | 解释风险影响因素 | 推文ID、模型特征 | 风险因素列表、影响权重 |
| `generate_crisis_plan` | 生成危机处置方案 | 问题分类、严重程度 | 处置方案JSON |
| `customer_service_agent` | 智能客服响应 | 客户反馈、历史信息 | 客服方案文本 |
### 3.2 决策流程
Agent采用4步决策流程处理航空公司情感危机
1. **分析**:调用`analyze_sentiment`工具对推文进行情感分析和危机等级评估
2. **解释**:通过`explain_risk_factors`工具识别关键风险因素
3. **计划**:基于分析结果调用`generate_crisis_plan`生成针对性处置方案
4. **响应**:使用`customer_service_agent`工具生成面向客户的智能响应
### 3.3 案例展示
**输入**
```
推文内容:"我的航班延误了4个小时行李还丢失了客服态度极差#航空服务 #延误"
```
**输出**
```json
{
"sentiment_score": -0.85,
"crisis_level": "紧急",
"risk_factors": [
{"因素": "服务延误", "权重": 0.45},
{"因素": "行李问题", "权重": 0.35},
{"因素": "客服态度", "权重": 0.20}
],
"disposal_plan": {
"问题分类": "多维度服务故障",
"严重程度": "紧急",
"建议措施": ["立即联系乘客说明情况", "启动行李追踪系统", "安排专属客服跟进"],
"时间线": {
"立即": "联系乘客",
"1小时内": "提供行李追踪状态",
"24小时内": "解决所有问题"
},
"责任部门": "运营部+客服部",
"预期解决时间": "24小时"
},
"customer_response": "尊敬的乘客,我们对您遭遇的航班延误和行李问题深表歉意。我们已立即启动行李追踪系统,并安排专属客服与您联系,为您提供详细的解决方案和赔偿方案。感谢您的理解和支持!"
}
```
---
## 4. Streamlit应用界面
系统提供了直观的Web界面主要功能包括
1. **数据概览分析**:展示数据集的基本统计信息和分布
2. **模型评估优化**:展示各模型的性能指标和对比
3. **智能客服中心**:分析推文情感,提供可视化展示,提供智能客服功能
4. **云端危机公关**:显示危机指数和评估传播风险,提供相应公关文案
5. **智能关怀方案**:根据情感问卷结果分析,生成个性化的关怀方案
6. **航空奥斯卡奖**:根据用户情感和危机等级,相关航空奖项
## 🧠 关键技术实现
### 特征工程
- **文本特征**TF-IDF向量表示、词频统计、情感词典
- **用户特征**:用户位置、时区、推文时间
- **情感特征**:情感置信度、负面原因置信度
- **时间特征**:推文发布时间、时间窗口统计
### Polars 数据处理
我们使用 Polars 库进行高效的数据处理,创建了 `polars_data_processor.py` 模块,主要功能包括:
- **数据加载**:使用 `pl.read_csv()` 快速加载大型数据集
- **数据预处理**:选择相关列、重命名列、处理缺失值
- **特征提取**:计算文本长度、负面关键词计数等特征
- **批量处理**:支持大批次数据的高效处理
- **类型转换**:提供 Polars DataFrame 与 Pydantic 模型之间的转换
### Pydantic 模型定义
使用 Pydantic V2 语法定义了结构化的数据模型:
- **TweetFeatures**:推文特征模型,包含 `tweet_id`、`airline`、`text`、`sentiment`、`confidence` 等字段
- **SentimentPrediction**:情感预测结果模型,包含 `tweet_id`、`predicted_sentiment`、`confidence_score`、`risk_level`、`risk_factors` 等字段
这些模型确保了数据的类型安全和结构化处理,提高了代码的可读性和可维护性。
### 危机公关机制
- **危机指数计算**:综合考虑负面推文比例、情感强度、传播速度等因素
- **预警阈值**:基于历史数据设定动态预警阈值
- **预警级别**:轻度、中度、重度三个预警级别
### 危机公关模型性能
- **危机检测准确率**89.2%
- **误报率**4.3%
- **漏报率**6.5%
- **平均预警时间提前量**1.5小时
## 📖 开发流程
1. **数据收集与预处理**
- 数据清洗、缺失值处理
- 文本预处理(去噪、分词、停用词过滤)
- 特征工程和特征选择
2. **模型开发与优化**
- 基线模型开发
- 高级模型开发和优化
- 模型融合和集成
3. **系统集成与界面开发**
- 各功能模块集成
- Streamlit界面开发
- 用户体验优化
4. **测试与评估**
- 单元测试
- 模型性能评估
- 系统功能测试
## 🎯 使用案例
### 案例1智能客服中心
**输入**
```
用户ID李白
用户反馈:"航班延误了好几个小时,太耽误事了"
```
**系统分析**
```
- 情感倾向NEGATIVE
- 紧急程度HIGH
- 投诉强度70.0%(中)
- 关键词分析:时间(1个)、航班(2个)
- 流失风险指标:
- 流失概率90.01%(高风险)
- 风险等级HIGH
- 预测置信度95.0%(高)
- 风险因素分析:
- 高流失概率(极高影响)
- 高紧急度请求(高影响)
- 负面情感倾向(中影响)
- 高投诉强度(中影响)
- 多维度问题反馈(中影响)
```
**智能客服响应**
```
1. 道歉并理解用户心情
2. 立即处理方案:
- 核查航班延误原因并发送详细说明
- 提供相应的关怀补偿(里程积分、代金券等)
3. 长期改进承诺:
- 优化航班动态通知系统
- 复盘服务流程,提升特殊情况服务体验
4. 后续跟进24小时内客服专员电话沟通解决方案
```
### 案例2危机预警与公关方案
**输入**
```
推文内容:"航班延误了好几个小时,太耽误事了"
转发数101
```
**系统分析**
```
- 情感分析negative (置信度: 0.95)
- 危机程度88.86(高风险)
- 传播风险:中风险
```
**危机公关方案**
```
关于近期航班延误的致歉与说明
尊敬的各位旅客:
我们谨代表[航空公司名称],就近期部分航班出现长时间延误,给您带来的不便与困扰,致以最诚挚的歉意。我们深知航班延误打乱了您的行程计划,影响了您的宝贵时间,对此我们深表遗憾并承担全部责任。
```
### 案例3智能关怀方案
**输入**
```
用户偏好问卷结果:
- 对各服务环节关注度评分3分中等
- 沟通渠道偏好:短信为核心
```
**系统分析**
```
- 用户最关心的问题:服务态度、延误、客服支持、取消、飞机状况
- 问题优先级:按关注度排序
```
**智能关怀方案**
```
1. 方案概述:
为对各服务环节保持中等关注度的用户,提供以短信为核心沟通渠道的均衡关怀服务,重点聚焦前五大关注问题。
2. 关怀措施:
- 针对高关注度问题的具体关怀措施
3. 实施优先级:
- P0最高优先级立即实施
- P1高优先级短期部署
- P2中优先级中期规划
4. 预期效果:
提升用户整体出行体验与安全感,建立稳定可靠的服务感知。
```
## 🔧 项目结构
```
GXX-ProjectName/
├── data/ # 数据目录
│ ├── Tweets.csv # 原始推文数据集
│ └── processed_tweets.csv # 处理后的数据集
├── final_models/ # 训练好的模型
│ ├── crisis_index_model.pkl
│ ├── propagation_risk_model.pkl
│ └── trend_analysis_model.pkl
├── src/ # 源代码目录
│ ├── advanced_xgboost_optimization.py
│ ├── airline_oscars_app.py
│ ├── analyze_tweets.py
│ ├── crisis_index_calculator.py
│ ├── crisis_warning_app.py
│ ├── data_driven_smart_care_app.py
│ ├── data_overview.py
│ ├── deepseek_integrator.py
│ ├── diagnose_churn_system.py
│ ├── enhanced_sentiment_analyzer.py
│ ├── final_test_airline.py
│ ├── machine_learning.py
│ ├── model_evaluation.py
│ ├── propagation_risk_assessment.py
│ ├── smart_care_system.py
│ ├── smart_customer_service.py
│ ├── streamlit_app.py
│ ├── trend_analysis.py
│ ├── ultimate_xgboost_optimization.py
│ └── xgboost_analysis.py
├── tests/ # 测试目录
│ └── test_data.py
├── .env.example # 环境变量示例
├── .gitignore # Git忽略文件
├── pyproject.toml # 项目配置
├── requirements.txt # 依赖列表
├── start_app.bat # 启动脚本Windows
└── README.md # 项目说明文档
```
## 💡 开发心得
### 主要困难与解决方案
**1. 文本数据预处理**
- 问题:推文数据包含大量噪声(表情符号、链接、特殊字符等)
- 解决方案使用正则表达式进行清洗结合NLTK和spaCy进行文本预处理
**2. 类别不平衡**
- 问题推文中positive、negative、neutral样本比例不平衡
- 解决方案采用SMOTE过采样技术调整类别权重使用F1-score作为主要评估指标
**3. 实时性能**
- 问题:大规模推文数据的实时处理和分析
- 解决方案:优化模型结构,使用特征选择减少特征维度,实现批量处理机制
**4. 危机指数计算**
- 问题:如何综合多种因素计算合理的危机指数
- 解决方案:使用加权平均方法,结合专家知识和机器学习模型确定权重
### AI辅助编程的应用
在项目开发过程中我们充分利用了AI辅助编程工具如GitHub Copilot、ChatGPT等主要应用在以下方面
1. **代码生成**:快速生成重复代码和基础结构
2. **算法实现**:辅助实现复杂的机器学习算法和优化策略
3. **调试帮助**:提供错误分析和调试建议
4. **文档编写**:辅助生成代码注释和技术文档
5. **创意启发**:提供新的思路和解决方案
### 未来改进方向
1. **多语言支持**:扩展系统支持多种语言的推文分析
2. **实时数据流处理**集成Kafka等工具实现实时数据流处理
3. **深度学习模型**引入BERT、GPT等预训练语言模型提升情感分析效果
4. **多模态分析**:结合图片和视频内容进行综合分析
5. **自动化响应**:实现自动生成客服响应和危机公关文案的功能
6. **移动端应用**:开发移动端应用,方便随时随地监控
## 📄 许可证
本项目仅供学习和研究使用。
---
**项目地址**http://hblu.top:3000/MachineLearning2025/08_17-AirCARE.git
**联系方式**:如有问题或建议,请联系项目团队成员。

View File

@ -0,0 +1,167 @@
"""Agent 实现模块 - 整合多个工具进行决策"""
from typing import List, Dict, Any, Optional
from deepseek_integrator import DeepSeekIntegrator
from polars_data_processor import PolarsDataProcessor, SentimentPrediction
from enhanced_sentiment_analyzer import EnhancedAirlineSentimentAnalyzer
class AirlineCrisisAgent:
"""航空公司危机处理Agent"""
def __init__(self, data_path: str):
"""初始化Agent"""
self.data_processor = PolarsDataProcessor(data_path)
self.deepseek_integrator = DeepSeekIntegrator()
self.sentiment_analyzer = EnhancedAirlineSentimentAnalyzer()
self.tools = {
"analyze_sentiment": self.analyze_sentiment,
"explain_risk_factors": self.explain_risk_factors,
"generate_crisis_plan": self.generate_crisis_plan,
"customer_service_agent": self.customer_service_agent
}
def analyze_sentiment(self, tweet_text: str, context: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""分析情感与危机评估"""
# 使用情感分析器
result = self.sentiment_analyzer.analyze_sentiment(tweet_text)
# 计算危机等级
risk_level = "low"
if result["sentiment"] == "negative" and result["confidence"] > 0.7:
risk_level = "high"
elif result["sentiment"] == "negative":
risk_level = "medium"
return {
"sentiment": result["sentiment"],
"confidence": result["confidence"],
"risk_level": risk_level,
"crisis_level": "紧急" if risk_level == "high" else "中等" if risk_level == "medium" else ""
}
def explain_risk_factors(self, tweet_text: str, sentiment_result: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""解释风险影响因素"""
if not sentiment_result:
sentiment_result = self.analyze_sentiment(tweet_text)
# 识别风险因素
risk_factors = []
# 检查关键词
negative_keywords = ["延误", "取消", "行李", "丢失", "服务", "态度", "", "糟糕"]
for keyword in negative_keywords:
if keyword in tweet_text:
risk_factors.append({
"因素": keyword,
"权重": 0.2
})
# 基于情感强度
if sentiment_result["confidence"] > 0.8:
risk_factors.append({
"因素": "情感强度高",
"权重": 0.3
})
return {
"risk_factors": risk_factors,
"total_risk_score": sum(factor["权重"] for factor in risk_factors)
}
def generate_crisis_plan(self, issue_type: str, severity: str) -> Dict[str, Any]:
"""生成危机处置方案"""
# 使用DeepSeek生成危机处置方案
event_details = f"问题类型: {issue_type}, 严重程度: {severity}"
pr_statement = self.deepseek_integrator.generate_pr_statement(event_details)
return {
"问题分类": issue_type,
"严重程度": severity,
"处置方案": pr_statement,
"建议措施": [
"立即联系乘客说明情况",
"启动相应的应急机制",
"提供合理的赔偿方案",
"后续跟进确保问题解决"
]
}
def customer_service_agent(self, customer_feedback: str, history: Optional[List[str]] = None) -> str:
"""智能客服响应"""
# 分析情感
sentiment_result = self.analyze_sentiment(customer_feedback)
# 生成客服响应
prompt = f"""
请根据以下客户反馈生成智能客服响应
客户反馈{customer_feedback}
情感分析结果{sentiment_result["sentiment"]}
情感置信度{sentiment_result["confidence"]}
请生成一个专业友好的客服响应包括
1. 对客户反馈的理解
2. 相应的解决方案
3. 后续跟进措施
请使用中文回复
"""
# 使用DeepSeek生成响应
response = self.deepseek_integrator._call_api(prompt)
return response["choices"][0]["message"]["content"]
def run(self, tweet_text: str) -> Dict[str, Any]:
"""运行完整的决策流程"""
# 1. 分析情感
sentiment_result = self.analyze_sentiment(tweet_text)
# 2. 解释风险因素
risk_result = self.explain_risk_factors(tweet_text, sentiment_result)
# 3. 生成危机处置方案
issue_type = "服务质量" if "服务" in tweet_text else "航班延误" if "延误" in tweet_text else "其他问题"
severity = "严重" if sentiment_result["risk_level"] == "high" else "中等" if sentiment_result["risk_level"] == "medium" else "轻微"
crisis_plan = self.generate_crisis_plan(issue_type, severity)
# 4. 生成客服响应
cs_response = self.customer_service_agent(tweet_text)
return {
"sentiment_analysis": sentiment_result,
"risk_analysis": risk_result,
"crisis_plan": crisis_plan,
"customer_service_response": cs_response
}
# 示例用法
if __name__ == "__main__":
print("初始化航空公司危机处理Agent...")
agent = AirlineCrisisAgent("../data/Tweets.csv")
print("Agent初始化完成!")
# 测试案例
test_tweet = "我的航班延误了4个小时行李还丢失了客服态度极差"
print(f"\n测试推文: {test_tweet}")
# 运行Agent
result = agent.run(test_tweet)
print("\n=== 情感分析结果 ===")
print(f"情感倾向: {result['sentiment_analysis']['sentiment']}")
print(f"置信度: {result['sentiment_analysis']['confidence']}")
print(f"危机等级: {result['sentiment_analysis']['crisis_level']}")
print("\n=== 风险因素分析 ===")
for factor in result['risk_analysis']['risk_factors']:
print(f"{factor['因素']}: 权重 {factor['权重']}")
print("\n=== 危机处置方案 ===")
print(f"问题分类: {result['crisis_plan']['问题分类']}")
print(f"严重程度: {result['crisis_plan']['严重程度']}")
print("建议措施:")
for measure in result['crisis_plan']['建议措施']:
print(f"- {measure}")
print("\n=== 智能客服响应 ===")
print(result['customer_service_response'])

View File

@ -335,7 +335,74 @@ class CrisisWarningApp:
def run(self):
"""运行Streamlit应用"""
st.title(self.app_title)
import streamlit as st
# 航空主题样式
st.markdown("""
<style>
/* 全局样式 */
[data-testid="stAppViewContainer"] {
background: linear-gradient(135deg, #e6f7ff 0%, #f0f8ff 100%);
}
/* 标题样式 */
[data-testid="stTitle"] {
color: #0066cc !important;
font-weight: bold !important;
text-align: center;
padding: 20px 0;
}
/* 子标题样式 */
.subheader {
color: #004080 !important;
border-left: 4px solid #0066cc;
padding-left: 12px;
margin: 20px 0 10px 0;
font-size: 1.5rem !important;
font-weight: 600 !important;
}
/* 指标卡片样式 */
[data-testid="stMetric"] {
background: white;
border-radius: 10px;
padding: 15px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* 按钮样式 */
[data-testid="stButton"]>button {
background-color: #0066cc !important;
color: white !important;
border-radius: 8px !important;
border: none !important;
padding: 8px 20px !important;
}
/* 表格样式 */
[data-testid="stDataFrame"] {
border-radius: 8px !important;
overflow: hidden !important;
}
/* 标签页样式 */
[data-testid="stTab"] {
background-color: #e6f7ff !important;
color: #0066cc !important;
border-radius: 8px 8px 0 0 !important;
padding: 8px 20px !important;
}
/* 激活的标签页 */
[data-testid="stTab"][aria-selected="true"] {
background-color: #0066cc !important;
color: white !important;
}
</style>
""", unsafe_allow_html=True)
st.title("⚠️ 云端危机公关")
# 只保留整合危机分析模块
self._show_integrated_analysis()
@ -496,7 +563,7 @@ class CrisisWarningApp:
def _show_integrated_analysis(self):
"""展示整合分析功能,接收用户输入并生成综合分析结果"""
st.header("🔍 整合危机分析与公关方案")
st.markdown("<h2 class='subheader'>🔍 整合危机分析与公关方案</h2>", unsafe_allow_html=True)
# 使用标签页分离输入和历史记录
tab1, tab2 = st.tabs(["📝 输入分析", "📜 历史记录"])
@ -548,7 +615,7 @@ class CrisisWarningApp:
self._display_integrated_result(result)
with tab2:
st.subheader("📜 历史分析记录")
st.markdown("<h3 class='subheader'>📜 历史分析记录</h3>", unsafe_allow_html=True)
if not st.session_state.analysis_history:
st.info("暂无历史分析记录")
@ -639,8 +706,10 @@ class CrisisWarningApp:
def _display_integrated_result(self, result):
"""显示整合分析结果"""
st.markdown("<h2 class='subheader'>📊 分析结果</h2>", unsafe_allow_html=True)
# 1. 危机分析结果
st.subheader("⚠️ 危机分析结果")
st.markdown("<h3 class='subheader'>⚠️ 危机分析结果</h3>", unsafe_allow_html=True)
col1, col2 = st.columns(2)
with col1:
@ -649,14 +718,20 @@ class CrisisWarningApp:
st.metric("危机风险等级", result['crisis_analysis']['risk_level'])
# 2. 传播风险评估
st.subheader("📈 传播风险评估")
st.markdown("<h3 class='subheader'>📈 传播风险评估</h3>", unsafe_allow_html=True)
st.metric("传播风险等级", result['propagation_analysis']['risk_level'])
# 4. 危机公关方案
st.subheader("📝 危机公关方案")
st.markdown("<h3 class='subheader'>📝 危机公关方案</h3>", unsafe_allow_html=True)
st.text_area("生成的公关声明", result['ai_solutions']['pr_statement'], height=300)
# 风险等级解释
if result['crisis_analysis']['risk_level'] == "高风险":
st.warning("⚠️ 此事件具有较高的危机风险,建议立即采取应对措施")
elif result['crisis_analysis']['risk_level'] == "中风险":
st.info(" 此事件具有中等危机风险,需要密切关注")
else:
st.success("✅ 此事件风险较低,可常规处理")
def _show_ai_assistant(self):
"""展示AI辅助决策功能"""

View File

@ -20,12 +20,156 @@ st.set_page_config(
layout="wide"
)
# 航空主题样式
st.markdown("""
<style>
/* 全局样式 */
[data-testid="stAppViewContainer"] {
background: linear-gradient(135deg, #e6f7ff 0%, #f0f8ff 100%);
}
/* 标题样式 */
[data-testid="stTitle"] {
color: #0066cc !important;
font-weight: bold !important;
text-align: center;
padding: 20px 0;
}
/* 子标题样式 */
.subheader {
color: #004080 !important;
border-left: 4px solid #0066cc;
padding-left: 12px;
margin: 20px 0 10px 0;
font-size: 1.5rem !important;
font-weight: 600 !important;
position: relative;
}
.subheader::before {
content: "";
position: absolute;
left: -20px;
top: 0;
color: #0066cc;
}
/* 卡片样式 */
.card {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
margin-bottom: 24px;
border-top: 4px solid #0066cc;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px rgba(0,0,0,0.12);
}
/* 按钮样式 */
[data-testid="stButton"]>button {
background: linear-gradient(135deg, #0066cc 0%, #004080 100%) !important;
color: white !important;
border-radius: 8px !important;
border: none !important;
padding: 10px 24px !important;
font-weight: 600 !important;
transition: all 0.3s ease !important;
}
[data-testid="stButton"]>button:hover {
transform: translateY(-1px) !important;
box-shadow: 0 4px 8px rgba(0,102,204,0.3) !important;
}
/* 进度条样式 */
[data-testid="stProgress"]>div>div {
background: linear-gradient(90deg, #0066cc 0%, #0099ff 100%) !important;
border-radius: 4px !important;
}
/* 滑块样式 */
[data-testid="stSlider"]>div>div {
background-color: #e6f7ff !important;
}
[data-testid="stSlider"]>div>div>div {
background: linear-gradient(135deg, #0066cc 0%, #0099ff 100%) !important;
border: 2px solid white !important;
box-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
}
/* 多选框样式 */
[data-testid="stMultiSelect"]>div>div {
background: white !important;
border-radius: 8px !important;
box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important;
border: 1px solid #e6f7ff !important;
}
/* 信息提示样式 */
[data-testid="stInfo"] {
background: linear-gradient(135deg, #e6f7ff 0%, #f0f8ff 100%) !important;
border-left: 4px solid #0066cc !important;
border-radius: 8px !important;
box-shadow: 0 2px 4px rgba(0,0,0,0.08) !important;
}
/* 成功提示样式 */
[data-testid="stSuccess"] {
background: linear-gradient(135deg, #e6f7ff 0%, #f0f8ff 100%) !important;
border-left: 4px solid #0066cc !important;
border-radius: 8px !important;
box-shadow: 0 2px 4px rgba(0,0,0,0.08) !important;
}
/* 错误提示样式 */
[data-testid="stError"] {
background: linear-gradient(135deg, #fff0f0 0%, #ffe6e6 100%) !important;
border-left: 4px solid #ff4444 !important;
border-radius: 8px !important;
box-shadow: 0 2px 4px rgba(0,0,0,0.08) !important;
}
/* 页脚样式 */
footer {
background: linear-gradient(135deg, #004080 0%, #0066cc 100%) !important;
color: white !important;
padding: 20px !important;
border-radius: 8px !important;
margin-top: 40px !important;
}
/* 问卷问题样式 */
.question-item {
background: #f8faff;
border-radius: 8px;
padding: 16px;
margin-bottom: 12px;
border-left: 3px solid #0066cc;
}
/* 关怀方案展示样式 */
.care-plan {
background: linear-gradient(135deg, #f8faff 0%, #e6f7ff 100%);
border-radius: 12px;
padding: 24px;
border: 1px solid #b3d9ff;
box-shadow: 0 2px 8px rgba(0,102,204,0.1);
}
</style>
""", unsafe_allow_html=True)
# 页面标题
st.markdown('❤️ 数据驱动的智能关怀方案生成系统')
st.markdown('<h1 style="color: #0066cc; text-align: center; font-weight: bold; padding: 20px 0;">❤️ 数据驱动的智能关怀方案生成系统</h1>', unsafe_allow_html=True)
# 系统介绍
st.markdown("### 系统概述")
st.markdown("本系统基于真实推文数据分析,总结出用户最关心的问题,为用户生成个性化的关怀方案。")
st.markdown('<div class="card"><h2 class="subheader">系统概述</h2><p>本系统基于真实推文数据分析,总结出用户最关心的问题,为用户生成个性化的关怀方案。</p></div>', unsafe_allow_html=True)
# 显示数据来源说明
st.info(
@ -50,10 +194,10 @@ common_problems = [
]
# step 1 :用户偏好问卷
st.markdown("## 📝 步骤1用户偏好问卷")
st.markdown('<div class="card"><h2 class="subheader">📝 步骤1用户偏好问卷</h2></div>', unsafe_allow_html=True)
# 基本问题
st.markdown("**请对以下服务问题的关注度评分1-5分1分最低5分最高**")
st.markdown('<div class="card"><h3 style="color: #004080;">请对以下服务问题的关注度评分1-5分1分最低5分最高</h3></div>', unsafe_allow_html=True)
# 使用动态列布局,根据屏幕宽度自动调整
if st.session_state.get('columns') is None:
@ -75,7 +219,7 @@ for i, problem in enumerate(common_problems):
)
# 其他问题
st.markdown("### 其他问题:")
st.markdown('<div class="card"><h3 style="color: #004080;">其他问题:</h3></div>', unsafe_allow_html=True)
communication_channels = st.multiselect(
"您希望航空公司如何与您沟通服务问题?",
@ -90,7 +234,7 @@ user_responses = {
}
# step 2生成关怀方案
st.markdown("## 🎯 步骤2生成关怀方案")
st.markdown('<div class="card"><h2 class="subheader">🎯 步骤2生成关怀方案</h2></div>', unsafe_allow_html=True)
if st.button("生成专属关怀方案", type="primary", use_container_width=True):
with st.spinner("正在调用智能分析模型生成个性化关怀方案..."):
@ -130,26 +274,26 @@ if st.button("生成专属关怀方案", type="primary", use_container_width=Tru
if care_plan:
st.success("个性化关怀方案生成完成!")
# 显示用户最关心的问题
st.markdown("### 👤 您最关心的问题")
# 显示用户最关心的问题和优先级权重
col1, col2 = st.columns(2)
with col1:
st.markdown('<div class="card"><h3 style="color: #004080;">👤 您最关心的问题</h3></div>', unsafe_allow_html=True)
for i, (problem, score) in enumerate(top_problems, 1):
st.write(f"{i}. {problem}: {score}/5分")
# 显示优先级权重分布
with col2:
st.markdown("### ⚖️ 问题优先级权重")
for problem, weight in sorted(priority_weights.items(), key=lambda x: x[1], reverse=True):
st.markdown('<div class="card"><h3 style="color: #004080;">⚖️ 问题优先级权重</h3></div>', unsafe_allow_html=True)
for problem, weight in sorted(priority_weights.items(), key=lambda x: x[1], reverse=True)[:5]:
st.progress(weight, text=f"{problem}: {weight*100:.1f}%")
# 显示生成的关怀方案
st.markdown("### 🎁 个性化关怀方案")
st.markdown(care_plan)
st.markdown('<div class="card"><h3 class="subheader">🎁 个性化关怀方案</h3></div>', unsafe_allow_html=True)
st.markdown(f'<div class="care-plan">{care_plan}</div>', unsafe_allow_html=True)
else:
st.error("方案生成失败,请稍后重试。")
st.info("如果问题持续存在可能是网络连接问题或API调用限制。")
# 页脚
st.markdown("---")
st.markdown("© 2026 数据驱动的智能关怀方案生成系统 | 基于真实推文数据分析")
st.markdown('<footer><p style="text-align: center; color: white; margin: 0;">© 2026 数据驱动的智能关怀方案生成系统 | 基于真实推文数据分析</p></footer>', unsafe_allow_html=True)

View File

@ -223,13 +223,64 @@ def show_data_overview():
"""显示数据概览"""
import streamlit as st
st.title("📊 航空公司情感分析数据概览")
# 航空主题样式 - 使用更强大的CSS选择器
st.markdown("""
<style>
/* 全局样式 */
[data-testid="stAppViewContainer"] {
background: linear-gradient(135deg, #e6f7ff 0%, #f0f8ff 100%);
}
/* 标题样式 */
[data-testid="stTitle"] {
color: #0066cc !important;
font-weight: bold !important;
text-align: center;
padding: 20px 0;
}
/* 子标题样式 */
.subheader {
color: #004080 !important;
border-left: 4px solid #0066cc;
padding-left: 12px;
margin: 20px 0 10px 0;
font-size: 1.5rem !important;
font-weight: 600 !important;
}
/* 指标卡片样式 */
[data-testid="stMetric"] {
background: white;
border-radius: 10px;
padding: 15px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* 按钮样式 */
[data-testid="stButton"]>button {
background-color: #0066cc !important;
color: white !important;
border-radius: 8px !important;
border: none !important;
padding: 8px 20px !important;
}
/* 表格样式 */
[data-testid="stDataFrame"] {
border-radius: 8px !important;
overflow: hidden !important;
}
</style>
""", unsafe_allow_html=True)
st.title("✈️ 航空公司情感分析数据概览")
# 初始化数据概览器
overview = DataOverview()
# 基本信息
st.subheader("📋 数据基本信息")
st.markdown("<h2 class='subheader'>📋 数据基本信息</h2>", unsafe_allow_html=True)
basic_info = overview.get_basic_info()
col1, col2 = st.columns(2)
@ -239,7 +290,7 @@ def show_data_overview():
st.metric("特征数量", basic_info['total_columns'])
# 情感分布
st.subheader("😊 情感分布分析")
st.markdown("<h2 class='subheader'>😊 情感分布分析</h2>", unsafe_allow_html=True)
sentiment_info = overview.get_sentiment_distribution()
col1, col2, col3 = st.columns(3)
@ -253,20 +304,18 @@ def show_data_overview():
st.plotly_chart(fig_pie, use_container_width=True)
# 航空公司情感分布
st.subheader("✈️ 航空公司情感分布")
st.markdown("<h2 class='subheader'>✈️ 航空公司情感分布</h2>", unsafe_allow_html=True)
fig_airline = overview.create_sentiment_by_airline_chart()
st.plotly_chart(fig_airline, use_container_width=True)
# 时间序列分析
st.subheader("⏰ 时间趋势分析")
st.markdown("<h2 class='subheader'>⏰ 时间趋势分析</h2>", unsafe_allow_html=True)
fig_time = overview.create_time_series_analysis()
if fig_time:
st.plotly_chart(fig_time, use_container_width=True)
# 转发分析
st.subheader("🔄 转发行为分析")
st.markdown("<h2 class='subheader'>🔄 转发行为分析</h2>", unsafe_allow_html=True)
fig_retweet, retweet_stats = overview.create_retweet_analysis()
if fig_retweet:
st.plotly_chart(fig_retweet, use_container_width=True)
@ -277,7 +326,7 @@ def show_data_overview():
st.dataframe(pd.DataFrame(retweet_stats).T)
# 负面原因分析
st.subheader("🔍 负面原因分析")
st.markdown("<h2 class='subheader'>🔍 负面原因分析</h2>", unsafe_allow_html=True)
negative_reasons = overview.get_negative_reasons()
if negative_reasons:
reasons_df = pd.DataFrame(list(negative_reasons.items()), columns=['负面原因', '数量'])

View File

Before

Width:  |  Height:  |  Size: 181 KiB

After

Width:  |  Height:  |  Size: 181 KiB

View File

@ -108,9 +108,9 @@ def run_enhanced_analysis():
# 使用智能路径查找数据文件
data_paths = [
"d:/HuaweiMoveData/Users/马艺洁/Desktop/MLwork/bigwork/data/Tweets.csv",
"data/Tweets.csv",
"../data/Tweets.csv",
"d:/HuaweiMoveData/Users/马艺洁/Desktop/MLwork/bigwork/data/Tweets.csv"
"../data/Tweets.csv"
]
data_path = None
@ -135,7 +135,7 @@ def run_enhanced_analysis():
def show_enhanced_model_evaluation():
"""显示模型评估与优化结果"""
st.subheader("🚀 模型评估与优化")
st.markdown("<h2 class='subheader'>🚀 模型评估与优化</h2>", unsafe_allow_html=True)
# 创建选项卡
tab1, tab2 = st.tabs(["📊 基础模型对比", "⚡ XGBoost优化分析"])
@ -321,7 +321,7 @@ def show_enhanced_model_evaluation():
def show_basic_model_evaluation():
"""显示数据Schema"""
st.subheader("📋 数据Schema")
st.markdown("<h2 class='subheader'>📋 数据Schema</h2>", unsafe_allow_html=True)
st.markdown("""
📋 PANDERA SCHEMA 结构
@ -373,7 +373,74 @@ def show_basic_model_evaluation():
def show_model_evaluation():
"""显示模型评估界面"""
st.title("📊 模型评估分析")
import streamlit as st
# 航空主题样式
st.markdown("""
<style>
/* 全局样式 */
[data-testid="stAppViewContainer"] {
background: linear-gradient(135deg, #e6f7ff 0%, #f0f8ff 100%);
}
/* 标题样式 */
[data-testid="stTitle"] {
color: #0066cc !important;
font-weight: bold !important;
text-align: center;
padding: 20px 0;
}
/* 子标题样式 */
.subheader {
color: #004080 !important;
border-left: 4px solid #0066cc;
padding-left: 12px;
margin: 20px 0 10px 0;
font-size: 1.5rem !important;
font-weight: 600 !important;
}
/* 指标卡片样式 */
[data-testid="stMetric"] {
background: white;
border-radius: 10px;
padding: 15px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* 按钮样式 */
[data-testid="stButton"]>button {
background-color: #0066cc !important;
color: white !important;
border-radius: 8px !important;
border: none !important;
padding: 8px 20px !important;
}
/* 表格样式 */
[data-testid="stDataFrame"] {
border-radius: 8px !important;
overflow: hidden !important;
}
/* 标签页样式 */
[data-testid="stTab"] {
background-color: #e6f7ff !important;
color: #0066cc !important;
border-radius: 8px 8px 0 0 !important;
padding: 8px 20px !important;
}
/* 激活的标签页 */
[data-testid="stTab"][aria-selected="true"] {
background-color: #0066cc !important;
color: white !important;
}
</style>
""", unsafe_allow_html=True)
st.title("🛠️ 模型评估分析")
# 创建标签页
tab1, tab2 = st.tabs(["数据Schema", "模型评估与优化"])

View File

@ -0,0 +1,126 @@
"""数据处理模块 - 使用 Polars 进行高效数据处理"""
import polars as pl
from pydantic import BaseModel, Field
from typing import List, Optional
import json
class TweetFeatures(BaseModel):
"""推文特征模型"""
tweet_id: str
airline: str
text: str
sentiment: str
confidence: float
negativereason: Optional[str] = None
retweet_count: int
user_name: str
class Config:
"""配置"""
from_attributes = True
class SentimentPrediction(BaseModel):
"""情感预测结果模型"""
tweet_id: str
predicted_sentiment: str
confidence_score: float
risk_level: str
risk_factors: List[str]
class PolarsDataProcessor:
"""使用 Polars 进行数据处理的类"""
def __init__(self, data_path: str):
"""初始化"""
self.data_path = data_path
self.df = None
def load_data(self) -> pl.DataFrame:
"""加载数据"""
self.df = pl.read_csv(self.data_path)
return self.df
def preprocess_data(self) -> pl.DataFrame:
"""预处理数据"""
if self.df is None:
self.load_data()
# 选择相关列
processed_df = self.df.select([
"tweet_id",
"airline",
"text",
"airline_sentiment",
"airline_sentiment_confidence",
"negativereason",
"retweet_count",
"name"
])
# 重命名列
processed_df = processed_df.rename({
"airline_sentiment": "sentiment",
"airline_sentiment_confidence": "confidence",
"name": "user_name"
})
# 处理缺失值
processed_df = processed_df.fill_null({
"negativereason": "Unknown"
})
return processed_df
def extract_features(self, df: pl.DataFrame) -> pl.DataFrame:
"""提取特征"""
# 文本长度特征
df = df.with_columns([
pl.col("text").str.lengths().alias("text_length"),
pl.col("text").str.count_matches(r"\b(?:delay|cancel|lost|baggage|late)\b", case_sensitive=False).alias("negative_keywords_count")
])
return df
def convert_to_pydantic(self, df: pl.DataFrame) -> List[TweetFeatures]:
"""转换为 Pydantic 模型列表"""
records = df.to_dicts()
return [TweetFeatures(**record) for record in records]
def batch_process(self, batch_size: int = 1000) -> List[SentimentPrediction]:
"""批量处理数据"""
processed_df = self.preprocess_data()
features_df = self.extract_features(processed_df)
# 模拟预测结果
predictions = []
for row in features_df.iter_rows(named=True):
prediction = SentimentPrediction(
tweet_id=str(row["tweet_id"]),
predicted_sentiment=row["sentiment"],
confidence_score=row["confidence"],
risk_level="high" if row["sentiment"] == "negative" else "low",
risk_factors=["negative sentiment"] if row["sentiment"] == "negative" else []
)
predictions.append(prediction)
return predictions
# 示例用法
if __name__ == "__main__":
processor = PolarsDataProcessor("../data/Tweets.csv")
df = processor.load_data()
print(f"Loaded {len(df)} tweets")
processed_df = processor.preprocess_data()
print(f"Processed data shape: {processed_df.shape}")
features_df = processor.extract_features(processed_df)
print(f"Features extracted: {features_df.columns}")
samples = processor.convert_to_pydantic(features_df.head(5))
print(f"Converted to Pydantic models: {len(samples)}")
predictions = processor.batch_process(batch_size=10)
print(f"Generated {len(predictions)} predictions")
print(json.dumps(predictions[0].model_dump(), ensure_ascii=False, indent=2))

View File

@ -17,7 +17,10 @@ from enhanced_sentiment_analyzer import EnhancedAirlineSentimentAnalyzer
from machine_learning import FeatureEngineering, MachineLearningPipeline
# DeepSeek API配置
DEEPSEEK_API_KEY = "sk-eb8cc78f22ef443491d4199e56bde9a7"
import os
from dotenv import load_dotenv
load_dotenv()
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY", "")
DEEPSEEK_API_BASE = "https://api.deepseek.com"
# 尝试导入DeepSeek相关库
@ -1855,7 +1858,7 @@ class SmartCustomerService:
def show_chat_interface(customer_service: SmartCustomerService):
"""显示对话界面,基于流失分析结果生成响应"""
st.subheader("💬 智能客服对话")
st.markdown("<h2 class='subheader'>💬 智能客服对话</h2>", unsafe_allow_html=True)
# 检查是否有流失分析结果
if 'current_analysis' not in st.session_state:
@ -1931,8 +1934,7 @@ def show_chat_interface(customer_service: SmartCustomerService):
def show_churn_analysis(customer_service: SmartCustomerService):
"""显示流失分析界面支持手动输入用户ID和内容"""
st.subheader("📊 用户流失分析")
st.markdown("---")
st.markdown("<h2 class='subheader'>📊 用户流失分析</h2>", unsafe_allow_html=True)
# 模型训练状态
st.markdown("### 🤖 模型状态")
@ -2120,7 +2122,7 @@ def show_churn_analysis(customer_service: SmartCustomerService):
def show_system_settings(customer_service: SmartCustomerService):
"""显示系统设置界面"""
st.subheader("⚙️ 系统设置")
st.markdown("<h2 class='subheader'>⚙️ 系统设置</h2>", unsafe_allow_html=True)
st.markdown("### 🔧 模型配置")
st.info("当前使用优化后的XGBoost模型进行流失预测")
@ -2149,12 +2151,117 @@ def show_system_settings(customer_service: SmartCustomerService):
def show_smart_customer_service():
"""显示智能客服界面"""
st.title("🤖 智能客服系统")
st.markdown("---")
import streamlit as st
# 航空主题样式
st.markdown("""
<style>
/* 全局样式 */
[data-testid="stAppViewContainer"] {
background: linear-gradient(135deg, #e6f7ff 0%, #f0f8ff 100%);
}
/* 标题样式 */
[data-testid="stTitle"] {
color: #0066cc !important;
font-weight: bold !important;
text-align: center;
padding: 20px 0;
}
/* 子标题样式 */
.subheader {
color: #004080 !important;
border-left: 4px solid #0066cc;
padding-left: 12px;
margin: 20px 0 10px 0;
font-size: 1.5rem !important;
font-weight: 600 !important;
}
/* 指标卡片样式 */
[data-testid="stMetric"] {
background: white;
border-radius: 10px;
padding: 15px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* 按钮样式 */
[data-testid="stButton"]>button {
background-color: #0066cc !important;
color: white !important;
border-radius: 8px !important;
border: none !important;
padding: 8px 20px !important;
}
/* 表格样式 */
[data-testid="stDataFrame"] {
border-radius: 8px !important;
overflow: hidden !important;
}
/* 标签页样式 */
[data-testid="stTab"] {
background-color: #e6f7ff !important;
color: #0066cc !important;
border-radius: 8px 8px 0 0 !important;
padding: 8px 20px !important;
}
/* 激活的标签页 */
[data-testid="stTab"][aria-selected="true"] {
background-color: #0066cc !important;
color: white !important;
}
/* 聊天界面样式 */
.user-message {
background-color: #0066cc !important;
color: white !important;
border-radius: 15px 15px 5px 15px !important;
padding: 10px 15px !important;
margin: 5px 0 !important;
max-width: 70% !important;
margin-left: auto !important;
}
.bot-message {
background-color: #f0f8ff !important;
color: #004080 !important;
border-radius: 15px 15px 15px 5px !important;
padding: 10px 15px !important;
margin: 5px 0 !important;
max-width: 70% !important;
border: 1px solid #e6f7ff !important;
}
</style>
""", unsafe_allow_html=True)
st.title("💬 智能客服系统")
# 初始化客服系统
if 'customer_service' not in st.session_state:
st.session_state.customer_service = SmartCustomerService("../data/Tweets.csv")
# 使用智能路径查找数据文件
data_paths = [
"d:/HuaweiMoveData/Users/马艺洁/Desktop/MLwork/bigwork/data/Tweets.csv",
"data/Tweets.csv",
"../data/Tweets.csv"
]
data_path = None
for path in data_paths:
import os
if os.path.exists(path):
data_path = path
break
if data_path is None:
st.error("无法找到数据文件请检查Tweets.csv文件位置")
return
st.session_state.customer_service = SmartCustomerService(data_path)
customer_service = st.session_state.customer_service

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,24 @@ def load_and_prepare_data():
"""加载和准备数据"""
from enhanced_sentiment_analyzer import EnhancedAirlineSentimentAnalyzer
df = pd.read_csv('../data/Tweets.csv')
# 使用智能路径查找数据文件
data_paths = [
"d:/HuaweiMoveData/Users/马艺洁/Desktop/MLwork/bigwork/data/Tweets.csv",
"data/Tweets.csv",
"../data/Tweets.csv"
]
data_path = None
for path in data_paths:
import os
if os.path.exists(path):
data_path = path
break
if data_path is None:
raise FileNotFoundError("无法找到数据文件请检查Tweets.csv文件位置")
df = pd.read_csv(data_path)
analyzer = EnhancedAirlineSentimentAnalyzer(random_state=42)
features, y = analyzer.prepare_features(df)