app:
  description: 日別売上データから異常を検出し、原因仮説と対策案を複数提示するワークフロー
  icon: 📊
  icon_background: '#FFEAD5'
  mode: workflow
  name: 売上異常分析支援
  use_icon_as_answer_icon: false
kind: app
version: 0.6.0
workflow:
  conversation_variables: []
  environment_variables: []
  features:
    file_upload:
      image:
        enabled: false
    opening_statement: ''
    suggested_questions: []
    suggested_questions_after_answer:
      enabled: false
    text_to_speech:
      enabled: false
  graph:
    edges:
    - data:
        sourceType: start
        targetType: code
      id: start-to-code1
      source: start
      target: code1
    - data:
        sourceType: code
        targetType: llm
      id: code1-to-llm1
      source: code1
      target: llm1
    - data:
        sourceType: llm
        targetType: end
      id: llm1-to-end
      source: llm1
      target: end
    nodes:
    - data:
        title: 開始
        type: start
        variables:
        - label: query
          max_length: 2048
          options: []
          required: true
          type: paragraph
          variable: query
      height: 90
      id: start
      position:
        x: 80
        y: 282
      type: custom
      width: 244
    - data:
        title: データ前処理
        type: code
        code_language: python3
        code: "def _safe_str(v):\n    \"\"\"Convert any value to string safely.\"\"\
          \"\n    if v is None:\n        return \"\"\n    if isinstance(v, list):\n\
          \        return \"\\n\".join(str(i) for i in v)\n    return str(v)\n\ndef\
          \ _safe_list(v):\n    \"\"\"Ensure value is a list.\"\"\"\n    if v is None:\n\
          \        return []\n    if isinstance(v, str):\n        return [v]\n   \
          \ if isinstance(v, list):\n        return v\n    return [v]\n\ndef main(**kwargs)\
          \ -> dict:\n    inputs = kwargs\n    raw = inputs.get(\"text\", \"\")\n\
          \    raw = str(raw).strip()\n    if raw == \"\":\n        processed = \"\
          \"\n        return dict(output=processed)\n    lines = raw.splitlines()\n\
          \    cleaned = []\n    for l in lines:\n        s = l.strip()\n        if\
          \ s == \"\":\n            continue\n        # カンマ区切りを優先、なければ空白で分割して最初の2項目を取得\n\
          \        if \",\" in s:\n            parts = [p.strip() for p in s.split(\"\
          ,\")]\n        else:\n            parts = [p.strip() for p in s.split()]\n\
          \        if len(parts) >= 2:\n            cleaned.append(parts[0] + \",\"\
          \ + parts[1])\n    if len(cleaned) == 0:\n        processed = raw\n    else:\n\
          \        header = \"date,value\"\n        processed = header + \"\\n\" +\
          \ \"\\n\".join(cleaned)\n    return dict(output=processed)\n"
        variables:
        - value_selector:
          - start
          - query
          variable: text
        outputs:
          output:
            type: string
            children: null
      height: 90
      id: code1
      position:
        x: 380
        y: 282
      type: custom
      width: 244
    - data:
        title: 異常検出と提案生成
        type: llm
        model:
          provider: openai
          name: gpt-5-mini
          mode: chat
          completion_params:
            temperature: 0.6
        prompt_template:
        - role: system
          text: "あなたは小売・流通分野に特化したデータアナリストAIです。与えられた日別売上時系列データから「異常」を検出し、各異常について以下を行ってください。\n\
            1) 異常の要約（発生した日付または期間、異常の種類: 急落/急増/季節外れ/欠損 等、推定される深刻度: high/medium/low）\n\
            2) 各異常に対する複数の原因仮説（事実ベースで検討可能な候補を3つ程度）\n3) 短期的な対策案（すぐに実行できる手順）と中長期的な改善策（プロセス/システム/在庫/販促等）\n\
            4) 必要な追加データや検証手順（どのデータを確認すべきか）\n出力は必ずJSON形式で行い、以下のキー構成を守ってください:\n{\n \
            \ \"anomalies\": [\n    {\n      \"date_range\": \"YYYY-MM-DD or YYYY-MM-DD\
            \ to YYYY-MM-DD\",\n      \"type\": \"急落/急増/季節外れ/欠損/その他\",\n      \"severity\"\
            : \"high/medium/low\",\n      \"explanation\": \"簡潔な説明\"\n    }\n  ],\n\
            \  \"hypotheses\": [\n    \"原因仮説1\",\n    \"原因仮説2\"\n  ],\n  \"recommendations\"\
            : {\n    \"short_term\": [\n      \"すぐできる対策1\",\n      \"すぐできる対策2\"\n\
            \    ],\n    \"mid_long_term\": [\n      \"中長期施策1\",\n      \"中長期施策2\"\
            \n    ]\n  },\n  \"required_checks\": [\n    \"確認すべき追加データや手順\"\n  ]\n\
            }\n\n\n---\n\n【最終出力フォーマット (この指示が最優先)】\n最終出力は **読みやすい日本語の Markdown** で返してください。JSON\n\
            配列・オブジェクトをそのまま出力してはいけません。\n- 見出し (## / ###) でセクションを区切る\n- リスト (- / 1.)\
            \ や表 (| ... |) で構造化\n- 各項目の意図や根拠が分かるよう短い説明文を添える\n- 営業デモで顧客に直接見せられる体裁にする\n\
            \n(構造化されたデータ項目を内部で扱うのは構いませんが、出力時に Markdown\nに変換してください。)"
        - role: user
          text: '以下が前処理済みの時系列データです（CSV: date,value）。ユーザーからの追加説明: {{#start.query#}}

            前処理データ:

            {{#code1.output#}}

            '
        vision:
          enabled: false
        memory: null
        context:
          enabled: false
      height: 90
      id: llm1
      position:
        x: 680
        y: 282
      type: custom
      width: 244
    - data:
        title: 終了
        type: end
        outputs:
        - value_selector:
          - llm1
          - text
          variable: result
      height: 90
      id: end
      position:
        x: 980
        y: 282
      type: custom
      width: 244
  hash: null
