""" Level-aware mock templates. Replace level1_propose / level2_propose / level3_propose with real logic. """ from __future__ import annotations from bridge_models import BestNow, NextLevelPreview, NeededInfo from session_store import AccumulatedContext def get_mock_best_now(level: str, ctx: AccumulatedContext) -> BestNow: campaign = ctx.campaign_name or "このキャンペーン" industry = ctx.industry or "この業界" if level == "level1": return BestNow( summary=( f"【{industry}】の業界ベンチマークを起点に、{campaign} の初期改善仮説を提案します。" " 一般的にEC・サービス系では認知→検討→CVの3段階で離脱が発生します。" " まずは訴求軸の見直し(ベネフィット訴求 vs 機能訴求)から着手することを推奨します。" ), actions=[ "ターゲット顧客の主要ペインを3つリストアップする", "現在の広告訴求軸を「機能」「ベネフィット」「感情」で分類する", "業界ベンチマークCVR(目安: 1〜3%)と現状ギャップを確認する", ], confidence="low", reasoning_basis=["campaign_name", "industry"], ) if level == "level2": cvr_text = f"CVR {ctx.cvr}%" if ctx.cvr is not None else "CVR不明" ctr_text = f"CTR {ctx.ctr}%" if ctx.ctr is not None else "" metrics_summary = "、".join(filter(None, [cvr_text, ctr_text])) return BestNow( summary=( f"{campaign} の定量データ({metrics_summary})をもとにファネル診断を行いました。" " CVRが業界平均(約2%)を下回る場合、LP到達後の離脱が主要ボトルネックである可能性が高いです。" " クリック後の初期体験(FV・CTA)の改善を優先します。" ), actions=[ "LPファーストビューのキャッチコピーをベネフィット訴求に変更する", "CTAボタンの文言・色・配置をA/Bテストする", "LPの読了率をヒートマップで確認し、離脱ポイントを特定する", ], confidence="mid", reasoning_basis=["cvr", "ctr", "campaign_name", "industry"], ) # level3 return BestNow( summary=( f"{campaign} のクリエイティブ画像を含めた総合的な改善提案です。" " 画像の視覚的訴求力(色彩・人物有無・テキスト量)と定量KPIを組み合わせて診断します。" " ファーストビューの画像とCTAの整合性が鍵です。" ), actions=[ "クリエイティブ画像のメインビジュアルに人物(使用シーン)を追加する", "画像内テキストを最小化し、LPコピーとの役割分担を明確にする", "高CVR画像の共通要素(色・構図・訴求軸)をパターン化してA/Bテストに活用する", ], confidence="high", reasoning_basis=["image_base64", "cvr", "ctr", "campaign_name", "industry"], ) def get_mock_next_level_preview(current_level: str) -> NextLevelPreview: if current_level == "level1": return NextLevelPreview( current_level="level1", next_level="level2", needed_info=[ NeededInfo(key="cvr", label="直近14日のCVR", example="2.1%"), NeededInfo(key="ctr", label="CTR(クリック率)", example="0.8%"), NeededInfo(key="cpa", label="CPA(獲得単価)", example="3500円"), ], what_will_be_possible=[ "ファネル診断(どの段階で離脱しているか特定)", "優先度付きの改善アクション(高インパクト順)", "KPI改善の定量目標設定", ], expected_impact="CVRやCTRの数値があると、業界平均との差分から改善余地を定量化でき、提案の精度が大幅に向上します。", ) if current_level == "level2": return NextLevelPreview( current_level="level2", next_level="level3", needed_info=[ NeededInfo(key="image_base64", label="広告クリエイティブ画像", example="バナー画像またはLP上部スクリーンショット"), ], what_will_be_possible=[ "クリエイティブ要素(ビジュアル・テキスト量・色彩)の具体的改善提案", "画像とKPIの相関分析(どのビジュアル要素がCVRに影響するか)", "高CVR画像パターンの抽出", ], expected_impact="画像があると、数値だけでは見えない「なぜ離脱するか」の視覚的原因を特定でき、具体的なクリエイティブ改善指示が出せます。", ) # level3 -- already at max return NextLevelPreview( current_level="level3", next_level=None, needed_info=[], what_will_be_possible=[], expected_impact="利用可能な全情報が揃っています。現在の提案は最高精度です。", ) def get_follow_up_question(current_level: str) -> str | None: if current_level == "level1": return "CVRやCTRなどの数値データはありますか?あれば入力いただくと提案精度が上がります。" if current_level == "level2": return "広告クリエイティブ画像(バナーやLPスクリーンショット)をアップロードできますか?" return None # --- Real implementation stubs (user replaces these) --- def level1_propose(ctx: AccumulatedContext, history: list) -> BestNow: """Level 1 real implementation. Replace this with your logic.""" return get_mock_best_now("level1", ctx) def level2_propose(ctx: AccumulatedContext, history: list) -> BestNow: """Level 2 real implementation. Replace this with your logic.""" return get_mock_best_now("level2", ctx) def level3_propose(ctx: AccumulatedContext, history: list) -> BestNow: """Level 3 real implementation. Replace this with your logic.""" return get_mock_best_now("level3", ctx)