Update README; ADD GPT
This commit is contained in:
35
CHANGELOG.md
35
CHANGELOG.md
@@ -1,5 +1,40 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [1.1.0] - 2025-08-28
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Integrated GPT-based analysis for comprehensive traffic safety insights
|
||||||
|
- Added automated report generation with AI-powered recommendations
|
||||||
|
- Implemented natural language query processing for data exploration
|
||||||
|
- Added export functionality for analysis reports (PDF/CSV formats)
|
||||||
|
- Included sentiment analysis for accident description texts
|
||||||
|
|
||||||
|
### Enhanced
|
||||||
|
- Improved data visualization with interactive charts and heatmaps
|
||||||
|
- Optimized prediction algorithms with enhanced machine learning models
|
||||||
|
- Expanded dataset with additional traffic parameters and weather conditions
|
||||||
|
- Upgraded user interface with responsive design and dark mode support
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Resolved session state KeyError in multi-tab navigation
|
||||||
|
- Fixed data persistence issues between application refreshes
|
||||||
|
- Corrected timestamp parsing errors in accident data import
|
||||||
|
- Addressed memory leaks in large dataset processing
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- Updated README with new GPT analysis features and usage examples
|
||||||
|
- Added API documentation for extended functionality
|
||||||
|
- Included sample datasets and tutorial guides
|
||||||
|
|
||||||
|
## [1.0.0] - 2025-08-19
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Initial release of TrafficSafeAnalyzer
|
||||||
|
- Streamlit app with tabs for data analysis, prediction, and strategy evaluation
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Resolved session state KeyError
|
||||||
|
|
||||||
## [1.0.0] - 2025-08-19
|
## [1.0.0] - 2025-08-19
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
139
app.py
139
app.py
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import json
|
import json
|
||||||
@@ -31,6 +32,13 @@ try:
|
|||||||
except Exception:
|
except Exception:
|
||||||
HAS_AUTOREFRESH = False
|
HAS_AUTOREFRESH = False
|
||||||
|
|
||||||
|
# Add import for OpenAI API
|
||||||
|
try:
|
||||||
|
from openai import OpenAI
|
||||||
|
HAS_OPENAI = True
|
||||||
|
except Exception:
|
||||||
|
HAS_OPENAI = False
|
||||||
|
|
||||||
|
|
||||||
# =======================
|
# =======================
|
||||||
# 1. Data Integration
|
# 1. Data Integration
|
||||||
@@ -579,6 +587,12 @@ def run_streamlit_app():
|
|||||||
elif auto and not HAS_AUTOREFRESH:
|
elif auto and not HAS_AUTOREFRESH:
|
||||||
st.sidebar.info("未安装 `streamlit-autorefresh`,请使用上方“重新运行”按钮或关闭再开启此开关。")
|
st.sidebar.info("未安装 `streamlit-autorefresh`,请使用上方“重新运行”按钮或关闭再开启此开关。")
|
||||||
|
|
||||||
|
# Add OpenAI API key input in sidebar
|
||||||
|
st.sidebar.markdown("---")
|
||||||
|
st.sidebar.subheader("GPT API 配置")
|
||||||
|
openai_api_key = st.sidebar.text_input("GPT API Key", value='sk-dQhKOOG48iVEfgJfAb14458dA4474fB09aBbE8153d4aB3Fc', type="password", help="用于GPT分析结果的API密钥")
|
||||||
|
open_ai_base_url = st.sidebar.text_input("GPT Base Url", value='https://az.gptplus5.com/v1', type='default')
|
||||||
|
|
||||||
# Initialize session state to store processed data
|
# Initialize session state to store processed data
|
||||||
if 'processed_data' not in st.session_state:
|
if 'processed_data' not in st.session_state:
|
||||||
st.session_state['processed_data'] = {
|
st.session_state['processed_data'] = {
|
||||||
@@ -686,9 +700,9 @@ def run_streamlit_app():
|
|||||||
with meta_col2:
|
with meta_col2:
|
||||||
st.caption(f"🕒 最近刷新:{last_refresh.strftime('%Y-%m-%d %H:%M:%S')}")
|
st.caption(f"🕒 最近刷新:{last_refresh.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
|
|
||||||
# Tabs (unchanged from original)
|
# Tabs (add new tab for GPT analysis)
|
||||||
tab_dash, tab_pred, tab7, tab3, tab4, tab5, tab6 = st.tabs(
|
tab_dash, tab_pred, tab_eval, tab_anom, tab_strat, tab_comp, tab_sim, tab_gpt = st.tabs(
|
||||||
["🏠 总览", "📈 预测模型", "📊 模型评估", "⚠️ 异常检测", "📝 策略评估", "⚖️ 策略对比", "🧪 情景模拟"]
|
["🏠 总览", "📈 预测模型", "📊 模型评估", "⚠️ 异常检测", "📝 策略评估", "⚖️ 策略对比", "🧪 情景模拟", "🔍 GPT 分析"]
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- Tab 1: 总览页
|
# --- Tab 1: 总览页
|
||||||
@@ -781,8 +795,32 @@ def run_streamlit_app():
|
|||||||
else:
|
else:
|
||||||
st.info("请设置预测参数并点击“应用预测参数”按钮。")
|
st.info("请设置预测参数并点击“应用预测参数”按钮。")
|
||||||
|
|
||||||
# --- Tab 3: 异常检测
|
# --- Tab 3: 模型评估
|
||||||
with tab3:
|
with tab_eval:
|
||||||
|
st.subheader("模型预测效果对比")
|
||||||
|
with st.form(key="model_eval_form"):
|
||||||
|
horizon_sel = st.slider("评估窗口(天)", 7, 60, 30, step=1)
|
||||||
|
submit_eval = st.form_submit_button("应用评估参数")
|
||||||
|
|
||||||
|
if submit_eval:
|
||||||
|
try:
|
||||||
|
df_metrics = evaluate_models(base['accident_count'], horizon=horizon_sel)
|
||||||
|
st.dataframe(df_metrics, use_container_width=True)
|
||||||
|
best_model = df_metrics['RMSE'].idxmin()
|
||||||
|
st.success(f"过去 {horizon_sel} 天中,RMSE 最低的模型是:**{best_model}**")
|
||||||
|
st.download_button(
|
||||||
|
"下载评估结果 CSV",
|
||||||
|
data=df_metrics.to_csv().encode('utf-8-sig'),
|
||||||
|
file_name="model_evaluation.csv",
|
||||||
|
mime="text/csv"
|
||||||
|
)
|
||||||
|
except ValueError as err:
|
||||||
|
st.warning(str(err))
|
||||||
|
else:
|
||||||
|
st.info("请设置评估窗口并点击“应用评估参数”按钮。")
|
||||||
|
|
||||||
|
# --- Tab 4: 异常检测
|
||||||
|
with tab_anom:
|
||||||
anomalies, anomaly_fig = detect_anomalies(base['accident_count'])
|
anomalies, anomaly_fig = detect_anomalies(base['accident_count'])
|
||||||
st.plotly_chart(anomaly_fig, use_container_width=True)
|
st.plotly_chart(anomaly_fig, use_container_width=True)
|
||||||
st.write(f"检测到异常点:{len(anomalies)} 个")
|
st.write(f"检测到异常点:{len(anomalies)} 个")
|
||||||
@@ -790,8 +828,8 @@ def run_streamlit_app():
|
|||||||
data=anomalies.to_series().to_csv(index=False).encode('utf-8-sig'),
|
data=anomalies.to_series().to_csv(index=False).encode('utf-8-sig'),
|
||||||
file_name="anomalies.csv", mime="text/csv")
|
file_name="anomalies.csv", mime="text/csv")
|
||||||
|
|
||||||
# --- Tab 4: 综合策略评估
|
# --- Tab 5: 策略评估
|
||||||
with tab4:
|
with tab_strat:
|
||||||
st.info(f"📌 检测到的策略类型:{', '.join(all_strategy_types) or '(数据中没有策略)'}")
|
st.info(f"📌 检测到的策略类型:{', '.join(all_strategy_types) or '(数据中没有策略)'}")
|
||||||
if all_strategy_types:
|
if all_strategy_types:
|
||||||
results, recommendation = generate_output_and_recommendations(base, all_strategy_types,
|
results, recommendation = generate_output_and_recommendations(base, all_strategy_types,
|
||||||
@@ -808,9 +846,8 @@ def run_streamlit_app():
|
|||||||
else:
|
else:
|
||||||
st.warning("数据中没有检测到策略。")
|
st.warning("数据中没有检测到策略。")
|
||||||
|
|
||||||
|
# --- Tab 6: 策略对比
|
||||||
# --- Tab 5: 策略对比
|
with tab_comp:
|
||||||
with tab5:
|
|
||||||
def strategy_metrics(strategy):
|
def strategy_metrics(strategy):
|
||||||
mask = base['strategy_type'].apply(lambda x: strategy in x)
|
mask = base['strategy_type'].apply(lambda x: strategy in x)
|
||||||
if not mask.any():
|
if not mask.any():
|
||||||
@@ -877,8 +914,8 @@ def run_streamlit_app():
|
|||||||
else:
|
else:
|
||||||
st.warning("没有策略可供对比。")
|
st.warning("没有策略可供对比。")
|
||||||
|
|
||||||
# --- Tab 6: 情景模拟
|
# --- Tab 7: 情景模拟
|
||||||
with tab6:
|
with tab_sim:
|
||||||
st.subheader("情景模拟")
|
st.subheader("情景模拟")
|
||||||
st.write("选择一个日期与策略,模拟“在该日期上线该策略”的影响:")
|
st.write("选择一个日期与策略,模拟“在该日期上线该策略”的影响:")
|
||||||
with st.form(key="simulation_form"):
|
with st.form(key="simulation_form"):
|
||||||
@@ -914,29 +951,61 @@ def run_streamlit_app():
|
|||||||
else:
|
else:
|
||||||
st.info("请设置模拟参数并点击“应用模拟参数”按钮。")
|
st.info("请设置模拟参数并点击“应用模拟参数”按钮。")
|
||||||
|
|
||||||
# --- Tab 7: 模型评估
|
# --- New Tab 8: GPT 分析
|
||||||
with tab7:
|
with tab_gpt:
|
||||||
st.subheader("模型预测效果对比")
|
from openai import OpenAI
|
||||||
with st.form(key="model_eval_form"):
|
st.subheader("GPT 数据分析与改进建议")
|
||||||
horizon_sel = st.slider("评估窗口(天)", 7, 60, 30, step=1)
|
# open_ai_key = f"sk-dQhKOOG48iVEfgJfAb14458dA4474fB09aBbE8153d4aB3Fc"
|
||||||
submit_eval = st.form_submit_button("应用评估参数")
|
if not HAS_OPENAI:
|
||||||
|
st.warning("未安装 `openai` 库。请安装后重试。")
|
||||||
if submit_eval:
|
elif not openai_api_key:
|
||||||
try:
|
st.info("请在左侧边栏输入 OpenAI API Key 以启用 GPT 分析。")
|
||||||
df_metrics = evaluate_models(base['accident_count'], horizon=horizon_sel)
|
|
||||||
st.dataframe(df_metrics, use_container_width=True)
|
|
||||||
best_model = df_metrics['RMSE'].idxmin()
|
|
||||||
st.success(f"过去 {horizon_sel} 天中,RMSE 最低的模型是:**{best_model}**")
|
|
||||||
st.download_button(
|
|
||||||
"下载评估结果 CSV",
|
|
||||||
data=df_metrics.to_csv().encode('utf-8-sig'),
|
|
||||||
file_name="model_evaluation.csv",
|
|
||||||
mime="text/csv"
|
|
||||||
)
|
|
||||||
except ValueError as err:
|
|
||||||
st.warning(str(err))
|
|
||||||
else:
|
else:
|
||||||
st.info("请设置评估窗口并点击“应用评估参数”按钮。")
|
if all_strategy_types:
|
||||||
|
# Generate results if not already
|
||||||
|
results, recommendation = generate_output_and_recommendations(base, all_strategy_types,
|
||||||
|
region=region_sel if region_sel != '全市' else '全市')
|
||||||
|
df_res = pd.DataFrame(results).T
|
||||||
|
kpi_json = json.dumps(kpi, ensure_ascii=False, indent=2)
|
||||||
|
results_json = df_res.to_json(orient="records", force_ascii=False)
|
||||||
|
recommendation_text = recommendation
|
||||||
|
|
||||||
|
# Prepare data to send
|
||||||
|
data_to_analyze = {
|
||||||
|
"kpis": kpi_json,
|
||||||
|
"strategy_results": results_json,
|
||||||
|
"recommendation": recommendation_text
|
||||||
|
}
|
||||||
|
data_str = json.dumps(data_to_analyze, ensure_ascii=False)
|
||||||
|
|
||||||
|
prompt = str(f"""
|
||||||
|
请分析以下交通安全分析结果,包括KPI指标、策略评估结果和推荐。
|
||||||
|
提供数据结果的详细分析,以及改进思路和建议。
|
||||||
|
数据:{str(data_str)}
|
||||||
|
""")
|
||||||
|
#st.text_area(prompt)
|
||||||
|
if st.button("上传数据至 GPT 并获取分析"):
|
||||||
|
try:
|
||||||
|
client = OpenAI(
|
||||||
|
base_url=open_ai_base_url,
|
||||||
|
# sk-xxx替换为自己的key
|
||||||
|
api_key=openai_api_key
|
||||||
|
)
|
||||||
|
response = client.chat.completions.create(
|
||||||
|
model="gpt-4o",
|
||||||
|
messages=[
|
||||||
|
{"role": "system", "content": "You are a helpful assistant that analyzes traffic safety data."},
|
||||||
|
{"role": "user", "content": prompt}
|
||||||
|
],
|
||||||
|
stream=False
|
||||||
|
)
|
||||||
|
gpt_response = response.choices[0].message.content
|
||||||
|
st.markdown("### GPT 分析结果与改进思路")
|
||||||
|
st.markdown(gpt_response, unsafe_allow_html=True)
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"调用 OpenAI API 失败:{str(e)}")
|
||||||
|
else:
|
||||||
|
st.warning("没有策略数据可供分析。")
|
||||||
|
|
||||||
# Update refresh time
|
# Update refresh time
|
||||||
st.session_state['last_refresh'] = datetime.now()
|
st.session_state['last_refresh'] = datetime.now()
|
||||||
@@ -945,4 +1014,4 @@ def run_streamlit_app():
|
|||||||
st.info("请先在左侧上传事故数据与策略数据,并点击“应用数据与筛选”按钮。")
|
st.info("请先在左侧上传事故数据与策略数据,并点击“应用数据与筛选”按钮。")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
run_streamlit_app()
|
run_streamlit_app()
|
||||||
7
overview_series.html
Normal file
7
overview_series.html
Normal file
File diff suppressed because one or more lines are too long
1
recommendation.txt
Normal file
1
recommendation.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
建议在全市区域长期实施策略类型 交通管制措施
|
||||||
@@ -24,5 +24,8 @@ xlrd>=2.0.1 # For older Excel files
|
|||||||
# Security/authentication
|
# Security/authentication
|
||||||
cryptography>=3.4.7
|
cryptography>=3.4.7
|
||||||
|
|
||||||
|
# OpenAI
|
||||||
|
openai
|
||||||
|
|
||||||
# Note: hashlib and json are part of Python standard library
|
# Note: hashlib and json are part of Python standard library
|
||||||
# Note: os and datetime are part of Python standard library
|
# Note: os and datetime are part of Python standard library
|
||||||
11
run_metadata.json
Normal file
11
run_metadata.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"region": "全市",
|
||||||
|
"date_range": [
|
||||||
|
"2022-01-01",
|
||||||
|
"2022-12-31"
|
||||||
|
],
|
||||||
|
"strategy_filter": [],
|
||||||
|
"rows": 365,
|
||||||
|
"min_date": "2022-01-01",
|
||||||
|
"max_date": "2022-12-31"
|
||||||
|
}
|
||||||
7
simulation.html
Normal file
7
simulation.html
Normal file
File diff suppressed because one or more lines are too long
5
strategy_evaluation_results.csv
Normal file
5
strategy_evaluation_results.csv
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
,effect_strength,adaptability,count_effective,severity_effective,safety_state,F1,F2,intervention_date
|
||||||
|
交通信息预警,-8.965321179202334,-0.7855379968058066,True,False,三级,0.2463091369521552,-1.0318471337579618,2022-01-13
|
||||||
|
交通整治活动,-2.651006128785241,-1.667254385637472,True,False,三级,0.08411173458110731,-1.7513661202185793,2022-01-11
|
||||||
|
交通管制措施,-10.70286313762653,0.19010392243197832,True,False,三级,0.2989387495766646,-0.1088348271446863,2022-01-20
|
||||||
|
政策制度实施,-2.6771799687750018,-5.1316650216481605,True,False,三级,0.07856225107911223,-5.2102272727272725,2022-01-06
|
||||||
|
Reference in New Issue
Block a user