This commit is contained in:
HuangHai
2026-01-21 08:51:44 +08:00
parent 7206bd554c
commit 2fda6f0dcf
6 changed files with 156 additions and 61 deletions

View File

@@ -214,29 +214,97 @@ async def export_ai_report_docx(req: AiReportRequest):
@router.get("/api/ai/pricing/strategy-summary")
async def ai_pricing_strategy_summary():
async def generate_stream():
resp = await get_operators_hourly_prices()
data = resp.get("operators", [])
text_data = []
for item in data:
text_data.append({"operator": item.get("operator"), "series": item.get("series")})
prompt = (
"下面是四家供应商(新电途、特来电、驿来特、艾特吉易充)基于最新爬取数据计算出的平均24小时分时电价:\n"
f"{text_data}\n"
"请根据这些数据,综合分析各司的定价策略差异,重点对比我司(驿来特)与其他供应商的分时电价水平,"
"指出我司在不同时段可能存在的潜在问题和风险例如明显偏贵、价格结构不合理等并给出2-3条可执行的优化建议。"
"请使用Markdown格式输出重点可以使用加粗如有公式可使用LaTeX格式。"
"回答控制在800字以内。"
)
async for chunk in get_llm_response(
prompt,
stream=True,
system_prompt="你是熟悉中国充电桩行业的电价策略分析顾问。",
):
yield chunk
try:
# 发送初始信息并增加一些空白填充,防止某些代理缓存
yield "正在收集各供应商价格数据,请稍候...\n\n" + (" " * 512) + "\n"
print("AI分析开始: 获取运营商价格数据...")
# 使用 asyncio.wait_for 防止数据库查询无限挂起
try:
# 1. 获取当前最新 24 小时平均价格
resp = await asyncio.wait_for(get_operators_hourly_prices(), timeout=30.0)
# 2. 获取最近 3 天的价格变动趋势
trend_resp = await asyncio.wait_for(get_operators_price_trends(days=3), timeout=30.0)
except asyncio.TimeoutError:
print("获取价格数据超时")
yield "\n\n**错误**: 获取价格数据超时,数据库响应过慢,请稍后重试。"
return
return StreamingResponse(generate_stream(), media_type="text/event-stream")
# 处理当前价格数据
data = resp.get("operators", [])
text_data = []
for item in data:
text_data.append({"operator": item.get("operator"), "series": item.get("series")})
# 处理 3 天趋势数据
trend_dates = trend_resp.get("dates", [])
trend_series = trend_resp.get("series", [])
trend_text = []
for s in trend_series:
trend_text.append({"operator": s.get("name"), "daily_avg_prices": s.get("data")})
print(f"数据获取完成准备请求LLM. 数据条数: {len(text_data)}, 趋势天数: {len(trend_dates)}")
yield "数据收集完成,正在分析最近 3 天的价格波动趋势并生成深度建议...\n\n"
# 增加一个心跳,确保连接不断开
yield " " * 128 + "\n"
prompt = (
"你是一位专业的充电桩调价策略分析顾问。下面是四家供应商(新电途、特来电、驿来特、艾特吉易充)的电价分析数据:\n\n"
"### 1. 当前最新 24 小时平均分时电价 (元/kWh)\n"
f"{json.dumps(text_data, ensure_ascii=False)}\n\n"
"### 2. 最近 3 天的价格变动趋势 (每日平均电价)\n"
f"日期序列: {trend_dates}\n"
f"各司趋势: {json.dumps(trend_text, ensure_ascii=False)}\n\n"
"请根据以上数据进行深度分析:\n"
"1. **现状对比**:对比我司(驿来特)与竞对在不同时段的电价水平,找出我司偏高或偏低的关键时段。\n"
"2. **趋势洞察**:分析最近 3 天各供应商的价格调整动态,判断市场整体是在涨价、降价还是保持稳定,我司的反应是否及时。\n"
"3. **问题诊断**:指出我司目前定价中存在的潜在风险(如价格倒挂、错失高峰收益、低谷缺乏竞争力等)。\n"
"4. **优化方案**:给出 2-3 条具体的、可落地的调价建议,并说明理由。\n\n"
"要求:\n"
"- 使用专业、客观的语气。\n"
"- 采用 Markdown 格式,适当使用加粗和表格。\n"
"- 回答控制在 800-1000 字以内。"
)
# 清空之前的提示信息,开始正式输出 AI 内容
yield "---CLEAR_PREVIOUS_HINTS---\n"
chunk_count = 0
# 使用 asyncio.wait_for 防止 LLM 请求完全死掉
try:
# 某些时候 LLM 可能会卡住,设置一个合理的整体超时
async for chunk in get_llm_response(
prompt,
stream=True,
system_prompt="你是熟悉中国充电桩行业的电价策略分析顾问。",
):
chunk_count += 1
if chunk_count == 1:
print("收到LLM首个chunk")
yield chunk
except Exception as llm_e:
print(f"LLM请求异常: {str(llm_e)}")
yield f"\n\n**AI 分析服务异常**: {str(llm_e)}。这可能是由于大模型服务商(如 DeepSeek响应过慢或连接中断导致的。"
return
print(f"AI分析完成共发送 {chunk_count} 个chunks")
except Exception as e:
error_msg = f"\n\n**分析过程出现严重错误**: {str(e)}"
print(error_msg)
yield error_msg
return StreamingResponse(
generate_stream(),
media_type="text/event-stream",
headers={
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"X-Accel-Buffering": "no",
"Content-Type": "text/event-stream; charset=utf-8"
}
)
@router.get("/api/ylt/stations", response_model=List[StationBase])