app:
  description: 水道事業の月次報告書ドラフト生成ワークフロー
  icon: 💧
  icon_background: '#E6F7FF'
  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    import re\n    text = str(inputs.get(\"\
          text\", \"\"))\n    # KPI一覧\n    kpi_names = [\"給水量\", \"収納率\", \"有収率\"\
          , \"事故件数\", \"苦情件数\"]\n    results = {}\n    # ヘルパー: 数値文字列をfloat化（%の場合も対応）\n\
          \    def to_num(s):\n        if s is None:\n            return None\n  \
          \      s2 = str(s).replace(\",\", \"\").strip()\n        if s2.endswith(\"\
          %\"):\n            s2 = s2[:-1].strip()\n        try:\n            return\
          \ float(s2)\n        except:\n            return None\n    # 個別KPIについて、現在値・前月・前年を抽出\n\
          \    for k in kpi_names:\n        curr = None\n        prev = None\n   \
          \     prev_y = None\n        # パターン1: KPI: 現値 (前月: xxx, 前年同月: yyy)\n   \
          \     p = re.search(k + r'\\s*[:：]\\s*([0-9,\\.%]+)(?:\\s*\\((.*?)\\))?',\
          \ text)\n        if p:\n            curr = to_num(p.group(1))\n        \
          \    inner = p.group(2) or \"\"\n            m1 = re.search(r'前月(?:実績)?[:：]?\\\
          s*([0-9,\\.%]+)', inner)\n            m2 = re.search(r'前年同月(?:実績)?[:：]?\\\
          s*([0-9,\\.%]+)', inner)\n            if m1:\n                prev = to_num(m1.group(1))\n\
          \            if m2:\n                prev_y = to_num(m2.group(1))\n    \
          \    # パターン2: 別行に「KPI 前月: x」などがある場合の検出\n        if prev is None:\n     \
          \       m = re.search(k + r'.{0,40}前月(?:実績)?[:：]?\\s*([0-9,\\.%]+)', text)\n\
          \            if m:\n                prev = to_num(m.group(1))\n        if\
          \ prev_y is None:\n            m = re.search(k + r'.{0,40}前年同月(?:実績)?[:：]?\\\
          s*([0-9,\\.%]+)', text)\n            if m:\n                prev_y = to_num(m.group(1))\n\
          \        # パターン3: 個別行で「KPI: 現値」だけのケースを補完\n        if curr is None:\n   \
          \         m = re.search(k + r'\\s*[:：]\\s*([0-9,\\.%]+)', text)\n      \
          \      if m:\n                curr = to_num(m.group(1))\n        results[k]\
          \ = dict(current=curr, prev_month=prev, prev_year=prev_y)\n    # 計算: 前月比・前年比（%）\n\
          \    out_lines = []\n    for k, v in results.items():\n        curr = v.get(\"\
          current\")\n        prev = v.get(\"prev_month\")\n        prev_y = v.get(\"\
          prev_year\")\n        line = k + \": \"\n        line = line + \"現在値=\"\
          \ + ( \"\" if curr is None else format(curr, \".2f\") )\n        if prev\
          \ is not None:\n            try:\n                diff = curr - prev if\
          \ curr is not None else None\n            except:\n                diff\
          \ = None\n            pct = None\n            if diff is not None and prev\
          \ != 0:\n                pct = diff / prev * 100\n            sign = \"\"\
          \n            if diff is not None:\n                if pct is not None:\n\
          \                    sign = (\"+\" if pct >= 0 else \"\") + format(pct,\
          \ \".2f\") + \"%\"\n                else:\n                    sign = \"\
          \"\n                line = line + \", 前月=\" + format(prev, \".2f\") + \"\
          \ (前月比 \" + sign + \")\"\n            else:\n                line = line\
          \ + \", 前月=\" + format(prev, \".2f\")\n        else:\n            line =\
          \ line + \", 前月=未設定\"\n        if prev_y is not None:\n            try:\n\
          \                diffy = curr - prev_y if curr is not None else None\n \
          \           except:\n                diffy = None\n            pxty = None\n\
          \            if diffy is not None and prev_y != 0:\n                pxty\
          \ = diffy / prev_y * 100\n            signy = \"\"\n            if diffy\
          \ is not None:\n                if pxty is not None:\n                 \
          \   signy = (\"+\" if pxty >= 0 else \"\") + format(pxty, \".2f\") + \"\
          %\"\n                else:\n                    signy = \"\"\n         \
          \       line = line + \", 前年同月=\" + format(prev_y, \".2f\") + \" (前年比 \"\
          \ + signy + \")\"\n            else:\n                line = line + \",\
          \ 前年同月=\" + format(prev_y, \".2f\")\n        else:\n            line = line\
          \ + \", 前年同月=未設定\"\n        out_lines.append(line)\n    result = \"増減率計算結果:\\\
          n\" + \"\\n\".join(out_lines)\n    return dict(output=result)\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: 報告書生成（LLM）
        type: llm
        model:
          provider: openai
          name: gpt-5-mini
          mode: chat
          completion_params:
            temperature: 0.6
        prompt_template:
        - role: system
          text: 'あなたは水道事業の社内向け報告書作成アシスタントです。以下の要件を満たす、事務文書調の月次総括レポート（草案）を生成してください。構成は必ず次の項目を含め、明確な見出しで区切ること。①業務概況（全体評価、短く要点）、②主要KPI実績（各KPIの数値と前月比・前年比を含める）、③特記事項（良化・悪化のポイント、原因推定を簡潔に）、④課題と次月対策（具体的で実行可能な対策案を箇条書き）、⑤管理職コメント欄（空欄のプレースホルダ）。KPIの記載はcodeノードの計算結果を参照して数値を忠実に使用すること。文体は公式で簡潔、各セクションは見出しと1〜5段落程度にまとめてください。


            ---


            【最終出力フォーマット (この指示が最優先)】

            最終出力は **読みやすい日本語の Markdown** で返してください。JSON

            配列・オブジェクトをそのまま出力してはいけません。

            - 見出し (## / ###) でセクションを区切る

            - リスト (- / 1.) や表 (| ... |) で構造化

            - 各項目の意図や根拠が分かるよう短い説明文を添える

            - 営業デモで顧客に直接見せられる体裁にする


            (構造化されたデータ項目を内部で扱うのは構いませんが、出力時に Markdown

            に変換してください。)'
        - role: user
          text: '入力（元データ）:

            {{#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
