### Install Layer Dependencies and Build/Deploy with SAM Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/deploy-checks/deploy-1-u0.md Navigate to the repository root, install Python dependencies for the Lambda Layer, build the SAM application, and deploy it. The initial deployment can also be guided. ```bash cd Auto-Reward-Service pip install -r requirements.txt -t layer/python/ --upgrade sam build sam deploy ``` -------------------------------- ### DynamoDB State Management Example Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-7/追加機能指示.md Example of DynamoDB item structure for managing user recommendation state, including step, category, and a TTL for automatic expiration. ```json DynamoDB: PK=USER#xxx SK=RECOMMEND_STATE# { "step": "WAITING_CATEGORY" | "WAITING_BUDGET" | null, "category": "relax", "ttl": 1716000000 ← 10分で自動失効 } ``` -------------------------------- ### Onboarding Flow State Machine Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-2/functional-design/business-logic-model.md Defines the state transitions and user interactions for the onboarding process, guiding users through profile setup. ```mermaid [WAITING_INCOME] → ユーザーが金額を返答 → LLM で月収を数値抽出 → PROFILE.monthly_income 更新 → 次のメッセージ「家賃とかスマホ代...は?」送信 → 状態 → [WAITING_FIXED_COSTS] [WAITING_FIXED_COSTS] → ユーザーが固定費を返答 → LLM で固定費リストと合計を抽出 → PROFILE.fixed_costs, FIXED_COSTS アイテム群を保存 → ご褒美枠を算出(月収 - 固定費の 10〜20%、最低 3,000円) → 枠提示メッセージ送信 → 状態 → [CONFIRM_REWARD_BUDGET] [CONFIRM_REWARD_BUDGET] → CONFIRM_YES → 状態 → [WAITING_BONUS] → CONFIRM_NO または金額変更 → 再算出 or ユーザー指定値を採用 → 状態 → [WAITING_BONUS] [WAITING_BONUS] → 「ボーナスってある?」質問送信 → ユーザーが回答 → ある場合: LLM で月・金額抽出 → PROFILE.bonus_months, bonus_amount 保存 → ない・スキップ: そのまま次へ → 状態 → [WAITING_BIRTHDAY] [WAITING_BIRTHDAY] → 「ちなみに誕生日いつ?」質問送信 → ユーザーが回答 → 日付抽出(MM-DD 形式)→ PROFILE.birthday 保存 → スキップ: そのまま次へ → 完了メッセージ送信 → 状態 → [COMPLETED] → ONBOARDING_STATE アイテム削除(クリーンアップ) ``` -------------------------------- ### Lambda Cold Start and Warm Invocation Sequence Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-0/nfr-design/logical-components.md Details the initialization sequence for service singletons during a Lambda cold start and highlights the efficiency of warm invocations where singletons are already cached. ```text Lambda コールドスタート │ ├─ secrets.py モジュールロード │ └─ _secret_cache = {} (初期化のみ、まだ取得しない) │ ├─ dynamodb_service.py モジュールロード │ └─ _dynamodb_service = None │ ├─ bedrock_service.py モジュールロード │ └─ _bedrock_service = None │ ├─ line_service.py モジュールロード │ └─ _line_service = None │ └─ google_calendar_service.py モジュールロード └─ _google_calendar_service = None Lambda ハンドラ 初回呼び出し │ ├─ warmup check → {"source":"warmup"} なら即 return │ ├─ get_line_service() │ ├─ _line_service is None → 初期化開始 │ ├─ get_secret("LINE_SECRET_NAME") │ │ └─ Secrets Manager: ars/line-{stage} 取得 → キャッシュ │ └─ LineService(channel_secret, access_token) 作成 → キャッシュ │ ├─ get_dynamodb_service() │ └─ DynamoDBService(table_name=env["DYNAMODB_TABLE_NAME"]) 作成 → キャッシュ │ └─ ハンドラ処理実行 Lambda ウォームインボケーション(2回目以降) │ └─ 全シングルトンキャッシュ済み → Secrets Manager / boto3 初期化なし ``` -------------------------------- ### Deployment Prerequisites Checklist Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-0/infrastructure-design/deployment-architecture.md A checklist to ensure all necessary tools and configurations are in place before deploying the Auto Reward Service. This includes AWS CLI and SAM CLI setup, Python installation, creation of required secrets in AWS Secrets Manager, and configuration of LINE Developer console webhook URLs. ```text [ ] AWS CLI が設定済み(aws configure) [ ] SAM CLI がインストール済み(sam --version) [ ] Python 3.14 がインストール済み [ ] ars/line シークレットが Secrets Manager に作成済み [ ] ars/google シークレットが Secrets Manager に作成済み [ ] ars/rakuten シークレットが Secrets Manager に作成済み [ ] LINE Developers コンソールで Webhook URL が設定済み ``` -------------------------------- ### Auto-Numbering Enums with `start` Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/layer/python/aenum/doc/aenum.rst Demonstrates how to use `start` to enable auto-numbering for enum members, ensuring consistent and ordered numeric values. This can be configured directly or via `_start_`. ```python >>> class Color(Enum, start=1): # doctest: +SKIP ... red, green, blue ... >>> Color.blue ``` ```python >>> class Color(Enum): # doctest: +SKIP ... _start_ = 1 ... red = auto() ... green = auto() ... blue = auto() ... >>> Color.blue ``` -------------------------------- ### User Story: Initial Registration Dialogue Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/inception/requirements/requirements.md Example dialogue for the initial user registration process, gathering financial information to set a reward budget. ```plaintext リワードちゃん: まずざっくり教えて〜。毎月の手取りってどれくらい? ユーザー: 30万くらい。ボーナスは年2回で合計80万。 リワードちゃん: 家賃とか固定費もざっくり教えて〜。 ユーザー: 家賃8万、スマホ1万… リワードちゃん: じゃあ今月のごほうび枠、まず2万円くらいから始めよっか。 ``` -------------------------------- ### Example Onboarding Conversation Flow Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/inception/application-design/unit-of-work.md Demonstrates a typical user onboarding conversation with the LINE Bot, covering income, fixed costs, bonus information, and birthday registration. ```text リワードちゃん: はじめまして〜!リワードちゃんだよ🎀 まずざっくり教えて〜。毎月の手取りってどれくらい? ユーザー: 30万くらい。 リワードちゃん: おっけー!家賃とかスマホ代とか、毎月決まって出ていくお金は? ユーザー: 家賃8万、スマホ1万、サブスク5000円くらいかな リワードちゃん: なるほど〜。じゃあ今月のごほうび枠、まず2万円くらいから始めよっか✨ リワードちゃん: ちなみにボーナスってある?あるなら何月にどれくらい? ユーザー: 6月と12月に40万ずつくらい。 リワードちゃん: いいね〜!ボーナス月はちょっと多めに使えるようにしとくね😏 リワードちゃん: あと誕生日いつ?覚えておきたいな〜🎂 ユーザー: 9月15日 リワードちゃん: 9/15ね、メモった📝 その日は特別なご褒美用意するから楽しみにしてて! リワードちゃん: おっけー準備完了!なんかあったらいつでも話しかけてね〜 ``` -------------------------------- ### Get Settings Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-7/functional-design/business-logic-model.md Retrieves the user's current settings. ```APIDOC ## GET /api/settings ### Description Retrieves the user's current settings, including tone, budget, and bonus configurations. ### Method GET ### Endpoint /api/settings ### Response #### Success Response (200) - **tone** (str) - Preferred tone for suggestions ('friendly', 'polite', 'devilish'). - **reward_budget_monthly** (int) - Monthly budget for rewards. - **bonus_months** (array) - Array of months (as integers) where a bonus is applicable. - **bonus_amount** (int) - The amount of the bonus. - **carryover_rate** (float) - The rate at which unused budget carries over to the next month. - **nickname** (str) - User's nickname. ### Response Example { "tone": "friendly", "reward_budget_monthly": 50000, "bonus_months": [12], "bonus_amount": 10000, "carryover_rate": 0.1, "nickname": "User123" } ``` -------------------------------- ### User Story: Expense Input via Chat Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/inception/requirements/requirements.md Example dialogue for logging expenses through chat, categorizing them, and noting specific item details. ```plaintext ユーザー: 今日セブンでプリンとカフェラテ買った。たぶん900円くらい。 リワードちゃん: やった〜。それは情緒安定費で覚えたい。 プリンってなんてプリン?次に似たやつ見つけたい〜 ユーザー: 320円の濃厚たまごプリン リワードちゃん: 濃厚たまごプリン、320円ね。覚えた〜。たまご系プリン、次も見張っとく。 ``` -------------------------------- ### samconfig.toml Deployment Configuration Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-0/infrastructure-design/infrastructure-design.md Configuration file for SAM CLI, specifying deployment parameters such as stack name, region, and capabilities. This example is for the default environment. ```toml version = 0.1 [default] [default.deploy] [default.deploy.parameters] stack_name = "auto-reward-service" resolve_s3 = true region = "ap-northeast-1" confirm_changeset = false capabilities = "CAPABILITY_IAM" [default.build] [default.build.parameters] use_container = false ``` -------------------------------- ### Quick Expense Input Example Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-7/追加機能指示.md Illustrates the conversational flow for quick expense input using LINE's quick replies. The bot prompts for the category and then the amount, confirming the entry. ```text リワードちゃん: 「何に使った?🎀」 [☕ カフェ] [🍽️ ランチ] [🍰 スイーツ] [📚 本・漫画] [🎮 ゲーム] [💊 日用品] [✏️ 直接入力] ユーザーが「☕ カフェ」を選ぶと: リワードちゃん: 「カフェね!いくらだった?」 ユーザー: 「650」 リワードちゃん: 「カフェ 650円ね、覚えた〜☕✨ 今月の残り: 14,350円」 ``` -------------------------------- ### Settings Retrieval Flow (GET /api/settings) Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-7/functional-design/business-logic-model.md Explains the process of retrieving user settings, including tone, budget, bonus months, and nickname, from DynamoDB. ```mermaid LiffApiFunction.handle_get_settings(user_id) │ ├─[1] DDB.get_item(USER#{id}, PROFILE#) │ └─[2] レスポンス: { "tone": str, # friendly / polite / devilish "reward_budget_monthly": int, "bonus_months": [int], "bonus_amount": int, "carryover_rate": float, "nickname": str, } ``` -------------------------------- ### Enum Initialization with Missing Values and `_generate_next_value_` Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/layer/python/aenum/doc/aenum.rst Demonstrates how `_generate_next_value_` is called to provide values for enum members when `_init_` requires arguments that are not supplied. This example uses a custom `__new__` and `_generate_next_value_`. ```python >>> from aenum import Enum >>> class SelectionEnum(Enum): ... _init_ = 'db user' ... def __new__(cls, *args, **kwds): ... count = len(cls.__members__) ... obj = object.__new__(cls) ... obj._count = count ... obj._value_ = args ... return obj ... @staticmethod ... def _generate_next_value_(name, start, count, values, *args, **kwds): ... return (name, ) + args ... >>> class NotificationType(SelectionEnum): ... # usually, name is the same as db ... # but not for blanks ... blank = '', '' ... C = 'Catalog' ... S = 'Sheet' ... B = 'Both' ... >>> NotificationType.blank >>> NotificationType.B >>> NotificationType.B.db 'B' >>> NotificationType.B.user 'Both' ``` -------------------------------- ### Warm-up Ping Pattern Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-1/nfr-design/nfr-design-patterns.md Handles warm-up requests by returning a 200 OK response immediately. This pattern prevents cold starts and reduces response latency for subsequent requests. ```python # handler 先頭で即リターン if event.get("source") == "warmup": return {"statusCode": 200, "body": "warm"} ``` -------------------------------- ### Onboarding Flow for New Users Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-2/infrastructure-design/deployment-architecture.md Details the process for a first-time user interacting with the service, covering initial greetings, intent classification, and the onboarding flow initiation. It shows how user profile and onboarding state are checked and updated, and the initial response generated. ```text 1. LINE → "こんにちは" 2. classify_intent → GREET (または CHAT) 3. dispatch → character_reply: → GetItem PROFILE: None → PROFILE 未登録 → GetItem ONBOARDING_STATE: None → オンボーディング未開始 → onboarding_flow.handle_onboarding(None): → PutItem ONBOARDING_STATE {step: WAITING_INCOME} → return "はじめまして〜!リワードちゃんだよ🎀 まずざっくり教えて〜。毎月の手取りってどれくらい?" 4. reply_message() ``` -------------------------------- ### Onboarding Flow with Flex Message Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-7/追加機能指示.md This diagram outlines the user onboarding process starting from a follow event. It shows the initial reply message from Reward Chan, followed by a Flex Message button that opens a LIFF form. After submission, a single Push message is sent to confirm onboarding completion. ```text 友だち追加(follow イベント) ↓ リワードちゃん(Reply): 「はじめまして〜!リワードちゃんだよ🎀 まずちょっとだけ教えてほしいことがあるの!」 [📝 登録フォームを開く] ← Flex Message のボタン(LIFF URL) ↓ LIFF フォーム(LINE内ブラウザ Full サイズ) ↓ 送信 → API Gateway → Lambda → DynamoDB 保存 ↓ Lambda から Push Message(※オンボーディング完了通知のみ Push。初回1回限り): 「おっけー!覚えた〜🎀 月収30万、固定費12万だから… ごほうび枠は 2万円くらいから始めよっか!」 ``` -------------------------------- ### GET /api/settings Response Schema Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-7/functional-design/domain-entities.md This JSON schema represents the response from the GET /api/settings endpoint, detailing user preferences such as tone, reward budget, bonus settings, and nickname. ```json { "tone": "friendly", "reward_budget_monthly": 20000, "bonus_months": [6, 12], "bonus_amount": 400000, "carryover_rate": 0.5, "nickname": "ともちゃん" } ``` -------------------------------- ### Reward-chan's Conversational Tone Examples Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/docs/コンセプト変更定義書.md Examples of Reward-chan's dialogue showcase a supportive and encouraging tone, framing expenses as 'recovery costs' or 'treats' rather than strict expenditures. ```text 今日もおつかれ〜。 それはプリン案件かも。 今月まだちょっと余裕あるよ。 これ買っちゃおうよ〜。 これは浪費じゃなくて、回復費でいけるやつ! ``` -------------------------------- ### Build and Deploy Auto-Reward-Service with SAM Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/deploy-checks/deploy-2-u0-u1.md Navigate to the project directory and use SAM CLI to build and deploy the serverless application. Ensure you have the correct AWS profile configured. ```powershell cd "Z:\oono.toshiki\OneDrive - Business1\code\AIハッカソン\Auto-Reward-Service" # SAM ビルド sam build # SAM デプロイ(profile=share) sam deploy --profile share ``` -------------------------------- ### GET /api/pool Response Schema Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-7/functional-design/domain-entities.md This JSON schema defines the response for the GET /api/pool endpoint, which lists potential reward items including their name, price, category, score, and URLs. ```json { "items": [ { "name": "バスソルト ギフトセット", "price": 2480, "category": "入浴剤", "score": 0.85, "type": "product", "image_url": "https://...", "source_url": "https://..." } ] } ``` -------------------------------- ### Handle Onboarding Flow Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/aidlc-docs/construction/unit-2/nfr-design/logical-components.md Manages the user onboarding state machine, guiding users through questions about income, expenses, rewards, bonuses, and birthdays. It interacts with DynamoDB to store and retrieve state information. ```python handle_onboarding(user_id, text, state) -> str │ ├── state is None → 初回 → 月収質問文を返す + PutItem ONBOARDING_STATE ├── WAITING_INCOME → 月収を解析 → 次ステップへ ├── WAITING_FIXED_COSTS → 固定費を解析 → ご褒美枠算出 → 確認質問 ├── CONFIRM_REWARD_BUDGET → WAITING_BONUS へ ├── WAITING_BONUS → ボーナス解析(スキップ可) → WAITING_BIRTHDAY へ ├── WAITING_BIRTHDAY → 誕生日解析(スキップ可) → COMPLETED へ └── COMPLETED → DeleteItem ONBOARDING_STATE + PutItem PROFILE → 完了メッセージ ``` -------------------------------- ### Submit Onboarding Form Source: https://github.com/nesic-aws-ai-hackathon/auto-reward-service/blob/main/src/handlers/liff/onboarding.html Collects all financial data, including income, fixed costs, subscriptions, other expenses, bonus details, and anniversaries. It then sends this data to the API to calculate the reward budget and displays the result or an error message. ```javascript async function submitForm() { const income = parseInt(document.getElementById('income').value) || 0; if (income <= 0) { alert('手取り月収を入力してください'); return; } const btn = document.getElementById('submitBtn'); btn.disabled = true; document.getElementById('loading').classList.add('show'); const data = { monthly_income: income * 10000, fixed_costs: collectFixedCosts(), subscriptions: collectSubscriptions(), other_fixed_costs: collectOtherFixed(), bonus_months: collectBonusMonths(), bonus_amount: (parseInt(document.getElementById('bonus').value) || 0) * 10000, anniversaries: collectAnniversaries(), }; try { const headers = { 'Content-Type': 'application/json' }; if (idToken) headers['Authorization'] = `Bearer ${idToken}`; const res = await fetch(`${API_BASE}/api/onboarding`, { method: 'POST', headers, body: JSON.stringify(data), }); const result = await res.json(); if (res.ok && result.success) { const budgetMan = Math.floor(result.reward_budget / 10000); const budgetSen = Math.floor((result.reward_budget % 10000) / 1000); const budgetStr = budgetMan > 0 ? (budgetSen > 0 ? `${budgetMan}万${budgetSen}千円` : `${budgetMan}万円`) : `${result.reward_budget.toLocaleString()}円`; document.getElementById('loading').classList.remove('show'); // 完了メッセージを画面に表示 document.body.innerHTML = `
🎀

登録完了!

今月のごほうび枠
${budgetStr}
LINEにもお知らせしたよ✨
ごほうびを選びに行こう🍮