diff --git a/routes/openclaw_bot_routes.py b/routes/openclaw_bot_routes.py index 21ca567..d127244 100644 --- a/routes/openclaw_bot_routes.py +++ b/routes/openclaw_bot_routes.py @@ -1836,6 +1836,7 @@ def _ppt_ai_analysis(prompt_data: str, report_type: str = '') -> str: 用 NIM DeepSeek 生成簡報 AI 分析文字 (批次任務用 NIM,節省 Gemini 即時對話額度) """ + is_monthly = '月報' in report_type is_strategy = '策略' in report_type is_competitor = '競品' in report_type is_promo = '促銷' in report_type @@ -1850,7 +1851,36 @@ def _ppt_ai_analysis(prompt_data: str, report_type: str = '') -> str: "5. 繁體中文,語氣專業、精準、業績導向" ) - if is_promo: + if is_monthly: + sys_instruction = ( + "你是資深電商營運分析師,擁有 10 年台灣電商月度營運管理實戰經驗," + "精通美妝保養、母嬰、個人清潔等品類的市場趨勢與商品策略。\n" + "請根據以下月報業績數據與外部市場情報,輸出一份完整的月度營運分析報告:\n\n" + "【整體業績解讀】(3-4句)\n" + "引用月業績、月訂單數、毛利率、客單價四項核心指標,評估本月整體表現等級(優/良/普/弱)," + "指出最顯著亮點(如品類爆發、客單拉升)或警訊(如毛利壓縮、成長放緩)," + "並與台灣電商月均表現(月業績成長率 5~15% 為健康區間)比較定位。\n\n" + "【品類結構深度解析】(3-4句)\n" + "點出貢獻業績最高的 1~2 個品類,說明其主導地位的成因(季節性/活動拉動/商品力);" + "識別成長最快或最具潛力的新興品類;" + "指出業績佔比過度集中帶來的風險(若美妝>60%則點明)。\n\n" + "【熱銷商品洞察】(2-3句)\n" + "點名 TOP3 熱銷商品,分析其高業績的成因(定價優勢/品牌力/活動推力)," + "說明這些商品對整體客單價與毛利的貢獻或壓力。\n\n" + "【MCP 市場情報整合】(2-3句)\n" + "結合外部市場情報,說明當前電商環境對本月業績的影響," + "並指出下個月應特別關注的外部機會(如節慶/消費趨勢/競品動態)。\n\n" + "【三段式行動建議】\n" + "■ 本週立即執行(2條,以 ✅ 開頭):針對庫存補貨、廣告投放、定價調整等短期動作\n" + "■ 本月優化重點(2條,以 ✅ 開頭):針對品類組合、客單提升、毛利改善\n" + "■ 下月預備部署(2條,以 ✅ 開頭):結合節慶時機與 MCP 情報,提早卡位\n" + "每條建議必須包含具體商品/品類名稱與量化目標(如:毛利率提升 2%/客單提升 NT$150)。\n\n" + "【風險預警】(1-2句):指出最大潛在風險與防禦建議。\n\n" + "要求:每段引用至少一個具體數字,全文 500~700 字,語氣如資深顧問月報。" + + FORMAT_RULES + ) + max_tokens = 1600 + elif is_promo: sys_instruction = ( "你是資深電商活動行銷策略分析師,擁有 10 年以上台灣電商促銷活動策劃與效益評估實戰經驗," "精通促銷活動 ROI 分析、商品選品策略、消費者行為洞察,深度熟悉美妝、保健、母嬰等品類的" @@ -2399,15 +2429,28 @@ def _generate_ppt_cmd(sub_type: str, sub_arg: str, _chat_id: int, target: str, ms = query_monthly_summary(yr, mo) top_cats = query_category_monthly(yr, mo, lim=8) ms['top_categories'] = top_cats + aov = ms.get('avg_order', ms.get('revenue', 0) / ms.get('orders', 1) if ms.get('orders') else 0) + top5_products = ms.get('top_products', [])[:5] + top5_cats = top_cats[:5] + cat_total = sum(float(c.get('revenue', 0)) for c in top5_cats) + cat_breakdown = '\n'.join( + f" - {c.get('cat','')}: NT${float(c.get('revenue',0)):,.0f}" + f"({float(c.get('revenue',0))/cat_total*100:.0f}%)" if cat_total else f" - {c.get('cat','')}:NT${float(c.get('revenue',0)):,.0f}" + for c in top5_cats + ) + prod_breakdown = '\n'.join( + f" {i+1}. {p.get('name','')[:30]} — NT${float(p.get('revenue',0)):,.0f}" + for i, p in enumerate(top5_products) + ) data_summary = ( - f"月份:{yr}/{mo:02d}\n" - f"月業績:NT$ {ms.get('revenue', 0):,.0f} | " - f"訂單:{ms.get('orders', 0)} | 毛利率:{ms.get('gross_margin', 0):.1f}%\n" - f"熱銷:" + " / ".join( - f"{p['name']}(NT${p['revenue']:,.0f})" - for p in ms.get('top_products', [])[:5]) + "\n" - f"分類:" + " / ".join(f"{c['cat']}(NT${c['revenue']:,.0f})" for c in top_cats[:3]) + "\n" - f"外部情報:{mcp_text[:500]}" + f"【月份】{yr}/{mo:02d}\n" + f"【月業績】NT${ms.get('revenue', 0):,.0f}\n" + f"【月訂單】{ms.get('orders', 0):,} 筆\n" + f"【毛利率】{ms.get('gross_margin', 0):.1f}%\n" + f"【平均客單價】NT${aov:,.0f}\n\n" + f"【品類業績分佈(TOP5)】\n{cat_breakdown}\n\n" + f"【熱銷商品 TOP5】\n{prod_breakdown}\n\n" + f"【MCP 外部市場情報】\n{mcp_text[:600] if mcp_text else '(無外部情報)'}" ) ai_text = cached_ai or _ppt_ai_analysis(data_summary, '月報') if not cached_ai and _ppt_needs_fallback(ai_text):