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: parameter-extractor
      id: start-to-extractor1
      source: start
      target: extractor1
    - data:
        sourceType: parameter-extractor
        targetType: code
      id: extractor1-to-code1
      source: extractor1
      target: code1
    - data:
        sourceType: code
        targetType: knowledge-retrieval
      id: code1-to-kr_auto
      source: code1
      target: kr_auto
    - data:
        sourceType: start
        targetType: llm
      id: start-to-llm1
      source: start
      target: llm1
    - data:
        sourceType: parameter-extractor
        targetType: llm
      id: extractor1-to-llm1
      source: extractor1
      target: llm1
    - data:
        sourceType: llm
        targetType: end
      id: llm1-to-end
      source: llm1
      target: end
    - id: kr_auto-to-llm1
      source: kr_auto
      target: llm1
      data:
        sourceType: knowledge-retrieval
        targetType: llm
    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: parameter-extractor
        model:
          provider: openai
          name: gpt-5-mini
          mode: chat
        query:
        - start
        - query
        parameters:
        - name: policy_number
          type: string
          description: 保険契約番号または証券番号
          required: true
        - name: claim_amount
          type: number
          description: 請求金額（数値）
          required: true
        - name: claimant_name
          type: string
          description: 被保険者または申請者の氏名
          required: false
        - name: claim_date
          type: string
          description: 請求日
          required: false
        - name: suspicious_clues
          type: string
          description: 不審と考えられる記載（カンマ区切りの短い列挙）
          required: false
        - name: incident_description
          type: string
          description: 事故や事象の説明（任意）
          required: false
        reasoning_mode: prompt
        instruction: '以下の入力テキスト（保険金請求に関する記載）から、指定した項目を抽出してください。


          出力ルール:

          1) policy_number は必ず返すこと。見つからない場合は空文字で返す。

          2) claim_amount は数値で返すこと。通貨記号やカンマが含まれている場合は数値に変換して返す。

          3) suspicious_clues には見つかった不審点をカンマ区切りで返す（例: 同一住所で複数申請, 証憑不整合）。

          4) 他の項目は見つかれば返し、なければ空文字にする。

          '
      height: 90
      id: extractor1
      position:
        x: 380
        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    # 単純なルールベースでリスクスコアを算出する例\n    policy_number\
          \ = inputs.get(\"policy_number\", \"\")\n    claim_amount_raw = inputs.get(\"\
          claim_amount\", \"\")\n    try:\n        amount = float(str(claim_amount_raw).replace(\"\
          ,\", \"\").replace(\" \", \"\"))\n    except Exception:\n        amount\
          \ = 0.0\n\n    suspicious_raw = inputs.get(\"suspicious_clues\", \"\")\n\
          \    clues = [c.strip() for c in str(suspicious_raw).split(\",\") if c.strip()]\n\
          \n    score = 0.0\n\n    # 契約番号欠落は高リスク\n    if not policy_number:\n    \
          \    score += 30.0\n\n    # 金額に応じた重み付け\n    if amount > 100000:\n      \
          \  score += 40.0\n    elif amount > 50000:\n        score += 25.0\n    elif\
          \ amount > 10000:\n        score += 10.0\n\n    # 不審箇所の数に応じて加点（最大30点）\n\
          \    score += min(30.0, len(clues) * 10.0)\n\n    # スコアを0-100にクランプ\n   \
          \ if score < 0.0:\n        score = 0.0\n    if score > 100.0:\n        score\
          \ = 100.0\n\n    reasons_list = []\n    if not policy_number:\n        reasons_list.append(\"\
          契約番号が欠落している\")\n    reasons_list.append(\"請求金額: \" + str(amount))\n    if\
          \ clues:\n        reasons_list.append(\"検出された不審点: \" + \"; \".join(clues))\n\
          \n    reasons = \"; \".join(reasons_list)\n\n    return dict(risk_score=round(score,\
          \ 1), reasons=reasons)\n"
        variables:
        - value_selector:
          - extractor1
          - policy_number
          variable: policy_number
        - value_selector:
          - extractor1
          - claim_amount
          variable: claim_amount
        - value_selector:
          - extractor1
          - claimant_name
          variable: claimant_name
        - value_selector:
          - extractor1
          - claim_date
          variable: claim_date
        - value_selector:
          - extractor1
          - suspicious_clues
          variable: suspicious_clues
        - value_selector:
          - extractor1
          - incident_description
          variable: incident_description
        outputs:
          risk_score:
            type: number
            children: null
          reasons:
            type: string
            children: null
      height: 90
      id: code1
      position:
        x: 680
        y: 282
      type: custom
      width: 244
    - data:
        title: 最終分析・優先順位付け
        type: llm
        model:
          provider: openai
          name: gpt-5-mini
          mode: chat
          completion_params:
            temperature: 0.5
        prompt_template:
        - role: system
          text: 'あなたは保険不正検知のアナリストです。以下の入力と抽出結果、算出されたリスクスコアを元に、不正の疑いがあるポイントを短く箇条書きで示し、その根拠、推定リスク指標（High/Medium/Low）、および調査優先度の理由と推奨アクションを出力してください。出力は日本語で、まず短い要約（1-2行）、次に優先度と根拠、最後に箇条書きの疑いポイントと根拠を示してください。


            重要: 回答の各手順・セクションにナレッジ検索結果を使用した場合は [参考: 文書名] タグを付けること。回答の末尾に「参考資料:」セクションを付けて参照した全文書名を一覧すること。省略不可。'
        - role: user
          text: "元の請求文:\n{{#start.query#}}\n\n抽出結果:\n- policy_number: {{#extractor1.policy_number#}}\n\
            - claim_amount: {{#extractor1.claim_amount#}}\n- claimant_name: {{#extractor1.claimant_name#}}\n\
            - claim_date: {{#extractor1.claim_date#}}\n- suspicious_clues: {{#extractor1.suspicious_clues#}}\n\
            - incident_description: {{#extractor1.incident_description#}}\n\n算出リスクスコア:\
            \ {{#code1.risk_score#}}\nスコア理由: {{#code1.reasons#}}\n\n上記を参照して、調査チーム向けの短く実用的な報告を作成してください。\n\
            \n【参考資料の明示ルール】\n回答の各セクション・箇条書きで、ナレッジ検索結果の情報を使った箇所には [参考: 文書名] タグを付けてください。\n\
            回答の末尾に「参考資料:」セクションを設け、参照した全文書名を一覧してください。\n出力例:\n  1. VPNクライアントを再起動してください\
            \ [参考: VPN接続トラブルシューティング.txt]\n  ...\n  参考資料:\n  - VPN接続トラブルシューティング.txt\n\
            \  - パスワードリセット手順.txt"
        vision:
          enabled: false
        memory: null
        context:
          enabled: true
          variable_selector:
          - kr_auto
          - result
      height: 90
      id: llm1
      position:
        x: 980
        y: 282
      type: custom
      width: 244
    - data:
        title: 終了
        type: end
        outputs:
        - value_selector:
          - llm1
          - text
          variable: result
      height: 90
      id: end
      position:
        x: 1280
        y: 282
      type: custom
      width: 244
    - id: kr_auto
      type: custom
      width: 244
      height: 90
      position:
        x: 680
        y: 282
      data:
        title: ナレッジ検索
        type: knowledge-retrieval
        dataset_ids:
        - __KR_0__
        retrieval_mode: single
        single_retrieval_config:
          model:
            provider: openai
            name: gpt-5-mini
            mode: chat
            completion_params:
              temperature: 0.7
        query_variable_selector:
        - start
        - query
  hash: null
