fix(security): 移除硬编码的API密钥并使用环境变量

将硬编码的API密钥替换为从环境变量中读取,并添加未配置时的模拟响应
为Streamlit组件添加唯一key属性以避免重复渲染问题
This commit is contained in:
你的姓名 2026-01-15 23:34:49 +08:00
parent 36316690cc
commit 37f0982809
6 changed files with 53 additions and 10 deletions

View File

@ -573,7 +573,8 @@ class CrisisWarningApp:
user_input = st.text_area( user_input = st.text_area(
"请输入推文内容或事件描述", "请输入推文内容或事件描述",
"", # 默认空白 "", # 默认空白
height=150 height=150,
key="crisis_input_text"
) )
# 自动情感分析 # 自动情感分析
@ -641,7 +642,7 @@ class CrisisWarningApp:
st.metric("传播风险等级", result['propagation_analysis']['risk_level']) st.metric("传播风险等级", result['propagation_analysis']['risk_level'])
st.write("**生成的公关声明:**") st.write("**生成的公关声明:**")
st.text_area("", result['ai_solutions']['pr_statement'], height=100, disabled=True) st.text_area("", result['ai_solutions']['pr_statement'], height=100, disabled=True, key=f"history_pr_{i}")
def _perform_integrated_analysis(self, text_content, retweet_count=0, sentiment="negative"): def _perform_integrated_analysis(self, text_content, retweet_count=0, sentiment="negative"):
"""执行整合分析,调用所有模块并生成综合结果""" """执行整合分析,调用所有模块并生成综合结果"""
@ -723,7 +724,7 @@ class CrisisWarningApp:
# 4. 危机公关方案 # 4. 危机公关方案
st.markdown("<h3 class='subheader'>📝 危机公关方案</h3>", unsafe_allow_html=True) st.markdown("<h3 class='subheader'>📝 危机公关方案</h3>", unsafe_allow_html=True)
st.text_area("生成的公关声明", result['ai_solutions']['pr_statement'], height=300) st.text_area("生成的公关声明", result['ai_solutions']['pr_statement'], height=300, key="result_pr")
# 风险等级解释 # 风险等级解释
if result['crisis_analysis']['risk_level'] == "高风险": if result['crisis_analysis']['risk_level'] == "高风险":
@ -744,7 +745,8 @@ class CrisisWarningApp:
st.subheader("公关声明生成") st.subheader("公关声明生成")
event_details = st.text_area( event_details = st.text_area(
"请输入事件详情", "请输入事件详情",
"因天气原因我公司今日有200多个航班延误影响乘客约3000人" "因天气原因我公司今日有200多个航班延误影响乘客约3000人",
key="event_details"
) )
target_audience = st.text_input("目标受众", "乘客") target_audience = st.text_input("目标受众", "乘客")
tone = st.text_input("语气要求", "道歉且负责任") tone = st.text_input("语气要求", "道歉且负责任")
@ -756,7 +758,7 @@ class CrisisWarningApp:
target_audience, target_audience,
tone tone
) )
st.text_area("生成的公关声明", pr_statement, height=400) st.text_area("生成的公关声明", pr_statement, height=400, key="ai_pr")
# 运行应用 # 运行应用
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -47,7 +47,13 @@ USER_TYPES = {
} }
# DeepSeek API配置 # 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_URL = "https://api.deepseek.com/v1/chat/completions" DEEPSEEK_API_URL = "https://api.deepseek.com/v1/chat/completions"
@ -56,6 +62,21 @@ def call_deepseek_api(prompt: str, max_tokens: int = 500, temperature: float = 0
import time import time
import requests import requests
# 检查API Key是否配置
if not DEEPSEEK_API_KEY:
print("DeepSeek API密钥未配置返回模拟响应")
# 返回模拟响应
if "问题分类" in prompt:
return json.dumps({"primary_category": "其他", "secondary_category": "其他"}, ensure_ascii=False)
elif "用户类型" in prompt:
return json.dumps({
"main_type": "效率型",
"type_probabilities": {"效率型": 0.6, "舒适型": 0.2, "经济型": 0.1, "情感型": 0.1},
"type_characteristics": USER_TYPES["效率型"]
}, ensure_ascii=False)
else:
return "API密钥未配置返回模拟响应。这是一个智能生成的关怀方案描述。"
max_retries = 3 max_retries = 3
retry_delay = 2 retry_delay = 2
timeout = 60 # 增加超时时间到60秒 timeout = 60 # 增加超时时间到60秒

View File

@ -1068,11 +1068,21 @@ class SmartCustomerService:
import requests import requests
import json import json
import os
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
# DeepSeek API配置 # DeepSeek API配置
api_key = "sk-eb8cc78f22ef443491d4199e56bde9a7" api_key = os.getenv("DEEPSEEK_API_KEY")
api_url = "https://api.deepseek.com/v1/chat/completions" api_url = "https://api.deepseek.com/v1/chat/completions"
# 检查API密钥是否配置
if not api_key:
print("DeepSeek API密钥未配置返回默认响应")
return "感谢您的反馈。我们的客服团队将尽快处理您的问题,并与您联系。"
# 构建系统提示 # 构建系统提示
system_prompt = """ system_prompt = """
你是一个专业的航空公司客服助手需要基于用户的反馈和流失分析结果生成结构化的响应 你是一个专业的航空公司客服助手需要基于用户的反馈和流失分析结果生成结构化的响应
@ -1299,11 +1309,21 @@ class SmartCustomerService:
import requests import requests
import json import json
import os
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
# 使用用户提供的DeepSeek API密钥 # 使用用户提供的DeepSeek API密钥
api_key = "sk-eb8cc78f22ef443491d4199e56bde9a7" api_key = os.getenv("DEEPSEEK_API_KEY")
api_url = "https://api.deepseek.com/v1/chat/completions" api_url = "https://api.deepseek.com/v1/chat/completions"
# 检查API密钥是否配置
if not api_key:
print("DeepSeek API密钥未配置返回默认情感分析结果")
return "neutral"
# 构建系统提示 # 构建系统提示
system_prompt = """ system_prompt = """
你是一个专业的情感分析助手需要分析用户反馈的情感倾向 你是一个专业的情感分析助手需要分析用户反馈的情感倾向
@ -1915,7 +1935,7 @@ def show_chat_interface(customer_service: SmartCustomerService):
# 用户输入 # 用户输入
st.markdown("### 💭 请输入您的查询") st.markdown("### 💭 请输入您的查询")
user_query = st.text_area("您的消息", placeholder="请输入您的问题或反馈...", value=user_content) user_query = st.text_area("您的消息", placeholder="请输入您的问题或反馈...", value=user_content, key="user_query")
if st.button("发送", type="primary") and user_query: if st.button("发送", type="primary") and user_query:
with st.spinner("正在分析您的查询并生成响应..."): with st.spinner("正在分析您的查询并生成响应..."):
@ -1961,7 +1981,7 @@ def show_churn_analysis(customer_service: SmartCustomerService):
# 手动输入区域 # 手动输入区域
st.markdown("### 👤 手动输入分析") st.markdown("### 👤 手动输入分析")
user_id = st.text_input("用户ID", placeholder="请输入用户ID例如user_001") user_id = st.text_input("用户ID", placeholder="请输入用户ID例如user_001")
user_content = st.text_area("用户反馈内容", placeholder="请输入用户反馈内容...") user_content = st.text_area("用户反馈内容", placeholder="请输入用户反馈内容...", key="user_feedback")
if st.button("🔍 进行流失分析", type="secondary") and user_id and user_content: if st.button("🔍 进行流失分析", type="secondary") and user_id and user_content:
with st.spinner("正在基于输入内容分析用户流失风险..."): with st.spinner("正在基于输入内容分析用户流失风险..."):