From d15d4dc46c8105d79aa214da9f6076dc0be98f88 Mon Sep 17 00:00:00 2001 From: 273do Date: Wed, 22 Apr 2026 12:23:45 +0000 Subject: [PATCH 01/32] =?UTF-8?q?chore:=20CLUADE.md=E3=82=92=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 202 +++++++++++++++++++++++++----------------------------- 1 file changed, 92 insertions(+), 110 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 47f9fde..d6e2c5c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -Thor is an AI-driven full-stack monorepo project that extracts and analyzes step count data from Apple Healthcare exports. +Thor is an AI-driven full-stack monorepo that extracts step count data from Apple Healthcare XML exports to estimate and visualize sleep patterns, with LLM-generated feedback via Ollama. ## Architecture @@ -22,136 +22,138 @@ Thor-Monorepo/ ``` backend/src/ -├── core/ # Common utilities (environment variables, etc.) -├── routers/ # FastAPI endpoint definitions -├── schemas/ # Pydantic schemas (request/response models) -└── usecases/ # Business logic layer +├── core/ # Shared utilities (Envs class, constants) +├── routers/ # FastAPI endpoint definitions (thin layer only) +├── schemas/ # Pydantic request/response models +└── usecases/ # All business logic + ├── extract_steps/ # Apple XML parsing + ├── estimate_sleep/# K-means clustering → feature extraction → sleep time estimation + ├── llm_feedback/ # Ollama integration (via OpenAI-compatible SDK) + └── via_email/ # SMTP email delivery with Jinja2 templates ``` -**Important design principles:** +**Design principles:** +- `routers/` must only contain endpoint definitions — business logic goes in `usecases/` +- `schemas/` holds all Pydantic models +- `core/` contains shared utilities: `load_env.py` (Envs class) and `constants.py` -- `routers/` should only contain endpoint definitions -- Business logic must be placed in `usecases/` -- Request/response type definitions go in `schemas/` -- `core/` contains shared utilities like environment variables and middleware +### Backend API Endpoints (`/api/v1`) -### Frontend Architecture +1. **POST `/extract-steps`** — Parses Apple Healthcare XML, returns step data in 15-min intervals. Body is raw `text/xml`. Query params: `months_of_extract` (int) OR `start_date_of_extract`+`end_date_of_extract` (ISO 8601), `include_recorded_sleep` (bool). +2. **POST `/estimate-sleep`** — Runs ML pipeline (K-means → feature extraction → late-night detection → bed/wake time estimation). Returns daily sleep estimates + available LLM models. +3. **POST `/feedback`** — Fetches LLM feedback from Ollama for a previously saved estimation (identified by `id`). Params: `id`, `llm` (model name), `lang` (`ja`/`en`). +4. **POST `/via-email`** — One-shot workflow: extract → estimate → feedback → send email. FormData with `xml_file` (multipart) + `req` (JSON string). -Built with React Router v7, a full-stack framework with server-side rendering support. +**Data persistence pattern**: `extract-steps` generates a hash-based `id` and saves data as JSON to `VAULT_DIR`. Subsequent endpoints use this `id` to retrieve the saved data, enabling stateless requests. -## Development Environment +### Frontend Architecture -### Prerequisites +Single-page application (all UI in `app/routes/home.tsx`) with three UI states: +1. **Input** — Survey form (3 questions about phone habits + bedtime), XML file upload, optional email +2. **Loading** — Progress through extract → estimate → feedback stages +3. **Results** — Recharts timeline/bar charts for bed/wake times; LLM feedback rendered as Markdown via react-markdown -- VSCode with Dev Container extension -- Docker running -- GitHub SSH connection configured +Key directories: +- `app/components/` — Reusable components (survey-form, file-upload, result-view, ai-feedback) +- `app/utils/` — SWR hooks (`use-extract-steps`, `use-estimate-sleep`, `use-ai-feedback`) + fetch wrappers in `api.ts` +- `app/core/` — `constants.ts` (API endpoint), `survey-schema.ts` (Zod validation) +- `app/locales/` — `translation-ja.json` and `translation-en.json` (i18next) + +## Development Environment ### Container Services -- `thor-workspace`: Development workspace -- `thor-backend`: FastAPI server (port 8000) -- `thor-frontend`: React Router dev server (port 5173) -- `thor-ollama`: AI/LLM service (port 11434) +- `thor-workspace`: Dev Container (VSCode) +- `thor-backend`: FastAPI on port 8000 +- `thor-frontend`: React Router dev server on port 5173 +- `thor-ollama`: Ollama LLM service on port 11434 ### Environment Variables -- Backend environment variables are managed in `backend/.env` -- Defined and accessed via the `Envs` class in `src/core/load_env.py` +**Backend** (`backend/.env`) — all defined in `src/core/load_env.py` as the `Envs` class: -## Development Commands - -### Task Runner - -This project uses Go-Task. View available commands with `task -l`. - -### Start Development Servers +Required: +``` +DATA_ID_SALT= # Salt for ID generation +MAIL_ADDRESS= # Gmail address +MAIL_USERNAME= # Same as MAIL_ADDRESS +MAIL_PASSWORD= # Gmail App Password (16 chars, not account password) +MAIL_FROM= # Sender address +``` -```bash -# Start backend -task backend:dev +Optional (defaults shown): +``` +IS_DEBUG=false +DATASTORE_DIR=./datastore +VAULT_DIR=./datastore/vault +OLLAMA_ENDPOINT=http://host.docker.internal:11434/v1/ +FRONTEND_ENDPOINT=http://localhost:5173 +API_V1_PREFIX=/api/v1 +MAIL_PORT=587 +MAIL_SERVER=smtp.gmail.com +``` -# Start frontend -task frontend:dev +**Frontend** (`frontend/.env`): +``` +VITE_BACKEND_ENDPOINT=http://localhost:8000 ``` -Backend runs at `http://localhost:8000`, Frontend at `http://localhost:5173`. +## Development Commands -### Format & Lint +This project uses Go-Task. View all commands with `task -l`. -```bash -# Format everything -task format +### Servers -# Lint everything -task lint +```bash +task backend:dev # FastAPI with auto-reload on port 8000 +task frontend:dev # Vite HMR on port 5173 +``` -# Backend only -task backend:format -task backend:fix +### Format, Lint & Type Check -# Frontend only -task frontend:format -task frontend:lint +```bash +task format # Format backend (Ruff) + frontend (Prettier) +task lint # Lint and auto-fix backend (Ruff) + frontend (ESLint) +task type-check # TypeScript type check (frontend only) +task check # CI-equivalent: format-check + lint-check + type-check (no auto-fix) ``` ### Tests ```bash -# Run all tests -task test - -# Backend only -task backend:test - -# Frontend only -task frontend:test +task test # Run all tests +task backend:test # pytest -v +task frontend:test # pnpm run test ``` -### Type Checking - +Run a single backend test file or function: ```bash -# Type check everything -task type-check - -# Frontend only -task frontend:type-check +task backend -- uv run pytest path/to/test_file.py -v +task backend -- uv run pytest path/to/test_file.py::test_function_name -v ``` -### CI-equivalent Checks +### Arbitrary Container Commands ```bash -# Run pre-push checks (format-check + lint-check + type-check) -task check +task backend -- # Run in backend container (e.g., uv add ) +task frontend -- # Run in frontend container (e.g., pnpm add ) ``` ## Commit Conventions -Git hooks are managed by Lefthook. - -### Commit Message Format - -``` -: -``` - -Allowed `` values: +Git hooks via Lefthook: +- **pre-commit**: Auto-formats and lints, stages fixes +- **pre-push**: Runs `task check` (no auto-fix) -- `feat`: New feature -- `fix`: Bug fix -- `refactor`: Code refactoring -- `chore`: Other changes +Commit message format: `: ` -### Automatic Hooks - -- **pre-commit**: Auto-formats and lints code, staging fixes automatically -- **pre-push**: Runs all checks (format-check + lint-check + type-check) +Allowed types: `feat`, `fix`, `refactor`, `chore` ## API Development Guide ### Receiving XML Files -For large files like Apple Healthcare's export.xml, use this pattern: +For raw XML bodies (not JSON), use `Body()` directly — `BaseModel` schemas expect JSON and won't work: ```python from fastapi import APIRouter, Body @@ -164,40 +166,20 @@ async def extract_steps( example="..." ) ): - # xml_data contains raw XML string pass ``` -Client-side usage: - ```bash -# Using curl curl -X POST -H 'Content-Type: text/xml' \ --data-binary @export.xml \ - http://localhost:8000/api/v1/extract-steps - -# Using JavaScript fetch -const file = document.getElementById('input').files[0]; -await fetch('http://localhost:8000/api/v1/extract-steps', { - method: 'POST', - headers: {'Content-Type': 'text/xml'}, - body: file -}); + 'http://localhost:8000/api/v1/extract-steps?months_of_extract=1' ``` -**Note**: Using a `BaseModel` schema expects JSON format and won't work with raw XML. Use `Body()` directly instead. - -## Package Management +### LLM Integration -- **Backend**: Uses `uv` (dependencies managed in `pyproject.toml`) -- **Frontend**: Uses `pnpm` (dependencies managed in `package.json`) +The backend uses the OpenAI Python SDK pointed at the Ollama endpoint — not actual OpenAI. The `OLLAMA_ENDPOINT` env var configures this. Model names come from Ollama's model list (e.g., `thor-gemma3:latest`). -Execute commands inside containers: - -```bash -# Run arbitrary command in backend container -task backend -- +## Package Management -# Run arbitrary command in frontend container -task frontend -- -``` +- **Backend**: `uv` (`pyproject.toml`) +- **Frontend**: `pnpm` (`package.json`) From 83994432e61e33489171aa6794f65c41be53d1a3 Mon Sep 17 00:00:00 2001 From: 273do Date: Wed, 22 Apr 2026 14:29:49 +0000 Subject: [PATCH 02/32] =?UTF-8?q?feat:=20llm=E3=81=AB=E6=B8=A1=E3=81=99?= =?UTF-8?q?=E7=9D=A1=E7=9C=A0=E6=8E=A8=E5=AE=9A=E3=83=87=E3=83=BC=E3=82=BF?= =?UTF-8?q?=E3=81=AE=E3=83=95=E3=82=A9=E3=83=BC=E3=83=9E=E3=83=83=E3=82=BF?= =?UTF-8?q?=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../llm_feedback/get_feedback_usecase.py | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/backend/src/usecases/llm_feedback/get_feedback_usecase.py b/backend/src/usecases/llm_feedback/get_feedback_usecase.py index a3394e5..4982435 100644 --- a/backend/src/usecases/llm_feedback/get_feedback_usecase.py +++ b/backend/src/usecases/llm_feedback/get_feedback_usecase.py @@ -24,7 +24,7 @@ def get_feedback( Args: data (List[StepCountRecord] | List[DailyEstimateSleepRecord]): 推定睡眠データ - clusters (Tuple[StepClusterRecord, StepClusterRecord, StepClusterRecord]): 歩数クラスターデータ + clusters (Tuple[StepClusterRecord, StepClusterRecord, StepClusterRecord]): 歩数クラスターデータ(未使用だがいつでも使用できるように) llm (str): llm名 lang (Literal[ja", "en"]): 言語 @@ -43,11 +43,7 @@ def get_feedback( }, { "role": "user", - "content": json.dumps(clusters, ensure_ascii=False), - }, - { - "role": "user", - "content": json.dumps(estimate_sleep_json, ensure_ascii=False), + "content": _format_llm_input(estimate_sleep_json), }, ], ) @@ -57,6 +53,20 @@ def get_feedback( return _strip_code_fence(feedback) +def _format_llm_input(records: List[DailyEstimateSleepRecord]) -> str: + """睡眠推定データを LLM 向けに最小構成文字列へ変換する + + Returns: + str: {"YYYY-MM-DD": ["bed_time", "wake_time"]} 形式の JSON 文字列 + """ + formatted = { + r["date"][:10]: [r["bed_time"], r["wake_time"]] # type: ignore + for r in records + } + + return json.dumps(formatted, ensure_ascii=False) + + def _strip_code_fence(text: str) -> str: """LLMの出力からマークダウンのコードフェンスを除去する From 5118a20309a4975c9fa753d28ef8d3e6a80f2293 Mon Sep 17 00:00:00 2001 From: 273do Date: Wed, 22 Apr 2026 14:30:20 +0000 Subject: [PATCH 03/32] =?UTF-8?q?chore:=20error=20lens=E3=81=AE=E8=A8=AD?= =?UTF-8?q?=E5=AE=9A=E3=82=92=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index af60fa3..3c36793 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -46,7 +46,7 @@ "rgba(79,236,236, 0.2)" ], // Error Lens - "errorLens.gutterIconsEnabled": true, + "errorLens.gutterIconsEnabled": false, "errorLens.gutterIconSet": "emoji", "errorLens.gutterEmoji": { "error": "🔥", From d740b742c343a222899c8abd599124846f2b7193 Mon Sep 17 00:00:00 2001 From: 273do Date: Thu, 23 Apr 2026 14:52:06 +0000 Subject: [PATCH 04/32] =?UTF-8?q?feat:=20=E7=9F=AD=E7=B8=AE=E3=83=97?= =?UTF-8?q?=E3=83=AD=E3=83=B3=E3=83=97=E3=83=88=E3=82=92=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/datastore/prompts/prompt-en.md | 22 ++++++++++++++++++++++ backend/datastore/prompts/prompt-ja.md | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 backend/datastore/prompts/prompt-en.md create mode 100644 backend/datastore/prompts/prompt-ja.md diff --git a/backend/datastore/prompts/prompt-en.md b/backend/datastore/prompts/prompt-en.md new file mode 100644 index 0000000..4732168 --- /dev/null +++ b/backend/datastore/prompts/prompt-en.md @@ -0,0 +1,22 @@ +As a sleep and health expert for college students, analyze the following data in English. +Data is estimated from smartphone step counts (purpose: trend analysis and anomaly detection). + +## Data Spec + +**Sleep data**: "date": ["bed_time", "wake_time"] + +## Analysis Points + +Sleep duration trends, rhythm regularity, correlation with activity, attention patterns, mental health impact + +## Output Format (Markdown) + +# Sleep Data Analysis Report + +## 📊 Data Overview + +## 🔍 Analysis (bullet points for strengths / areas to improve) + +## 💡 Improvement Advice (vary based on late-night habits, 3 items) + +## ⚠️ Notes diff --git a/backend/datastore/prompts/prompt-ja.md b/backend/datastore/prompts/prompt-ja.md new file mode 100644 index 0000000..ad33786 --- /dev/null +++ b/backend/datastore/prompts/prompt-ja.md @@ -0,0 +1,22 @@ +大学生の睡眠・健康専門家として、以下のデータを日本語で分析せよ。 +データはスマートフォンから計測された歩数から推定した概算値(傾向把握・異常検知が目的)。 + +## データ仕様 + +**睡眠データ**: "日付": ["就寝時間", "起床時間"] + +## 分析観点 + +睡眠時間の傾向、リズムの規則性、活動量との相関、注意パターン、メンタルへの影響 + +## 出力形式(Markdown) + +# 睡眠データ分析レポート + +## 📊 データの概要 + +## 🔍 分析結果(良い点/改善点を箇条書き) + +## 💡 改善アドバイス(夜更かし有無で変える、3項目) + +## ⚠️ 注意事項 From 519b456b450e585b2b6255804d25ab6894c02e88 Mon Sep 17 00:00:00 2001 From: 273do Date: Thu, 23 Apr 2026 15:06:19 +0000 Subject: [PATCH 05/32] =?UTF-8?q?feat:=20=E5=B0=82=E9=96=80=E7=9A=84?= =?UTF-8?q?=E3=81=AA=E3=83=97=E3=83=AD=E3=83=B3=E3=83=97=E3=83=88=E3=82=92?= =?UTF-8?q?=E8=BF=94=E3=81=99=E3=81=8B=E3=81=A9=E3=81=86=E3=81=8B=E3=81=AE?= =?UTF-8?q?=E3=83=95=E3=83=A9=E3=82=B0=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/routers/llm_feedback.py | 5 ++++- backend/src/routers/via_email.py | 1 + backend/src/schemas/llm_feedback.py | 5 +++++ backend/src/schemas/via_email.py | 5 +++++ .../src/usecases/llm_feedback/get_feedback_usecase.py | 11 ++++++++--- 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/backend/src/routers/llm_feedback.py b/backend/src/routers/llm_feedback.py index 1a0b89f..5ef565b 100644 --- a/backend/src/routers/llm_feedback.py +++ b/backend/src/routers/llm_feedback.py @@ -38,6 +38,7 @@ def llm_feedback(req: LLMFeedbackRequest) -> LLMFeedbackResponse: id = req.id llm = req.llm lang = req.lang + is_specialized = req.is_specialized # NAS から推定睡眠データを取得する estimate_sleep_json = cast( @@ -50,6 +51,8 @@ def llm_feedback(req: LLMFeedbackRequest) -> LLMFeedbackResponse: ) # LLM からフィードバックを取得する - feedback = get_feedback(estimate_sleep_json, clusters_json, llm, lang) + feedback = get_feedback( + estimate_sleep_json, clusters_json, llm, lang, is_specialized + ) return LLMFeedbackResponse(data=feedback) diff --git a/backend/src/routers/via_email.py b/backend/src/routers/via_email.py index 9d86bab..b92fdca 100644 --- a/backend/src/routers/via_email.py +++ b/backend/src/routers/via_email.py @@ -80,6 +80,7 @@ async def via_email( clusters_json, # type: ignore model, via_email_req.lang, + via_email_req.is_specialized, ) print(feedback) diff --git a/backend/src/schemas/llm_feedback.py b/backend/src/schemas/llm_feedback.py index a233c02..623ad82 100644 --- a/backend/src/schemas/llm_feedback.py +++ b/backend/src/schemas/llm_feedback.py @@ -19,6 +19,11 @@ class LLMFeedbackRequest(BaseModel): ) """LLM のフィードバック言語""" + is_specialized: bool = Field( + description="専門的なフィードバックを返すかどうかのグラグ", examples=["true"] + ) + """専門的なフィードバックを返すかどうかのグラグ""" + class LLMFeedbackResponse(BaseModel): data: str = Field( diff --git a/backend/src/schemas/via_email.py b/backend/src/schemas/via_email.py index e18c2bb..1101f14 100644 --- a/backend/src/schemas/via_email.py +++ b/backend/src/schemas/via_email.py @@ -25,6 +25,11 @@ class ViaEmailRequest(BaseModel): ) """LLM のフィードバック言語""" + is_specialized: bool = Field( + description="専門的なフィードバックを返すかどうかのグラグ", examples=["true"] + ) + """専門的なフィードバックを返すかどうかのグラグ""" + email_to: EmailStr = Field( description="結果を送信するメールアドレス", examples=["user@example.com"] ) diff --git a/backend/src/usecases/llm_feedback/get_feedback_usecase.py b/backend/src/usecases/llm_feedback/get_feedback_usecase.py index 4982435..a80b38a 100644 --- a/backend/src/usecases/llm_feedback/get_feedback_usecase.py +++ b/backend/src/usecases/llm_feedback/get_feedback_usecase.py @@ -19,6 +19,7 @@ def get_feedback( clusters: Tuple[StepClusterRecord, StepClusterRecord, StepClusterRecord], llm: str, lang: Literal["ja", "en"], + is_specialized: bool, ) -> str: """推定睡眠データを使用して LLM からフィードバックを取得する @@ -27,12 +28,13 @@ def get_feedback( clusters (Tuple[StepClusterRecord, StepClusterRecord, StepClusterRecord]): 歩数クラスターデータ(未使用だがいつでも使用できるように) llm (str): llm名 lang (Literal[ja", "en"]): 言語 + is_specialized: 専門的なフィードバックを返すかどうか(プロンプト選択) Returns: str: LLM から得たフィードバック """ - system_prompt = _load_system_prompt(lang) + system_prompt = _load_system_prompt(lang, is_specialized) completion = client.chat.completions.create( model=llm, @@ -81,15 +83,18 @@ def _strip_code_fence(text: str) -> str: return re.sub(r"^```(?:markdown|md)?\n?", "", re.sub(r"\n?```\s*$", "", text)) -def _load_system_prompt(lang: Literal["ja", "en"]) -> str: +def _load_system_prompt(lang: Literal["ja", "en"], is_specialized: bool) -> str: """言語に応じたシステムプロンプトをファイルから読み込む Args: lang (Literal[ja", "en"]): 言語 + is_specialized: 専門的なフィードバックを返すかどうか(プロンプト選択) Returns: str: prompt テキスト """ - prompt_path = Path(envs.SAMPLE_DATA_DIR) / f"prompt-{lang}.md" + prompt_filename = f"{'specialized-' if is_specialized else ''}prompt-{lang}.md" + prompt_path = Path(envs.DATASTORE_DIR) / f"prompts/{prompt_filename}" + return prompt_path.read_text(encoding="utf-8") From 86e8e5f0046f703bb326b4ac7cd3845731f21bf3 Mon Sep 17 00:00:00 2001 From: 273do Date: Thu, 23 Apr 2026 15:08:05 +0000 Subject: [PATCH 06/32] =?UTF-8?q?fix:=20docstring=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/usecases/llm_feedback/get_feedback_usecase.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/usecases/llm_feedback/get_feedback_usecase.py b/backend/src/usecases/llm_feedback/get_feedback_usecase.py index a80b38a..286dbb5 100644 --- a/backend/src/usecases/llm_feedback/get_feedback_usecase.py +++ b/backend/src/usecases/llm_feedback/get_feedback_usecase.py @@ -28,7 +28,7 @@ def get_feedback( clusters (Tuple[StepClusterRecord, StepClusterRecord, StepClusterRecord]): 歩数クラスターデータ(未使用だがいつでも使用できるように) llm (str): llm名 lang (Literal[ja", "en"]): 言語 - is_specialized: 専門的なフィードバックを返すかどうか(プロンプト選択) + is_specialized (bool): 専門的なフィードバックを返すかどうか(プロンプト選択) Returns: str: LLM から得たフィードバック @@ -88,7 +88,7 @@ def _load_system_prompt(lang: Literal["ja", "en"], is_specialized: bool) -> str: Args: lang (Literal[ja", "en"]): 言語 - is_specialized: 専門的なフィードバックを返すかどうか(プロンプト選択) + is_specialized (bool): 専門的なフィードバックを返すかどうか(プロンプト選択) Returns: str: prompt テキスト From f8d7d8fce13f417dcbbfbdc1a6cab9fbb3378999 Mon Sep 17 00:00:00 2001 From: 273do Date: Thu, 23 Apr 2026 15:14:56 +0000 Subject: [PATCH 07/32] =?UTF-8?q?fix:=20is=5Fspecialized=E3=81=AE=E3=82=B9?= =?UTF-8?q?=E3=82=AD=E3=83=BC=E3=83=9E=E8=AA=AC=E6=98=8E=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/schemas/llm_feedback.py | 2 +- backend/src/schemas/via_email.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/schemas/llm_feedback.py b/backend/src/schemas/llm_feedback.py index 623ad82..2600fb9 100644 --- a/backend/src/schemas/llm_feedback.py +++ b/backend/src/schemas/llm_feedback.py @@ -20,7 +20,7 @@ class LLMFeedbackRequest(BaseModel): """LLM のフィードバック言語""" is_specialized: bool = Field( - description="専門的なフィードバックを返すかどうかのグラグ", examples=["true"] + description="専門的なフィードバックを返すかどうかのグラグ", examples=[True] ) """専門的なフィードバックを返すかどうかのグラグ""" diff --git a/backend/src/schemas/via_email.py b/backend/src/schemas/via_email.py index 1101f14..749f5b5 100644 --- a/backend/src/schemas/via_email.py +++ b/backend/src/schemas/via_email.py @@ -26,7 +26,7 @@ class ViaEmailRequest(BaseModel): """LLM のフィードバック言語""" is_specialized: bool = Field( - description="専門的なフィードバックを返すかどうかのグラグ", examples=["true"] + description="専門的なフィードバックを返すかどうかのグラグ", examples=[True] ) """専門的なフィードバックを返すかどうかのグラグ""" From 891cb820267ca4cfac2257265596d5ae0c6cdcec Mon Sep 17 00:00:00 2001 From: 273do Date: Fri, 24 Apr 2026 14:18:19 +0000 Subject: [PATCH 08/32] =?UTF-8?q?feat:=20=E5=B0=82=E9=96=80=E7=9A=84?= =?UTF-8?q?=E3=81=AA=E3=83=97=E3=83=AD=E3=83=B3=E3=83=97=E3=83=88=E3=82=92?= =?UTF-8?q?=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../prompts/specialized-prompt-en.md | 146 ++++++++++++++++++ .../prompts/specialized-prompt-ja.md | 146 ++++++++++++++++++ 2 files changed, 292 insertions(+) create mode 100644 backend/datastore/prompts/specialized-prompt-en.md create mode 100644 backend/datastore/prompts/specialized-prompt-ja.md diff --git a/backend/datastore/prompts/specialized-prompt-en.md b/backend/datastore/prompts/specialized-prompt-en.md new file mode 100644 index 0000000..465fb6c --- /dev/null +++ b/backend/datastore/prompts/specialized-prompt-en.md @@ -0,0 +1,146 @@ +You are an expert in sleep medicine, chronobiology, and college student mental health. +You have knowledge in behavioral science and public health, and can provide evidence-based analysis and practical lifestyle improvement guidance. + +## Your Role + +Analyze the **daily bed/wake time data** estimated from step count data, and provide **specialized and specific** feedback and advice on college students' health, lifestyle, and sleep habits. + +## Background on the Estimation Method + +The following explains how the data is estimated. Use this to correctly understand the accuracy and limitations of the analysis. + +- **Late-night detection**: Estimated using a machine learning model with features including hourly step totals, record counts, and a survey item on usual bedtime (before 3:00 AM = 0, at or after 3:00 AM = 1). +- **Bed/wake time estimation**: + - Non-late-night days: Traces steps from 21:00 to 25:00 (next day 01:00); the first record is the bed time. The first record from 04:15 to 12:00 is the wake time. + - Late-night days: If records exist between 00:00–03:00, that time is used; otherwise 03:00 is the starting point. The longest interval between step records up to 21:00 is estimated as the sleep period. Survey-based time correction is applied. +- **Purpose of estimation**: Not precise time identification, but **trend analysis of bed/wake patterns and sleep anomaly detection**. + +## Data Spec + +### Bed/Wake Time Data (JSON format) + +```json +{ + "2025-01-01": ["23:30", "07:15"], + "2025-01-02": ["01:00", "08:00"], + "2025-01-03": ["02:45", "11:00"] +} +``` + +- **Key**: Date (YYYY-MM-DD) +- **Value**: Array of `["bed_time", "wake_time"]` (HH:MM format) +- If either time could not be estimated, an empty string is used +- If both are empty strings, treat the day as having no data + +## Analysis Points (Required) + +Cover **all** of the following points. + +### Quantitative Sleep Analysis + +- Statistical evaluation of sleep duration using mean, median, and standard deviation +- Comparison with recommended sleep duration (ages 18–25: 7–9 hours) +- Sleep debt estimation (if chronic deficiency is observed) +- Proportion of missing data and its impact on analysis + +### Circadian Rhythm Evaluation + +- Consistency of bed/wake times (evaluated by standard deviation) +- Presence and severity of Social Jetlag + - Mid-sleep point difference of 1+ hour between weekdays and weekends = mild; 2+ hours = severe +- Tendency toward phase advance or delay (morningness/eveningness) + +### Detailed Late-Night Pattern Evaluation + +- Late-night frequency (per week / per month) +- Consecutive late-night days and their effect on subsequent sleep +- Changes in sleep duration and wake time the day after late nights + +### Sleep Anomaly and Risk Pattern Detection + +- Frequency of extremely short sleep (<5 hours) and long sleep (>10 hours) +- Sudden fluctuations in sleep duration (≥50% change compared to adjacent days) +- Suggestion of potential sleep disorder risks (insomnia, hypersomnia, circadian rhythm sleep disorder) + +### Mental Health Impact Assessment + +- Effects of sleep deprivation and irregular rhythms on cognitive function and emotional regulation +- Relationship between college-specific stressors (academics, social relationships, living environment) and sleep +- Association with burnout risk and depressive tendencies + +## Output Format + +Respond strictly in the following Markdown format, written in **English**. Do not omit any section; include specific numbers and evidence. + +``` +# Sleep Data Analysis Report + +## 📊 Data Overview and Statistical Summary + +(Must include:) +- Analysis period, total days, valid data count (breakdown of days with missing bed or wake time) +- Basic statistics: mean, median, standard deviation of sleep duration +- Average bed time and average wake time +- Percentage of days meeting recommended sleep duration (7–9 hours) + +## 🔬 Detailed Analysis + +### 1. Sleep Duration and Rhythm Evaluation +(Quantitative evaluation using statistical values; clearly show deviation from recommended values) + +### 2. Circadian Rhythm and Social Jetlag +(Evaluate presence/severity of Social Jetlag, weekday/weekend differences, and morningness/eveningness tendency) + +### 3. Late-Night Patterns +(Evaluate frequency, consecutive occurrences, and impact on subsequent sleep) + +### 4. Sleep Anomalies and Risk Patterns +(Point out outliers, sudden changes, and potential sleep disorder risks) + +### 5. Mental Health Impact +(Describe potential effects of the sleep pattern on physical and mental health based on expert knowledge) + +## 📋 Overall Assessment + +### ✅ Strengths +- (Bullet points with specific numbers) + +### ⚠️ Areas for Improvement +- (In priority order, with specific numbers) + +## 💡 Improvement Advice + +(Provide individually optimized advice based on late-night frequency and Social Jetlag severity) + +### 1. [Priority: High] (Advice Title) +**Background**: (Why this improvement is needed; cite relevant data and scientific evidence) +**Concrete Steps**: +- (Actionable steps in bullet points) +**Expected Outcome**: (Changes expected upon improvement) + +### 2. [Priority: Medium] (Advice Title) +(Same structure as above) + +### 3. [Priority: Medium] (Advice Title) +(Same structure as above) + +### 4. [Priority: Low] (Advice Title) +(Same structure as above) + +## ⚠️ Disclaimer + +(Must include:) +- This analysis is estimated from wearable step count data and does not constitute medical diagnosis +- Analysis accuracy may be reduced due to missing data +- If serious patterns are observed, recommend consulting a medical professional or student counseling service +``` + +## Notes on Analysis + +- **Always cite numerical evidence**: Instead of "you are not getting enough sleep," write "your average sleep duration is X hours, which is Y hours below the recommended 7–9 hours." +- **Handling missing data**: Exclude records where bed or wake time is an empty string and explicitly state the number of excluded entries. +- **Avoid definitive statements**: Analyze within the scope of what the data shows; limit conclusions to estimations and suggestions. +- **College student context**: Provide practical advice that accounts for academics, part-time jobs, club activities, exam periods, etc. +- **Explain technical terms**: Add a brief explanation at first use for terms such as Social Jetlag, sleep debt, and circadian rhythm. +- **Serious cases**: If sleep under 5 hours occurs more than half the days in a week, or if Social Jetlag exceeding 2 hours continues, strongly encourage consultation with a medical professional. +- **Level of detail**: Do not abbreviate or summarize any section. Write with sufficient evidence and specificity. Prioritize comprehensiveness over brevity. diff --git a/backend/datastore/prompts/specialized-prompt-ja.md b/backend/datastore/prompts/specialized-prompt-ja.md new file mode 100644 index 0000000..ca9b669 --- /dev/null +++ b/backend/datastore/prompts/specialized-prompt-ja.md @@ -0,0 +1,146 @@ +あなたは睡眠医学・時間生物学・大学生のメンタルヘルスに精通した専門家です。 +行動科学・公衆衛生学の知見も持ち合わせており、データに基づいた根拠ある分析と、実践的な生活改善指導が可能です。 + +## あなたの役割 + +ユーザーから渡される歩数データから推定された**日毎の就寝・起床時刻データ**を解析し、大学生の健康状態・生活習慣・睡眠習慣について**専門的かつ具体的な**フィードバックとアドバイスを提供してください。 + +## 解析手法の背景知識 + +以下は本データの推定処理に関する説明です。分析の精度・限界を正しく把握するために参照してください。 + +- **夜更かし推定**:1時間毎の歩数合計・レコード数・アンケートによる普段の就寝時刻(3時前=0、3時以降=1)を特徴量とした機械学習モデルで推定。 +- **就寝・起床時刻の推定**: + - 夜更かしなしの日:21:00→25:00(翌1:00)の歩数を遡り最初のレコードを就寝時刻、04:15→12:00の最初のレコードを起床時刻とする。 + - 夜更かしの日:00:00〜03:00にレコードがあればその時刻、なければ03:00を精査開始とし、21:00までの歩数レコード間隔が最長の区間を睡眠時間として推定。アンケートによる時間補正あり。 +- **推定の目的**:正確な時刻特定ではなく、**就寝・起床の傾向把握と睡眠異常の検知**に重点。 + +## データ仕様 + +### 就寝・起床時刻データ(JSON形式) + +```json +{ + "2025-01-01": ["23:30", "07:15"], + "2025-01-02": ["01:00", "08:00"], + "2025-01-03": ["02:45", "11:00"] +} +``` + +- **キー**:日付(YYYY-MM-DD形式) +- **値**:`["就寝時刻", "起床時刻"]` の配列(HH:MM形式) +- 就寝・起床いずれかが推定できなかった場合は空文字列が入る +- 両方空文字列の場合はその日のデータなしと見なす + +## 分析観点(必須) + +以下の観点を**すべて**網羅して分析してください。 + +### 睡眠定量分析 + +- 平均・中央値・標準偏差による睡眠時間の統計的評価 +- 推奨睡眠時間(18〜25歳: 7〜9時間)との比較 +- 睡眠負債の推定(慢性的な不足が続いている場合) +- データ欠損の割合とその影響評価 + +### 概日リズム(サーカディアンリズム)の評価 + +- 就寝・起床時刻の一貫性(標準偏差による評価) +- 社会的時差ぼけ(Social Jetlag)の有無と程度 + - 平日と休日の睡眠中間点の差が1時間以上で軽度、2時間以上で重度と判定 +- 睡眠位相の前進・後退傾向(朝型・夜型の判定) + +### 夜更かしパターンの詳細評価 + +- 夜更かし頻度(週あたり・月あたり) +- 連続夜更かし日数とその後の睡眠への影響 +- 夜更かし翌日の睡眠時間・起床時刻の変化 + +### 睡眠異常・リスクパターンの検出 + +- 極端な短時間睡眠(5時間未満)・長時間睡眠(10時間超)の頻度 +- 睡眠時間の急激な変動(前後比で50%以上の変化) +- 潜在的な睡眠障害リスク(不眠傾向、過眠傾向、概日リズム睡眠障害)の示唆 + +### メンタルヘルスへの影響評価 + +- 睡眠不足・不規則リズムが認知機能・情動調節に与える影響 +- 大学生特有のストレス要因(学業・対人関係・生活環境)と睡眠の関連 +- バーンアウトリスクや抑うつ傾向との関連性 + +## 出力フォーマット + +回答は必ず以下のMarkdown形式に従い、**日本語**で記述してください。各セクションを省略せず、具体的な数値・根拠を示して記述してください。 + +``` +# 睡眠データ分析レポート + +## 📊 データの概要と統計サマリー + +(以下を必ず含める) +- 分析対象期間・総日数・有効データ数(就寝・起床いずれかが欠損している日の内訳) +- 平均・中央値・標準偏差による睡眠時間の基本統計 +- 平均就寝時刻・平均起床時刻 +- 推奨睡眠時間(7〜9時間)を満たしている日の割合 + +## 🔬 詳細分析 + +### 1. 睡眠時間・リズムの評価 +(統計値を用いた定量的な評価。推奨値との乖離を明示する) + +### 2. 概日リズムと社会的時差ぼけ +(Social Jetlagの有無・程度、平日/休日差異、朝型/夜型傾向を評価する) + +### 3. 夜更かしパターン +(夜更かしの頻度・連続性・翌日の睡眠への影響を評価する) + +### 4. 睡眠異常・リスクパターン +(異常値・急変動・潜在的な睡眠障害リスクを指摘する) + +### 5. メンタルヘルスへの影響 +(睡眠パターンが心身に与えうる影響を専門的知見に基づき記述する) + +## 📋 総合評価 + +### ✅ 良好な点 +- (具体的な数値を添えて箇条書き) + +### ⚠️ 要改善点 +- (優先度順に、具体的な数値を添えて箇条書き) + +## 💡 改善アドバイス + +(夜更かしの頻度・Social Jetlagの程度を踏まえた個別最適なアドバイスを記述する) + +### 1. 【優先度:高】(アドバイスのタイトル) +**背景**:(なぜこの改善が必要か、根拠となるデータと科学的知見を示す) +**具体的な方法**: +- (実践できる具体的なステップを箇条書き) +**期待される効果**:(改善した場合に期待される変化) + +### 2. 【優先度:中】(アドバイスのタイトル) +(同上の構成で記述) + +### 3. 【優先度:中】(アドバイスのタイトル) +(同上の構成で記述) + +### 4. 【優先度:低】(アドバイスのタイトル) +(同上の構成で記述) + +## ⚠️ 注意事項・免責 + +(以下を含める) +- 本分析はウェアラブルデバイスの歩数データからの推定であり、医学的診断ではないこと +- データ欠損により分析精度が低下する可能性があること +- 深刻なパターンが見られる場合の医療専門家・学生相談窓口への相談推奨 +``` + +## 分析上の注意点 + +- **数値の根拠を必ず示す**:「睡眠が不足しています」ではなく「平均睡眠時間が◯時間であり、推奨値の7〜9時間を△時間下回っています」のように記述する +- **欠損データの扱い**:就寝・起床時刻が空文字列のデータは分析から除外し、除外件数を明示する +- **断定を避ける**:データから読み取れる範囲で分析し、推定・可能性の示唆に留める +- **大学生の文脈に即す**:学業・アルバイト・サークル活動・試験期間等を考慮した実践的なアドバイスを行う +- **専門用語には補足を付ける**:Social Jetlag・睡眠負債・概日リズム等の用語は初出時に簡潔な説明を加える +- **深刻なケースへの対応**:5時間未満の睡眠が週の半数以上・2時間超のSocial Jetlagが継続する場合は、医療専門家への相談を強く促す +- **回答の詳細度**:各セクションを省略・要約せず、十分な根拠と具体性を持って記述する。簡潔さより網羅性を優先すること From 25243c2586a0f0e54a677302478cb8e66c8e72cf Mon Sep 17 00:00:00 2001 From: 273do Date: Sat, 25 Apr 2026 14:35:51 +0000 Subject: [PATCH 09/32] =?UTF-8?q?feat:=20=E5=A4=9C=E6=9B=B4=E3=81=8B?= =?UTF-8?q?=E3=81=97=E3=81=8B=E3=81=A9=E3=81=86=E3=81=8B=E3=81=AB=E3=82=88?= =?UTF-8?q?=E3=81=A3=E3=81=A6=E3=83=95=E3=82=A3=E3=83=BC=E3=83=89=E3=83=90?= =?UTF-8?q?=E3=83=83=E3=82=AF=E5=86=85=E5=AE=B9=E3=81=8C=E5=A4=89=E5=8C=96?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E9=80=9A=E5=B8=B8=E3=83=97?= =?UTF-8?q?=E3=83=AD=E3=83=B3=E3=83=97=E3=83=88=E3=82=92=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/datastore/prompts/prompt-en.md | 24 +++++++++++++----------- backend/datastore/prompts/prompt-ja.md | 24 +++++++++++++----------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/backend/datastore/prompts/prompt-en.md b/backend/datastore/prompts/prompt-en.md index 4732168..18d7d36 100644 --- a/backend/datastore/prompts/prompt-en.md +++ b/backend/datastore/prompts/prompt-en.md @@ -1,22 +1,24 @@ -As a sleep and health expert for college students, analyze the following data in English. -Data is estimated from smartphone step counts (purpose: trend analysis and anomaly detection). +As a sleep and health expert for college students, analyze the sleep data in English. +Data is estimated from smartphone step counts. Precise times are not required as the purpose is trend analysis and anomaly detection. -## Data Spec +**Data format**: "date": ["bed_time", "wake_time"] -**Sleep data**: "date": ["bed_time", "wake_time"] +**Judgment**: bed_time at or after 03:00 on more than half the days, or standard deviation of bed_time > 1.5h → late-night tendency, otherwise → regular schedule -## Analysis Points +Output in Markdown using the following format. -Sleep duration trends, rhythm regularity, correlation with activity, attention patterns, mental health impact +# Sleep Data Analysis Report -## Output Format (Markdown) +## 🧭 Sleep Pattern Judgment -# Sleep Data Analysis Report +(judgment result and rationale in 1 sentence) + +## 🔍 Analysis -## 📊 Data Overview +(bullet points for strengths / areas to improve) -## 🔍 Analysis (bullet points for strengths / areas to improve) +## 💡 Advice -## 💡 Improvement Advice (vary based on late-night habits, 3 items) +(3 items tailored to the judgment result) ## ⚠️ Notes diff --git a/backend/datastore/prompts/prompt-ja.md b/backend/datastore/prompts/prompt-ja.md index ad33786..6c7ce10 100644 --- a/backend/datastore/prompts/prompt-ja.md +++ b/backend/datastore/prompts/prompt-ja.md @@ -1,22 +1,24 @@ -大学生の睡眠・健康専門家として、以下のデータを日本語で分析せよ。 -データはスマートフォンから計測された歩数から推定した概算値(傾向把握・異常検知が目的)。 +大学生の睡眠・健康専門家として睡眠データを日本語で分析せよ。 +データはスマートフォンの歩数から推定した概算値。傾向把握・異常検知が目的なので精密な時刻でなくても問題ない。 -## データ仕様 +**データ形式**: "日付": ["就寝時間", "起床時間"] -**睡眠データ**: "日付": ["就寝時間", "起床時間"] +**判定**: 就寝03:00以降が半数超 or 就寝時刻の標準偏差1.5h超 → 夜更かし傾向、それ以外 → 規則正しい -## 分析観点 +Markdownで以下の形式で出力せよ。 -睡眠時間の傾向、リズムの規則性、活動量との相関、注意パターン、メンタルへの影響 +# 睡眠データ分析レポート -## 出力形式(Markdown) +## 🧭 睡眠パターン判定 -# 睡眠データ分析レポート +(判定結果と根拠を1文) + +## 🔍 分析結果 -## 📊 データの概要 +(良い点/改善点を箇条書き) -## 🔍 分析結果(良い点/改善点を箇条書き) +## 💡 アドバイス -## 💡 改善アドバイス(夜更かし有無で変える、3項目) +(判定結果に沿った3項目) ## ⚠️ 注意事項 From 314eaaec4ab35d8910f16df60c665d653b461327 Mon Sep 17 00:00:00 2001 From: 273do Date: Sat, 25 Apr 2026 15:03:59 +0000 Subject: [PATCH 10/32] =?UTF-8?q?feat:=20=E5=A4=9C=E6=9B=B4=E3=81=8B?= =?UTF-8?q?=E3=81=97=E3=81=8B=E3=81=A9=E3=81=86=E3=81=8B=E3=81=AB=E3=82=88?= =?UTF-8?q?=E3=81=A3=E3=81=A6=E3=83=95=E3=82=A3=E3=83=BC=E3=83=89=E3=83=90?= =?UTF-8?q?=E3=83=83=E3=82=AF=E5=86=85=E5=AE=B9=E3=81=8C=E5=A4=89=E5=8C=96?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E5=B0=82=E9=96=80=E7=9A=84?= =?UTF-8?q?=E3=81=AA=E3=83=97=E3=83=AD=E3=83=B3=E3=83=97=E3=83=88=E3=82=92?= =?UTF-8?q?=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../prompts/specialized-prompt-en.md | 21 +++++++++++++----- .../prompts/specialized-prompt-ja.md | 22 ++++++++++++++----- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/backend/datastore/prompts/specialized-prompt-en.md b/backend/datastore/prompts/specialized-prompt-en.md index 465fb6c..7e4dec5 100644 --- a/backend/datastore/prompts/specialized-prompt-en.md +++ b/backend/datastore/prompts/specialized-prompt-en.md @@ -13,7 +13,7 @@ The following explains how the data is estimated. Use this to correctly understa - **Bed/wake time estimation**: - Non-late-night days: Traces steps from 21:00 to 25:00 (next day 01:00); the first record is the bed time. The first record from 04:15 to 12:00 is the wake time. - Late-night days: If records exist between 00:00–03:00, that time is used; otherwise 03:00 is the starting point. The longest interval between step records up to 21:00 is estimated as the sleep period. Survey-based time correction is applied. -- **Purpose of estimation**: Not precise time identification, but **trend analysis of bed/wake patterns and sleep anomaly detection**. +- **Purpose of estimation**: Not precise time identification, but **trend analysis of bed/wake patterns and sleep anomaly detection**. Precise times are not required as the purpose is trend analysis and anomaly detection. ## Data Spec @@ -50,6 +50,13 @@ Cover **all** of the following points. - Mid-sleep point difference of 1+ hour between weekdays and weekends = mild; 2+ hours = severe - Tendency toward phase advance or delay (morningness/eveningness) +### Sleep Pattern Judgment + +If either of the following applies, classify as "late-night tendency"; otherwise classify as "regular schedule". Use this judgment as the primary axis for advice. + +- Bed time at or after 03:00 on more than half of all days +- Standard deviation of bed time exceeds 1.5 hours (irregular rhythm) + ### Detailed Late-Night Pattern Evaluation - Late-night frequency (per week / per month) @@ -83,6 +90,10 @@ Respond strictly in the following Markdown format, written in **English**. Do no - Average bed time and average wake time - Percentage of days meeting recommended sleep duration (7–9 hours) +## 🧭 Sleep Pattern Judgment + +(State "late-night tendency" or "regular schedule" explicitly, and cite the numerical evidence for the judgment) + ## 🔬 Detailed Analysis ### 1. Sleep Duration and Rhythm Evaluation @@ -108,15 +119,15 @@ Respond strictly in the following Markdown format, written in **English**. Do no ### ⚠️ Areas for Improvement - (In priority order, with specific numbers) -## 💡 Improvement Advice +## 💡 Advice -(Provide individually optimized advice based on late-night frequency and Social Jetlag severity) +(Use the Sleep Pattern Judgment as the primary axis. For "late-night tendency": prioritize actionable steps to improve sleep rhythm. For "regular schedule": prioritize advice to maintain and strengthen the current rhythm.) ### 1. [Priority: High] (Advice Title) -**Background**: (Why this improvement is needed; cite relevant data and scientific evidence) +**Background**: (Why this improvement or maintenance is needed; cite relevant data and scientific evidence) **Concrete Steps**: - (Actionable steps in bullet points) -**Expected Outcome**: (Changes expected upon improvement) +**Expected Outcome**: (Changes expected upon improvement or continuation) ### 2. [Priority: Medium] (Advice Title) (Same structure as above) diff --git a/backend/datastore/prompts/specialized-prompt-ja.md b/backend/datastore/prompts/specialized-prompt-ja.md index ca9b669..46fdb0c 100644 --- a/backend/datastore/prompts/specialized-prompt-ja.md +++ b/backend/datastore/prompts/specialized-prompt-ja.md @@ -13,7 +13,7 @@ - **就寝・起床時刻の推定**: - 夜更かしなしの日:21:00→25:00(翌1:00)の歩数を遡り最初のレコードを就寝時刻、04:15→12:00の最初のレコードを起床時刻とする。 - 夜更かしの日:00:00〜03:00にレコードがあればその時刻、なければ03:00を精査開始とし、21:00までの歩数レコード間隔が最長の区間を睡眠時間として推定。アンケートによる時間補正あり。 -- **推定の目的**:正確な時刻特定ではなく、**就寝・起床の傾向把握と睡眠異常の検知**に重点。 +- **推定の目的**:正確な時刻特定ではなく、**就寝・起床の傾向把握と睡眠異常の検知**に重点。傾向把握・異常検知が目的なので精密な時刻でなくても問題ない。 ## データ仕様 @@ -50,6 +50,13 @@ - 平日と休日の睡眠中間点の差が1時間以上で軽度、2時間以上で重度と判定 - 睡眠位相の前進・後退傾向(朝型・夜型の判定) +### 睡眠パターン判定 + +以下のいずれかに該当する場合は「夜更かし傾向」、それ以外は「規則正しい」と判定する。この判定結果をアドバイスの方向性の主軸とすること。 + +- 就寝時刻が03:00以降の日が全体の半数を超える +- 就寝時刻の標準偏差が1.5時間を超える(リズムが不規則) + ### 夜更かしパターンの詳細評価 - 夜更かし頻度(週あたり・月あたり) @@ -83,6 +90,10 @@ - 平均就寝時刻・平均起床時刻 - 推奨睡眠時間(7〜9時間)を満たしている日の割合 +## 🧭 睡眠パターン判定 + +(「夜更かし傾向」または「規則正しい」を明示し、判定根拠となる数値を示す) + ## 🔬 詳細分析 ### 1. 睡眠時間・リズムの評価 @@ -108,15 +119,16 @@ ### ⚠️ 要改善点 - (優先度順に、具体的な数値を添えて箇条書き) -## 💡 改善アドバイス +## 💡 アドバイス -(夜更かしの頻度・Social Jetlagの程度を踏まえた個別最適なアドバイスを記述する) +(睡眠パターン判定の結果を主軸に、夜更かしの頻度・Social Jetlagの程度を踏まえた個別最適なアドバイスを記述する) +(「夜更かし傾向」の場合はリズム改善に向けた提案を、「規則正しい」場合は現在のリズムを維持・強化するための提案を優先する) ### 1. 【優先度:高】(アドバイスのタイトル) -**背景**:(なぜこの改善が必要か、根拠となるデータと科学的知見を示す) +**背景**:(なぜこの改善/維持が必要か、根拠となるデータと科学的知見を示す) **具体的な方法**: - (実践できる具体的なステップを箇条書き) -**期待される効果**:(改善した場合に期待される変化) +**期待される効果**:(改善または継続した場合に期待される変化) ### 2. 【優先度:中】(アドバイスのタイトル) (同上の構成で記述) From c2c7590ed36db635e4a36d17190869c0cc1427b5 Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 28 Apr 2026 10:22:10 +0000 Subject: [PATCH 11/32] =?UTF-8?q?refactor:=20=E3=82=A2=E3=83=97=E3=83=AA?= =?UTF-8?q?=E7=94=A8=E3=83=A2=E3=83=87=E3=83=AB=E3=81=AE=E3=83=97=E3=83=AC?= =?UTF-8?q?=E3=83=95=E3=82=A3=E3=83=83=E3=82=AF=E3=82=B9=E3=82=92=E7=92=B0?= =?UTF-8?q?=E5=A2=83=E5=A4=89=E6=95=B0=E3=81=AB=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 2 ++ ollama/setup.sh | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 495816f..3c97b54 100644 --- a/.env.example +++ b/.env.example @@ -6,4 +6,6 @@ FRONTEND_ENDPOINT=http://localhost:${FRONTEND_PORT} BACKEND_ENDPOINT=http://localhost:${BACKEND_PORT}/api/v1 OLLAMA_ENDPOINT=http://host.docker.internal:${OLLAMA_PORT}/v1 +MODEL_NAME_PREFIX=thor- + CLOUDFLARE_TUNNEL_TOKEN=changeme \ No newline at end of file diff --git a/ollama/setup.sh b/ollama/setup.sh index 32f4e2a..0505d35 100755 --- a/ollama/setup.sh +++ b/ollama/setup.sh @@ -2,6 +2,8 @@ set -euo pipefail +source .env + SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" echo "=== Ollama Model Setup ===" @@ -10,7 +12,7 @@ for modelfile in "$SCRIPT_DIR"/Modelfile.*; do [ -f "$modelfile" ] || continue # Modelfile.llama3 -> thor-llama3 - name="thor-$(basename "$modelfile" | sed 's/^Modelfile\.//')" + name="${MODEL_NAME_PREFIX}$(basename "$modelfile" | sed 's/^Modelfile\.//')" echo "Creating model: $name from $(basename "$modelfile")" ollama create "$name" -f "$modelfile" From 662fb15820c9bc6939092b61a71b77fb7163250e Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 28 Apr 2026 10:23:28 +0000 Subject: [PATCH 12/32] =?UTF-8?q?feat:=20=E3=83=95=E3=82=A3=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=83=90=E3=83=83=E3=82=AF=E3=81=AB=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=83=A2=E3=83=87=E3=83=AB=E3=81=A8=E3=83=91?= =?UTF-8?q?=E3=83=A9=E3=83=A1=E3=83=BC=E3=82=BF=E3=82=92=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 +++++++++++----- ollama/Modelfile.gemma3 | 19 ------------------- ollama/Modelfile.gemma3-12b | 10 ++++++++++ ollama/Modelfile.llama3 | 19 ------------------- ollama/Modelfile.llama3-3-70b | 10 ++++++++++ ollama/Modelfile.qwen3-14b | 31 +++++++++++++++++++++++++++++++ ollama/Modelfile.qwen3-5-122b | 33 +++++++++++++++++++++++++++++++++ 7 files changed, 95 insertions(+), 43 deletions(-) delete mode 100644 ollama/Modelfile.gemma3 create mode 100644 ollama/Modelfile.gemma3-12b delete mode 100644 ollama/Modelfile.llama3 create mode 100644 ollama/Modelfile.llama3-3-70b create mode 100644 ollama/Modelfile.qwen3-14b create mode 100644 ollama/Modelfile.qwen3-5-122b diff --git a/README.md b/README.md index f73694e..269440f 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ git clone git@github.com:273Do/Thor-Monorepo.git ### 3. LLM の用意 -以下のコマンドを実行して`ollama/` 内に用意された LLM を読み込みます。 +以下のコマンドを実行して`ollama/` 内に用意された LLM を読み込みます。かなり時間がかかります。 ```bash chmod +x ollama/setup.sh @@ -70,12 +70,18 @@ chmod +x ollama/setup.sh ``` NAME ID SIZE MODIFIED -gemma3:12b hogehogehoge o GB x seconds ago -thor-gemma3:latest fugafugafuga o GB x seconds ago -thor-llama3:latest piyopiyopiyo o GB x seconds ago -llama3.1:8b fofoofoofoof o GB x seconds ago +thor-qwen3-5-122b:latest aaaaaaaaaaaa 81 GB x hours ago +qwen3.5:122b bbbbbbbbbbbb 81 GB x hours ago +qwen3:14b cccccccccccc 9.3 GB x hours ago +thor-qwen3-14b:latest dddddddddddd 9.3 GB x hours ago +llama3.3:70b eeeeeeeeeeee 42 GB x hours ago +thor-llama3-3-70b:latest ffffffffffff 42 GB x hours ago +gemma3:12b gggggggggggg 8.1 GB x hours ago +thor-gemma3-12b:latest hhhhhhhhhhhh 8.1 GB x hours ago ``` +Modelfile の各パラメータ詳細は[公式ドキュメント](https://docs.ollama.com/modelfile#parameter)を参照。 + ### 4. 起動方法 VSCode で Dev Container でプロジェクトを開きます。 diff --git a/ollama/Modelfile.gemma3 b/ollama/Modelfile.gemma3 deleted file mode 100644 index 30e3cf6..0000000 --- a/ollama/Modelfile.gemma3 +++ /dev/null @@ -1,19 +0,0 @@ -# base model -FROM gemma3:12b - -# パラメータの設定 - -# 生成の多様性(0.0〜1.0)。フィードバック生成のため適度な柔軟性を持たせる -PARAMETER temperature 0.5 - -# コンテキストウィンドウサイズ。システムプロンプト + 睡眠データを十分に収める -PARAMETER num_ctx 8192 - -# 最大生成トークン数。マークダウン形式のレポートを完全に出力するため余裕を持たせる -PARAMETER num_predict 2048 - -# 繰り返しペナルティ。同じ表現の繰り返しを抑制する -PARAMETER repeat_penalty 1.1 - -# Top-p(核サンプリング)。temperatureと組み合わせて生成品質を安定させる -PARAMETER top_p 0.9 diff --git a/ollama/Modelfile.gemma3-12b b/ollama/Modelfile.gemma3-12b new file mode 100644 index 0000000..2812ab2 --- /dev/null +++ b/ollama/Modelfile.gemma3-12b @@ -0,0 +1,10 @@ +# 簡易的なフィードバックに使用するLLM + +FROM gemma3:12b + +PARAMETER temperature 0.6 +PARAMETER top_p 0.9 +PARAMETER top_k 50 +PARAMETER repeat_penalty 1.1 +PARAMETER num_ctx 8192 +PARAMETER num_predict 800 \ No newline at end of file diff --git a/ollama/Modelfile.llama3 b/ollama/Modelfile.llama3 deleted file mode 100644 index eb9f13f..0000000 --- a/ollama/Modelfile.llama3 +++ /dev/null @@ -1,19 +0,0 @@ -# base model -FROM llama3.1:8b - -# パラメータの設定 - -# 生成の多様性(0.0〜1.0)。フィードバック生成のため適度な柔軟性を持たせる -PARAMETER temperature 0.5 - -# コンテキストウィンドウサイズ。システムプロンプト + 睡眠データを十分に収める -PARAMETER num_ctx 8192 - -# 最大生成トークン数。マークダウン形式のレポートを完全に出力するため余裕を持たせる -PARAMETER num_predict 2048 - -# 繰り返しペナルティ。同じ表現の繰り返しを抑制する -PARAMETER repeat_penalty 1.1 - -# Top-p(核サンプリング)。temperatureと組み合わせて生成品質を安定させる -PARAMETER top_p 0.9 \ No newline at end of file diff --git a/ollama/Modelfile.llama3-3-70b b/ollama/Modelfile.llama3-3-70b new file mode 100644 index 0000000..27225f6 --- /dev/null +++ b/ollama/Modelfile.llama3-3-70b @@ -0,0 +1,10 @@ +# 専門的なフィードバックに使用するLLM + +FROM llama3.3:70b + +PARAMETER temperature 0.3 +PARAMETER top_p 0.85 +PARAMETER top_k 40 +PARAMETER repeat_penalty 1.15 +PARAMETER num_ctx 16384 +PARAMETER num_predict 3000 \ No newline at end of file diff --git a/ollama/Modelfile.qwen3-14b b/ollama/Modelfile.qwen3-14b new file mode 100644 index 0000000..658ff81 --- /dev/null +++ b/ollama/Modelfile.qwen3-14b @@ -0,0 +1,31 @@ +# 簡易的なフィードバックに使用するLLM + +FROM qwen3:14b + +# 出力の多様性(低=安定・一貫、高=創造的) +# 簡易フィードバックは多少の多様性があった方が自然な文体になる +PARAMETER temperature 0.6 + +# 累積確率のサンプリング範囲 +# 専門用より広めに取って流暢さを優先 +PARAMETER top_p 0.9 + +# 選択肢のトークン数制限 +# 14Bなので候補を少し広げても品質は安定する +PARAMETER top_k 50 + +# Qwen系に有効。低確率トークンをカットしてノイズを減らす +# 軽めに設定。速度優先 +PARAMETER min_p 0.03 + +# 同じ表現の繰り返し抑制 +# 短い出力なので繰り返しはそこまで問題にならない +PARAMETER repeat_penalty 1.1 + +# コンテキストウィンドウ長 +# 簡易用はプロンプトが短いのでこれで十分 +PARAMETER num_ctx 8192 + +# 最大出力トークン数 +# 簡潔なフィードバックに絞る +PARAMETER num_predict 800 \ No newline at end of file diff --git a/ollama/Modelfile.qwen3-5-122b b/ollama/Modelfile.qwen3-5-122b new file mode 100644 index 0000000..481bc60 --- /dev/null +++ b/ollama/Modelfile.qwen3-5-122b @@ -0,0 +1,33 @@ +# 専門的なフィードバックに使用するLLM + +FROM qwen3.5:122b + +# パラメータの詳細は公式はドキュメントを参照 +# https://docs.ollama.com/modelfile#parameter + +# 出力の多様性(低=安定・一貫、高=創造的) +# 専門的な分析は一貫性重視。高いと医学・統計用語がブレる +PARAMETER temperature 0.3 + +# 累積確率のサンプリング範囲 +# 上位85%のトークンから選択。専門語彙を外しにくくする +PARAMETER top_p 0.85 + +# 選択肢のトークン数制限 +# 候補を絞り、脱線を防ぐ +PARAMETER top_k 40 + +# Qwen系に有効。低確率トークンをカットしてノイズを減らす +PARAMETER min_p 0.05 + +# 同じ表現の繰り返し抑制 +# レポート形式では同じフレーズが繰り返されやすいので強めに設定 +PARAMETER repeat_penalty 1.15 + +# コンテキストウィンドウ長 +# 長文プロンプト+JSONデータに対応。122Bなら余裕で確保可能 +PARAMETER num_ctx 16384 + +# 最大出力トークン数 +# 専門レポート(6セクション)の出力に十分な長さ +PARAMETER num_predict 3000 \ No newline at end of file From d12903266a083389c3967d20aa2ea836670bb3ce Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 28 Apr 2026 10:45:50 +0000 Subject: [PATCH 13/32] =?UTF-8?q?fix:=20=E3=82=A2=E3=83=97=E3=83=AA?= =?UTF-8?q?=E5=B0=82=E7=94=A8=E3=83=A2=E3=83=87=E3=83=AB=E3=81=AE=E3=81=BF?= =?UTF-8?q?=E8=A8=98=E9=8C=B2=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ollama/setup.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ollama/setup.sh b/ollama/setup.sh index 0505d35..9fa9f91 100755 --- a/ollama/setup.sh +++ b/ollama/setup.sh @@ -25,6 +25,9 @@ echo "[" > "$OUTPUT_FILE" # [をファイルに出力 first=true ollama list | tail -n +2 | while read -r line; do model_name=$(echo "$line" | awk '{print $1}') + + [[ "$model_name" == "${MODEL_NAME_PREFIX}"* ]] || continue # プレフィックスがないモデルはスキップ + if [ "$first" = true ]; then first=false else From fe0becb297c0ed7f06f1fece682fa921ba3ee439 Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 28 Apr 2026 12:50:53 +0000 Subject: [PATCH 14/32] =?UTF-8?q?refactor:=20via-email=E3=81=AE=E3=82=B9?= =?UTF-8?q?=E3=82=AD=E3=83=BC=E3=83=9E=E3=81=AA=E3=81=A9=E3=82=92=E3=83=AA?= =?UTF-8?q?=E3=83=95=E3=82=A1=E3=82=AF=E3=82=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/routers/via_email.py | 9 ++------- backend/src/schemas/llm_feedback.py | 22 +++++++++++++++------- backend/src/schemas/via_email.py | 17 +++-------------- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/backend/src/routers/via_email.py b/backend/src/routers/via_email.py index b92fdca..a9663ce 100644 --- a/backend/src/routers/via_email.py +++ b/backend/src/routers/via_email.py @@ -3,7 +3,6 @@ from src.schemas.extract_steps import ExtractStepsQueryParams, validate_extract_params from src.schemas.via_email import ViaEmailRequest from src.usecases.estimate_sleep.run_estimate_sleep_usecase import run_estimate_sleep -from src.usecases.estimate_sleep.save_data_to_storage_usecase import get_llms from src.usecases.extract_steps.extract_steps_usecase import ( extract_steps_from_applehealthcare, ) @@ -68,17 +67,13 @@ async def via_email( via_email_req.answers, ) - models = get_llms() - - model = models[0] - estimate_sleep_json = [r.model_dump(mode="json") for r in estimated_data] clusters_json = [c.model_dump(mode="json") for c in clusters] feedback = get_feedback( estimate_sleep_json, # type: ignore clusters_json, # type: ignore - model, + via_email_req.llm, via_email_req.lang, via_email_req.is_specialized, ) @@ -88,5 +83,5 @@ async def via_email( await send_email( via_email_req.email_to, feedback, - model, + via_email_req.llm, ) diff --git a/backend/src/schemas/llm_feedback.py b/backend/src/schemas/llm_feedback.py index 2600fb9..f1eeb56 100644 --- a/backend/src/schemas/llm_feedback.py +++ b/backend/src/schemas/llm_feedback.py @@ -3,13 +3,8 @@ from pydantic import BaseModel, Field -class LLMFeedbackRequest(BaseModel): - id: str = Field( - description="データ識別用のID", - examples=["0123456789abcdef_20260101000000"], - min_length=1, - ) - """データ識別用のID""" +class LLMFeedbackParams(BaseModel): + """LLM による睡眠フィードバックを取得する基底スキーマ""" llm: str = Field(description="使用するLLM", examples=["thor-gemma3:latest"]) """使用するLLM""" @@ -25,7 +20,20 @@ class LLMFeedbackRequest(BaseModel): """専門的なフィードバックを返すかどうかのグラグ""" +class LLMFeedbackRequest(LLMFeedbackParams): + """LLM による睡眠フィードバックを取得するリクエストボディ""" + + id: str = Field( + description="データ識別用のID", + examples=["0123456789abcdef_20260101000000"], + min_length=1, + ) + """データ識別用のID""" + + class LLMFeedbackResponse(BaseModel): + """LLM による睡眠フィードバックを取得するレスポンススキーマ""" + data: str = Field( description="LLMからのフィードバック", examples=["LLMのフィードバック。マークダウン形式。"], diff --git a/backend/src/schemas/via_email.py b/backend/src/schemas/via_email.py index 749f5b5..84dca7f 100644 --- a/backend/src/schemas/via_email.py +++ b/backend/src/schemas/via_email.py @@ -1,11 +1,10 @@ -from typing import Literal - -from pydantic import BaseModel, EmailStr, Field +from pydantic import EmailStr, Field from src.schemas.estimate_sleep import Answers +from src.schemas.llm_feedback import LLMFeedbackParams -class ViaEmailRequest(BaseModel): +class ViaEmailRequest(LLMFeedbackParams): """Email経由で解析を実行するリクエストボディ""" answers: Answers = Field( @@ -20,16 +19,6 @@ class ViaEmailRequest(BaseModel): ) """睡眠状態を推定するためのアンケートの回答""" - lang: Literal["ja", "en"] = Field( - description="LLM のフィードバック言語", examples=["ja"] - ) - """LLM のフィードバック言語""" - - is_specialized: bool = Field( - description="専門的なフィードバックを返すかどうかのグラグ", examples=[True] - ) - """専門的なフィードバックを返すかどうかのグラグ""" - email_to: EmailStr = Field( description="結果を送信するメールアドレス", examples=["user@example.com"] ) From 5166e46102a517063723938d62fc2b6caf544d21 Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 28 Apr 2026 12:51:17 +0000 Subject: [PATCH 15/32] =?UTF-8?q?chore:=20env=E3=83=95=E3=82=A1=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E3=81=AE=E4=BE=8B=E3=81=AB=E3=81=A6=E4=B8=80=E9=83=A8?= =?UTF-8?q?=E9=96=93=E9=81=95=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F=E7=AE=87?= =?UTF-8?q?=E6=89=80=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/.env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/.env.example b/backend/.env.example index 928a8aa..0c4b81f 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -29,4 +29,4 @@ MAIL_USERNAME=${MAIL_ADDRESS} MAIL_PASSWORD=xxxxxxxxxxxxxxxx MAIL_FROM=${MAIL_ADDRESS} MAIL_PORT=587 -MAIL_SERVER=smtp.mail.com \ No newline at end of file +MAIL_SERVER=smtp.gmail.com \ No newline at end of file From 02efac145bd39125cccc64f3d93c2564e2d3b155 Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 28 Apr 2026 13:13:01 +0000 Subject: [PATCH 16/32] =?UTF-8?q?feat:=20=E3=83=A1=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=81=AE=E3=83=86=E3=83=B3=E3=83=97=E3=83=AC=E3=83=BC=E3=83=88?= =?UTF-8?q?=E3=81=AB=E8=8B=B1=E8=AA=9E=E7=89=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/templates/email-en.html | 75 +++++++++++++++++++ .../templates/{email.html => email-ja.html} | 0 2 files changed, 75 insertions(+) create mode 100644 backend/templates/email-en.html rename backend/templates/{email.html => email-ja.html} (100%) diff --git a/backend/templates/email-en.html b/backend/templates/email-en.html new file mode 100644 index 0000000..b02a2de --- /dev/null +++ b/backend/templates/email-en.html @@ -0,0 +1,75 @@ + + + + + + + + Sleep Estimation Feedback + + + +
+
+
+ + + +
+
+

Sleep Insight

+

+ Delivering sleep analysis results from your health data +

+
+
+ +
+
+
+ + + + + + + + +
+

AI Feedback

+
+
+
{{ feedback | safe }}
+
+

+ This feedback was generated by {{ llm }}. +

+
+
+ + +
+ + diff --git a/backend/templates/email.html b/backend/templates/email-ja.html similarity index 100% rename from backend/templates/email.html rename to backend/templates/email-ja.html From 5ba822261ec03f4018c845ae9c668d2ccad81a2f Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 28 Apr 2026 13:14:24 +0000 Subject: [PATCH 17/32] =?UTF-8?q?feat:=20=E3=83=A1=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=81=AE=E3=83=86=E3=83=B3=E3=83=97=E3=83=AC=E3=83=BC=E3=83=88?= =?UTF-8?q?=E3=81=8Ci18n=E3=81=AB=E5=AF=BE=E5=BF=9C=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/routers/via_email.py | 1 + .../usecases/via_email/send_email_usecase.py | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/backend/src/routers/via_email.py b/backend/src/routers/via_email.py index a9663ce..126d23b 100644 --- a/backend/src/routers/via_email.py +++ b/backend/src/routers/via_email.py @@ -84,4 +84,5 @@ async def via_email( via_email_req.email_to, feedback, via_email_req.llm, + via_email_req.lang, ) diff --git a/backend/src/usecases/via_email/send_email_usecase.py b/backend/src/usecases/via_email/send_email_usecase.py index 5b86a64..811f76a 100644 --- a/backend/src/usecases/via_email/send_email_usecase.py +++ b/backend/src/usecases/via_email/send_email_usecase.py @@ -1,4 +1,5 @@ from pathlib import Path +from typing import Literal import markdown from fastapi import HTTPException @@ -20,17 +21,27 @@ ) -async def send_email(email_to: str, feedback: str, llm: str) -> None: +async def send_email( + email_to: str, + feedback: str, + llm: str, + lang: Literal["ja", "en"], +) -> None: """フィードバックメール送信 Args: email_to (str): 送信先メールアドレス feedback (str): フィードバック llm (str): llm名 + lang (Literal[ja", "en"]): 言語 """ + + template_name: str = f"email-{lang}.html" + subject = "睡眠推定フィードバック" if lang == "ja" else "Sleep Estimation Feedback" + try: message = MessageSchema( - subject="睡眠推定フィードバック", + subject=subject, recipients=[email_to], # type: ignore template_body={ "feedback": markdown.markdown(feedback, extensions=["extra"]), @@ -39,6 +50,6 @@ async def send_email(email_to: str, feedback: str, llm: str) -> None: subtype=MessageType.html, ) fm = FastMail(conf) - await fm.send_message(message, template_name="email.html") + await fm.send_message(message, template_name) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) From a8009ca129e85c42b287d2f3e14bfa9830bc3efd Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 28 Apr 2026 13:58:55 +0000 Subject: [PATCH 18/32] =?UTF-8?q?refactor:=20=E3=83=86=E3=83=B3=E3=83=97?= =?UTF-8?q?=E3=83=AC=E3=83=BC=E3=83=88=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB?= =?UTF-8?q?=E5=90=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/usecases/via_email/send_email_usecase.py | 2 +- backend/templates/{email-en.html => email_en.html} | 0 backend/templates/{email-ja.html => email_ja.html} | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename backend/templates/{email-en.html => email_en.html} (100%) rename backend/templates/{email-ja.html => email_ja.html} (100%) diff --git a/backend/src/usecases/via_email/send_email_usecase.py b/backend/src/usecases/via_email/send_email_usecase.py index 811f76a..e71e872 100644 --- a/backend/src/usecases/via_email/send_email_usecase.py +++ b/backend/src/usecases/via_email/send_email_usecase.py @@ -36,7 +36,7 @@ async def send_email( lang (Literal[ja", "en"]): 言語 """ - template_name: str = f"email-{lang}.html" + template_name: str = f"email_{lang}.html" subject = "睡眠推定フィードバック" if lang == "ja" else "Sleep Estimation Feedback" try: diff --git a/backend/templates/email-en.html b/backend/templates/email_en.html similarity index 100% rename from backend/templates/email-en.html rename to backend/templates/email_en.html diff --git a/backend/templates/email-ja.html b/backend/templates/email_ja.html similarity index 100% rename from backend/templates/email-ja.html rename to backend/templates/email_ja.html From a55883711acd1e78982e91d5a6e6e42ef8bffc55 Mon Sep 17 00:00:00 2001 From: 273Do Date: Wed, 29 Apr 2026 05:18:17 +0000 Subject: [PATCH 19/32] =?UTF-8?q?feat:=20=E3=83=97=E3=83=AD=E3=83=B3?= =?UTF-8?q?=E3=83=97=E3=83=88=E3=81=AB=E6=96=87=E7=AB=A0=E3=82=92=E5=84=AA?= =?UTF-8?q?=E5=85=88=E3=81=99=E3=82=8B=E8=A8=98=E8=BF=B0=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/datastore/prompts/prompt-en.md | 2 +- backend/datastore/prompts/prompt-ja.md | 2 +- backend/datastore/prompts/specialized-prompt-en.md | 2 +- backend/datastore/prompts/specialized-prompt-ja.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/datastore/prompts/prompt-en.md b/backend/datastore/prompts/prompt-en.md index 18d7d36..4605edb 100644 --- a/backend/datastore/prompts/prompt-en.md +++ b/backend/datastore/prompts/prompt-en.md @@ -1,5 +1,5 @@ As a sleep and health expert for college students, analyze the sleep data in English. -Data is estimated from smartphone step counts. Precise times are not required as the purpose is trend analysis and anomaly detection. +Data is estimated from smartphone step counts. Precise times are not required as the purpose is trend analysis and anomaly detection. focus on conveying the information clearly in writing. **Data format**: "date": ["bed_time", "wake_time"] diff --git a/backend/datastore/prompts/prompt-ja.md b/backend/datastore/prompts/prompt-ja.md index 6c7ce10..9881049 100644 --- a/backend/datastore/prompts/prompt-ja.md +++ b/backend/datastore/prompts/prompt-ja.md @@ -1,5 +1,5 @@ 大学生の睡眠・健康専門家として睡眠データを日本語で分析せよ。 -データはスマートフォンの歩数から推定した概算値。傾向把握・異常検知が目的なので精密な時刻でなくても問題ない。 +データはスマートフォンの歩数から推定した概算値。傾向把握・異常検知が目的なので精密な時刻でなくても問題ない。文章で丁寧に伝えることを意識する。 **データ形式**: "日付": ["就寝時間", "起床時間"] diff --git a/backend/datastore/prompts/specialized-prompt-en.md b/backend/datastore/prompts/specialized-prompt-en.md index 7e4dec5..4d78c7d 100644 --- a/backend/datastore/prompts/specialized-prompt-en.md +++ b/backend/datastore/prompts/specialized-prompt-en.md @@ -13,7 +13,7 @@ The following explains how the data is estimated. Use this to correctly understa - **Bed/wake time estimation**: - Non-late-night days: Traces steps from 21:00 to 25:00 (next day 01:00); the first record is the bed time. The first record from 04:15 to 12:00 is the wake time. - Late-night days: If records exist between 00:00–03:00, that time is used; otherwise 03:00 is the starting point. The longest interval between step records up to 21:00 is estimated as the sleep period. Survey-based time correction is applied. -- **Purpose of estimation**: Not precise time identification, but **trend analysis of bed/wake patterns and sleep anomaly detection**. Precise times are not required as the purpose is trend analysis and anomaly detection. +- **Purpose of estimation**: Not precise time identification, but **trend analysis of bed/wake patterns and sleep anomaly detection**. Precise times are not required as the purpose is trend analysis and anomaly detection. Therefore, there is no need to include specific figures or tables; instead, focus on conveying the information clearly in writing. ## Data Spec diff --git a/backend/datastore/prompts/specialized-prompt-ja.md b/backend/datastore/prompts/specialized-prompt-ja.md index 46fdb0c..4d834d5 100644 --- a/backend/datastore/prompts/specialized-prompt-ja.md +++ b/backend/datastore/prompts/specialized-prompt-ja.md @@ -13,7 +13,7 @@ - **就寝・起床時刻の推定**: - 夜更かしなしの日:21:00→25:00(翌1:00)の歩数を遡り最初のレコードを就寝時刻、04:15→12:00の最初のレコードを起床時刻とする。 - 夜更かしの日:00:00〜03:00にレコードがあればその時刻、なければ03:00を精査開始とし、21:00までの歩数レコード間隔が最長の区間を睡眠時間として推定。アンケートによる時間補正あり。 -- **推定の目的**:正確な時刻特定ではなく、**就寝・起床の傾向把握と睡眠異常の検知**に重点。傾向把握・異常検知が目的なので精密な時刻でなくても問題ない。 +- **推定の目的**:正確な時刻特定ではなく、**就寝・起床の傾向把握と睡眠異常の検知**に重点。傾向把握・異常検知が目的なので精密な時刻でなくても問題ない。故に具体的な数字やテーブル表は表示しなくていいので、文章で丁寧に伝えることを意識する。 ## データ仕様 From c8664c70be6137c39568f7e81d6d87d4404339fc Mon Sep 17 00:00:00 2001 From: 273Do Date: Wed, 29 Apr 2026 06:40:13 +0000 Subject: [PATCH 20/32] =?UTF-8?q?feat:=20=E4=BD=BF=E7=94=A8=E3=81=99?= =?UTF-8?q?=E3=82=8Bllm=E3=82=92=E9=81=B8=E5=AE=9A=E3=81=97=E3=81=A6?= =?UTF-8?q?=E6=B1=BA=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ollama/Modelfile.gemma3-12b | 2 +- ...file.qwen3-5-122b => Modelfile.gemma3-27b} | 21 +++++-------- ollama/Modelfile.llama3-3-70b | 10 ------ ollama/Modelfile.mistral-small3-1-24b | 26 ++++++++++++++++ ollama/Modelfile.qwen3-14b | 31 ------------------- 5 files changed, 34 insertions(+), 56 deletions(-) rename ollama/{Modelfile.qwen3-5-122b => Modelfile.gemma3-27b} (51%) delete mode 100644 ollama/Modelfile.llama3-3-70b create mode 100644 ollama/Modelfile.mistral-small3-1-24b delete mode 100644 ollama/Modelfile.qwen3-14b diff --git a/ollama/Modelfile.gemma3-12b b/ollama/Modelfile.gemma3-12b index 2812ab2..04b3ecb 100644 --- a/ollama/Modelfile.gemma3-12b +++ b/ollama/Modelfile.gemma3-12b @@ -7,4 +7,4 @@ PARAMETER top_p 0.9 PARAMETER top_k 50 PARAMETER repeat_penalty 1.1 PARAMETER num_ctx 8192 -PARAMETER num_predict 800 \ No newline at end of file +PARAMETER num_predict 3000 \ No newline at end of file diff --git a/ollama/Modelfile.qwen3-5-122b b/ollama/Modelfile.gemma3-27b similarity index 51% rename from ollama/Modelfile.qwen3-5-122b rename to ollama/Modelfile.gemma3-27b index 481bc60..e093421 100644 --- a/ollama/Modelfile.qwen3-5-122b +++ b/ollama/Modelfile.gemma3-27b @@ -1,33 +1,26 @@ # 専門的なフィードバックに使用するLLM -FROM qwen3.5:122b - -# パラメータの詳細は公式はドキュメントを参照 -# https://docs.ollama.com/modelfile#parameter +FROM gemma3:27b # 出力の多様性(低=安定・一貫、高=創造的) # 専門的な分析は一貫性重視。高いと医学・統計用語がブレる -PARAMETER temperature 0.3 +PARAMETER temperature 0.8 # 累積確率のサンプリング範囲 -# 上位85%のトークンから選択。専門語彙を外しにくくする -PARAMETER top_p 0.85 +# 上位95%のトークンから選択。専門語彙を外しにくくする +PARAMETER top_p 0.95 # 選択肢のトークン数制限 # 候補を絞り、脱線を防ぐ -PARAMETER top_k 40 - -# Qwen系に有効。低確率トークンをカットしてノイズを減らす -PARAMETER min_p 0.05 +PARAMETER top_k 64 # 同じ表現の繰り返し抑制 # レポート形式では同じフレーズが繰り返されやすいので強めに設定 PARAMETER repeat_penalty 1.15 # コンテキストウィンドウ長 -# 長文プロンプト+JSONデータに対応。122Bなら余裕で確保可能 +# 長文プロンプト+JSONデータに対応。 PARAMETER num_ctx 16384 # 最大出力トークン数 -# 専門レポート(6セクション)の出力に十分な長さ -PARAMETER num_predict 3000 \ No newline at end of file +PARAMETER num_predict 5000 \ No newline at end of file diff --git a/ollama/Modelfile.llama3-3-70b b/ollama/Modelfile.llama3-3-70b deleted file mode 100644 index 27225f6..0000000 --- a/ollama/Modelfile.llama3-3-70b +++ /dev/null @@ -1,10 +0,0 @@ -# 専門的なフィードバックに使用するLLM - -FROM llama3.3:70b - -PARAMETER temperature 0.3 -PARAMETER top_p 0.85 -PARAMETER top_k 40 -PARAMETER repeat_penalty 1.15 -PARAMETER num_ctx 16384 -PARAMETER num_predict 3000 \ No newline at end of file diff --git a/ollama/Modelfile.mistral-small3-1-24b b/ollama/Modelfile.mistral-small3-1-24b new file mode 100644 index 0000000..0a146f9 --- /dev/null +++ b/ollama/Modelfile.mistral-small3-1-24b @@ -0,0 +1,26 @@ +# 簡易的なフィードバックに使用するLLM + +FROM mistral-small3.1:24b + +# 簡易フィードバック用:速度と日英品質のバランス重視 + +# 出力の多様性(低=安定・一貫、高=創造的) +# Mistralはtemperatureへの感度がやや高め。0.5で自然な文体を保ちつつ一貫性を確保。 +PARAMETER temperature 0.5 + +# 累積確率のサンプリング範囲 +# 上位90%からサンプリング。日英どちらも語彙の幅を保つ。 +PARAMETER top_p 0.9 + +# 選択肢のトークン数制限 +PARAMETER top_k 50 + +# 同じ表現の繰り返し抑制 +PARAMETER repeat_penalty 1.1 + +# コンテキストウィンドウ長 +# 簡易用はプロンプトが短いのでこれで十分 +PARAMETER num_ctx 8192 + +# 最大出力トークン数 +PARAMETER num_predict 3000 \ No newline at end of file diff --git a/ollama/Modelfile.qwen3-14b b/ollama/Modelfile.qwen3-14b deleted file mode 100644 index 658ff81..0000000 --- a/ollama/Modelfile.qwen3-14b +++ /dev/null @@ -1,31 +0,0 @@ -# 簡易的なフィードバックに使用するLLM - -FROM qwen3:14b - -# 出力の多様性(低=安定・一貫、高=創造的) -# 簡易フィードバックは多少の多様性があった方が自然な文体になる -PARAMETER temperature 0.6 - -# 累積確率のサンプリング範囲 -# 専門用より広めに取って流暢さを優先 -PARAMETER top_p 0.9 - -# 選択肢のトークン数制限 -# 14Bなので候補を少し広げても品質は安定する -PARAMETER top_k 50 - -# Qwen系に有効。低確率トークンをカットしてノイズを減らす -# 軽めに設定。速度優先 -PARAMETER min_p 0.03 - -# 同じ表現の繰り返し抑制 -# 短い出力なので繰り返しはそこまで問題にならない -PARAMETER repeat_penalty 1.1 - -# コンテキストウィンドウ長 -# 簡易用はプロンプトが短いのでこれで十分 -PARAMETER num_ctx 8192 - -# 最大出力トークン数 -# 簡潔なフィードバックに絞る -PARAMETER num_predict 800 \ No newline at end of file From 7c99147303e78bea70f42f79c564d7f3889971c9 Mon Sep 17 00:00:00 2001 From: 273Do Date: Wed, 29 Apr 2026 07:19:52 +0000 Subject: [PATCH 21/32] =?UTF-8?q?feat:=20readme=E3=81=AE=E3=83=A2=E3=83=87?= =?UTF-8?q?=E3=83=AB=E8=A8=98=E8=BF=B0=E3=82=92=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 269440f..ad7a00a 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Thor の AI 駆動のフルスタック -https://github.com/273Do/Thor +https://github.com/273Do/Thor https://github.com/273Do/Thor-Web-App-Frontend https://github.com/273Do/Thor-Web-App-Backend @@ -65,23 +65,23 @@ chmod +x ollama/setup.sh ./ollama/setup.sh ``` -うまく読み込めると以下のように表示されますが、自作モデル(thor-\*)はベースモデルの重みを共有して参照しているだけなので、ディスク容量が2倍になるわけではありません。Modelfile -で設定したパラメータの差分だけが追加で保持されています。 +うまく読み込めると以下のように表示されますが、自作モデル(thor-\*)はベースモデルの重みを共有して参照しているだけなので、ディスク容量が2倍になるわけではありません。Modelfile で設定したパラメータの差分だけが追加で保持されています。 ``` NAME ID SIZE MODIFIED -thor-qwen3-5-122b:latest aaaaaaaaaaaa 81 GB x hours ago -qwen3.5:122b bbbbbbbbbbbb 81 GB x hours ago -qwen3:14b cccccccccccc 9.3 GB x hours ago -thor-qwen3-14b:latest dddddddddddd 9.3 GB x hours ago -llama3.3:70b eeeeeeeeeeee 42 GB x hours ago -thor-llama3-3-70b:latest ffffffffffff 42 GB x hours ago -gemma3:12b gggggggggggg 8.1 GB x hours ago -thor-gemma3-12b:latest hhhhhhhhhhhh 8.1 GB x hours ago +gemma3:27b abcdefghijkl 17 GB X hours ago +thor-gemma3-27b:latest mnopqrstuvwx 17 GB X hours ago +thor-mistral-small3-1-24b:latest yz0123456789 15 GB X hours ago +mistral-small3.1:24b ABCDEFGHIJKL 15 GB X hours ago ``` Modelfile の各パラメータ詳細は[公式ドキュメント](https://docs.ollama.com/modelfile#parameter)を参照。 +フィードバックの種類によりによりモデルが異なります。 + +> 専門的なフィードバック:[gemma3:27b](https://ollama.com/library/gemma3:27b) +> 簡易的なフィードバック:[mistral-small3.1:24b](https://ollama.com/library/mistral-small3.1:24b) + ### 4. 起動方法 VSCode で Dev Container でプロジェクトを開きます。 From 930d92539698a789f444cfa5d15962d62a163ee0 Mon Sep 17 00:00:00 2001 From: 273Do Date: Wed, 29 Apr 2026 09:30:19 +0000 Subject: [PATCH 22/32] =?UTF-8?q?chore:=20readme=E3=82=92=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ad7a00a..3a3a451 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,20 @@ https://github.com/273Do/Thor-Web-App-Backend 本サービスは Apple ヘルスケアの XML エクスポートを利用するため、iPhone ユーザーを対象としています。Android など他のデバイスをお使いの方は、ヘルスデータを[指定の形式](https://github.com/273Do/Thor-Monorepo/blob/1923da19e313a79f8afa3c7c4b4036ce1542586a/backend/src/schemas/estimate_sleep.py#L29-L46)に変換したうえで API を直接呼び出すことでご利用いただけます。 +### LLM を用いたフィードバック + +独自のアルゴリズムによって推定された睡眠データを参考に、ローカル LLM を使用してフィードバックを行います。対応経路によって使用するモデルとプロンプトが異なります。 + +- ブラウザ表示では解析結果がグラフで視覚的に確認できるため、LLM フィードバックは補助的な位置づけです。応答速度がユーザー体験に直結するため、軽量モデルを使用し、プロンプトも睡眠傾向の要約と手軽なアドバイスに絞っています。 + +- メール送信では応答速度より質を優先できます。グラフを伴わないテキストのみの出力になります。睡眠パター + ンの詳細な分析・専門的見解・生活習慣への影響・具体的な改善アドバイスを含む包括的なフィードバックを返すプロンプトを使用しています。 + +| 種別 | モデル | レスポンス内容 | レスポンス速度 | 対応経路 | +| ---------------------- | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | -------------- | -------------------- | +| 専門的なフィードバック | [gemma3:27b](https://ollama.com/library/gemma3:27b) | 解析結果をもとにした睡眠パターンの詳細な分析・専門的見解・生活への影響・具体的な改善アドバイス | 1分程度 | メール経由のみ | +| 簡易的なフィードバック | [mistral-small3.1:24b](https://ollama.com/library/mistral-small3.1:24b) | 睡眠傾向のサマリーと、すぐに実践できる簡単なアドバイス | 10秒程度 | ブラウザ・メール経由 | + ## プロジェクト構成 - **Frontend**: React + TypeScript + Tailwind CSS @@ -77,11 +91,6 @@ mistral-small3.1:24b ABCDEFGHIJKL 15 GB X hours ago Modelfile の各パラメータ詳細は[公式ドキュメント](https://docs.ollama.com/modelfile#parameter)を参照。 -フィードバックの種類によりによりモデルが異なります。 - -> 専門的なフィードバック:[gemma3:27b](https://ollama.com/library/gemma3:27b) -> 簡易的なフィードバック:[mistral-small3.1:24b](https://ollama.com/library/mistral-small3.1:24b) - ### 4. 起動方法 VSCode で Dev Container でプロジェクトを開きます。 From 2282c5426154ad774e05cb8d98e86b7b952b15cf Mon Sep 17 00:00:00 2001 From: 273Do Date: Wed, 29 Apr 2026 14:51:54 +0000 Subject: [PATCH 23/32] =?UTF-8?q?fix:=20=E5=B0=82=E9=96=80=E7=9A=84?= =?UTF-8?q?=E3=81=AA=E3=83=97=E3=83=AD=E3=83=B3=E3=83=97=E3=83=88=E3=81=AE?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E3=81=A8=E8=BB=B8=E3=82=92=E7=9D=A1=E7=9C=A0?= =?UTF-8?q?=E7=95=B0=E5=B8=B8=E3=82=92=E4=B8=BB=E3=81=A8=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../prompts/specialized-prompt-en.md | 51 +++++++++++------ .../prompts/specialized-prompt-ja.md | 55 ++++++++++++------- 2 files changed, 68 insertions(+), 38 deletions(-) diff --git a/backend/datastore/prompts/specialized-prompt-en.md b/backend/datastore/prompts/specialized-prompt-en.md index 4d78c7d..fad9f3f 100644 --- a/backend/datastore/prompts/specialized-prompt-en.md +++ b/backend/datastore/prompts/specialized-prompt-en.md @@ -52,28 +52,42 @@ Cover **all** of the following points. ### Sleep Pattern Judgment -If either of the following applies, classify as "late-night tendency"; otherwise classify as "regular schedule". Use this judgment as the primary axis for advice. +Evaluate on a three-level scale — "Good," "Caution," or "Needs Improvement" — using the criteria below. Use this judgment as the primary axis for advice. -- Bed time at or after 03:00 on more than half of all days -- Standard deviation of bed time exceeds 1.5 hours (irregular rhythm) +- Abnormal sleep days account for 1/5 or more of all days: "Caution"; 1/3 or more: "Needs Improvement" +- Fewer than 50% of days meet recommended sleep duration (7–9 hours): "Caution" +- Standard deviation of bed/wake times exceeds 1.5 hours (unstable rhythm): "Caution" +- Two or more criteria apply, or abnormal days occur consecutively: "Needs Improvement" -### Detailed Late-Night Pattern Evaluation +### Abnormal Sleep Day Detection -- Late-night frequency (per week / per month) -- Consecutive late-night days and their effect on subsequent sleep -- Changes in sleep duration and wake time the day after late nights +A day is classified as an abnormal sleep day if it meets any of the following conditions: + +- Bed time is 2 or more hours later than usual (median) +- Sleep duration is 2 or more hours shorter than usual (median) +- Sleep duration is under 5 hours (extremely short sleep) +- Sleep duration exceeds 10 hours (hypersomnia) + +For each detected abnormal day, evaluate the following: + +- Frequency (per week / per month) and proportion of total days +- Consecutive occurrences (multiple consecutive abnormal days are considered especially serious) +- Impact on surrounding sleep (changes in sleep duration and wake time the following day) +- Concentration on specific days of the week or time periods ### Sleep Anomaly and Risk Pattern Detection -- Frequency of extremely short sleep (<5 hours) and long sleep (>10 hours) - Sudden fluctuations in sleep duration (≥50% change compared to adjacent days) +- Clustering of abnormal days (concentration in a specific period may suggest external stressors) - Suggestion of potential sleep disorder risks (insomnia, hypersomnia, circadian rhythm sleep disorder) +- Severity assessment: determine whether the pattern warrants a recommendation to seek professional care ### Mental Health Impact Assessment -- Effects of sleep deprivation and irregular rhythms on cognitive function and emotional regulation -- Relationship between college-specific stressors (academics, social relationships, living environment) and sleep +- Effects of abnormal sleep day frequency and consecutive occurrences on cognitive function and emotional regulation +- Relationship between college-specific stressors (academics, social relationships, living environment, exam periods) and abnormal days - Association with burnout risk and depressive tendencies +- Criteria for cases where professional support is beneficial (sleep clinic, campus health center, student counseling service) ## Output Format @@ -92,7 +106,7 @@ Respond strictly in the following Markdown format, written in **English**. Do no ## 🧭 Sleep Pattern Judgment -(State "late-night tendency" or "regular schedule" explicitly, and cite the numerical evidence for the judgment) +(State "Good," "Caution," or "Needs Improvement" explicitly, and cite the numerical evidence for the judgment) ## 🔬 Detailed Analysis @@ -102,14 +116,14 @@ Respond strictly in the following Markdown format, written in **English**. Do no ### 2. Circadian Rhythm and Social Jetlag (Evaluate presence/severity of Social Jetlag, weekday/weekend differences, and morningness/eveningness tendency) -### 3. Late-Night Patterns -(Evaluate frequency, consecutive occurrences, and impact on subsequent sleep) +### 3. Abnormal Sleep Day Analysis +(List detected abnormal days; evaluate frequency, consecutive occurrences, and impact on surrounding sleep. Emphasize cases where abnormal days are consecutive or concentrated in a specific period.) ### 4. Sleep Anomalies and Risk Patterns -(Point out outliers, sudden changes, and potential sleep disorder risks) +(Based on the pattern of abnormal days, point out potential sleep disorder risks and possible external stressors) ### 5. Mental Health Impact -(Describe potential effects of the sleep pattern on physical and mental health based on expert knowledge) +(Describe potential effects of the abnormal sleep pattern on physical and mental health based on expert knowledge. In serious cases, actively encourage consultation with a professional.) ## 📋 Overall Assessment @@ -121,7 +135,7 @@ Respond strictly in the following Markdown format, written in **English**. Do no ## 💡 Advice -(Use the Sleep Pattern Judgment as the primary axis. For "late-night tendency": prioritize actionable steps to improve sleep rhythm. For "regular schedule": prioritize advice to maintain and strengthen the current rhythm.) +(Use the Sleep Pattern Judgment as the primary axis, taking into account the frequency and consecutive nature of abnormal days and the degree of Social Jetlag. For "Needs Improvement": actively encourage a visit to a sleep clinic or campus health center. For "Caution": suggest lifestyle improvements alongside professional consultation if needed.) ### 1. [Priority: High] (Advice Title) **Background**: (Why this improvement or maintenance is needed; cite relevant data and scientific evidence) @@ -143,7 +157,8 @@ Respond strictly in the following Markdown format, written in **English**. Do no (Must include:) - This analysis is estimated from wearable step count data and does not constitute medical diagnosis - Analysis accuracy may be reduced due to missing data -- If serious patterns are observed, recommend consulting a medical professional or student counseling service +- If abnormal sleep days occur frequently or consecutively, or if persistent excessive sleepiness or low mood is present, strongly recommend consulting a **sleep clinic or the campus health center / student counseling service** +- Sleep issues are closely linked to mental health; actively convey that the reader should not struggle alone and should seek professional support ``` ## Notes on Analysis @@ -153,5 +168,5 @@ Respond strictly in the following Markdown format, written in **English**. Do no - **Avoid definitive statements**: Analyze within the scope of what the data shows; limit conclusions to estimations and suggestions. - **College student context**: Provide practical advice that accounts for academics, part-time jobs, club activities, exam periods, etc. - **Explain technical terms**: Add a brief explanation at first use for terms such as Social Jetlag, sleep debt, and circadian rhythm. -- **Serious cases**: If sleep under 5 hours occurs more than half the days in a week, or if Social Jetlag exceeding 2 hours continues, strongly encourage consultation with a medical professional. +- **Serious cases**: If abnormal sleep days account for more than half the days in a week or occur consecutively for 3 or more days, or if a pattern of hypersomnia or strong fatigue is observed, strongly encourage a visit to a sleep clinic or campus health center. If mental health impact is suggested, also recommend the student counseling service. - **Level of detail**: Do not abbreviate or summarize any section. Write with sufficient evidence and specificity. Prioritize comprehensiveness over brevity. diff --git a/backend/datastore/prompts/specialized-prompt-ja.md b/backend/datastore/prompts/specialized-prompt-ja.md index 4d834d5..f919ad5 100644 --- a/backend/datastore/prompts/specialized-prompt-ja.md +++ b/backend/datastore/prompts/specialized-prompt-ja.md @@ -52,28 +52,42 @@ ### 睡眠パターン判定 -以下のいずれかに該当する場合は「夜更かし傾向」、それ以外は「規則正しい」と判定する。この判定結果をアドバイスの方向性の主軸とすること。 +以下の基準により「良好」「要注意」「要改善」の3段階で評価する。この判定結果をアドバイスの方向性の主軸とすること。 -- 就寝時刻が03:00以降の日が全体の半数を超える -- 就寝時刻の標準偏差が1.5時間を超える(リズムが不規則) +- 異常な睡眠日の頻度が全体の1/5以上:「要注意」、1/3以上:「要改善」 +- 推奨睡眠時間(7〜9時間)を満たしている日が50%未満:「要注意」 +- 就寝・起床時刻の標準偏差が1.5時間超(リズム不安定):「要注意」 +- 上記が複数該当、または異常日が連続している:「要改善」 -### 夜更かしパターンの詳細評価 +### 異常な睡眠である日の検出 -- 夜更かし頻度(週あたり・月あたり) -- 連続夜更かし日数とその後の睡眠への影響 -- 夜更かし翌日の睡眠時間・起床時刻の変化 +その日の睡眠が以下のいずれかの条件を満たしている場合、異常な睡眠である日だと判定する。 + +- 就寝時刻が普段(中央値)より2時間以上遅い +- 睡眠時間が普段(中央値)より2時間以上短い +- 睡眠時間が5時間未満(極端な短時間睡眠) +- 睡眠時間が10時間超(過眠) + +検出した異常日については、以下を評価する: + +- 発生頻度(週あたり・月あたり)と全体に占める割合 +- 連続性(複数日にわたる連続した異常は特に深刻と見なす) +- 前後の睡眠パターンへの影響(翌日の睡眠時間・起床時刻の変化) +- 特定の曜日・時期への集中の有無 ### 睡眠異常・リスクパターンの検出 -- 極端な短時間睡眠(5時間未満)・長時間睡眠(10時間超)の頻度 - 睡眠時間の急激な変動(前後比で50%以上の変化) +- 異常日の連続・集中(特定期間に集中している場合は外的ストレス要因を示唆) - 潜在的な睡眠障害リスク(不眠傾向、過眠傾向、概日リズム睡眠障害)の示唆 +- パターンの重大度評価:受診勧奨が必要なレベルかどうかを判定する ### メンタルヘルスへの影響評価 -- 睡眠不足・不規則リズムが認知機能・情動調節に与える影響 -- 大学生特有のストレス要因(学業・対人関係・生活環境)と睡眠の関連 +- 異常な睡眠日の頻度・連続性と、認知機能・情動調節への影響 +- 大学生特有のストレス要因(学業・対人関係・生活環境・試験期間)と異常日の関連 - バーンアウトリスクや抑うつ傾向との関連性 +- 専門的サポートが有効なケース(睡眠科・保健管理センター・学生相談室)の判断基準 ## 出力フォーマット @@ -92,7 +106,7 @@ ## 🧭 睡眠パターン判定 -(「夜更かし傾向」または「規則正しい」を明示し、判定根拠となる数値を示す) +(「良好」「要注意」「要改善」のいずれかを明示し、判定根拠となる数値を示す) ## 🔬 詳細分析 @@ -102,27 +116,27 @@ ### 2. 概日リズムと社会的時差ぼけ (Social Jetlagの有無・程度、平日/休日差異、朝型/夜型傾向を評価する) -### 3. 夜更かしパターン -(夜更かしの頻度・連続性・翌日の睡眠への影響を評価する) +### 3. 異常な睡眠日の分析 +(検出した異常日を列挙し、頻度・連続性・前後への影響を評価する。特に連続している場合や特定期間への集中が見られる場合は強調する) ### 4. 睡眠異常・リスクパターン -(異常値・急変動・潜在的な睡眠障害リスクを指摘する) +(異常日のパターンから示唆される潜在的な睡眠障害リスク・外的ストレス要因を指摘する) ### 5. メンタルヘルスへの影響 -(睡眠パターンが心身に与えうる影響を専門的知見に基づき記述する) +(異常な睡眠パターンが心身に与えうる影響を専門的知見に基づき記述する。深刻な場合は専門機関への相談を促す) ## 📋 総合評価 ### ✅ 良好な点 -- (具体的な数値を添えて箇条書き) +- (睡眠の観点から箇条書き) ### ⚠️ 要改善点 - (優先度順に、具体的な数値を添えて箇条書き) ## 💡 アドバイス -(睡眠パターン判定の結果を主軸に、夜更かしの頻度・Social Jetlagの程度を踏まえた個別最適なアドバイスを記述する) -(「夜更かし傾向」の場合はリズム改善に向けた提案を、「規則正しい」場合は現在のリズムを維持・強化するための提案を優先する) +(睡眠パターン判定の結果を主軸に、異常な睡眠日の頻度・連続性・Social Jetlagの程度を踏まえた個別最適なアドバイスを記述する) +(「要改善」の場合は睡眠科・保健管理センターへの受診を積極的に促す。「要注意」の場合は生活習慣の改善とあわせて必要に応じた相談を提案する) ### 1. 【優先度:高】(アドバイスのタイトル) **背景**:(なぜこの改善/維持が必要か、根拠となるデータと科学的知見を示す) @@ -144,7 +158,8 @@ (以下を含める) - 本分析はウェアラブルデバイスの歩数データからの推定であり、医学的診断ではないこと - データ欠損により分析精度が低下する可能性があること -- 深刻なパターンが見られる場合の医療専門家・学生相談窓口への相談推奨 +- 異常な睡眠日が頻繁・連続して見られる場合や、強い眠気・気分の落ち込みが続く場合は、**睡眠科または大学の保健管理センター・学生相談室**への相談を強く推奨すること +- 睡眠の問題はメンタルヘルスと密接に関連するため、一人で抱え込まずに専門家に相談することを積極的に伝えること ``` ## 分析上の注意点 @@ -154,5 +169,5 @@ - **断定を避ける**:データから読み取れる範囲で分析し、推定・可能性の示唆に留める - **大学生の文脈に即す**:学業・アルバイト・サークル活動・試験期間等を考慮した実践的なアドバイスを行う - **専門用語には補足を付ける**:Social Jetlag・睡眠負債・概日リズム等の用語は初出時に簡潔な説明を加える -- **深刻なケースへの対応**:5時間未満の睡眠が週の半数以上・2時間超のSocial Jetlagが継続する場合は、医療専門家への相談を強く促す +- **深刻なケースへの対応**:異常な睡眠日が週の半数以上・連続して3日以上継続する場合、または過眠・強い倦怠感のパターンが見られる場合は、保健管理センターへの受診を強く促す。メンタルヘルスへの影響が示唆される場合は学生相談室も併せて案内する - **回答の詳細度**:各セクションを省略・要約せず、十分な根拠と具体性を持って記述する。簡潔さより網羅性を優先すること From 2a7d7fa62eeb1cf7e4e77bf8ba759c73ec493d85 Mon Sep 17 00:00:00 2001 From: 273Do Date: Wed, 29 Apr 2026 14:57:19 +0000 Subject: [PATCH 24/32] =?UTF-8?q?fix:=20=E7=B0=A1=E6=98=93=E7=9A=84?= =?UTF-8?q?=E3=81=AA=E3=83=97=E3=83=AD=E3=83=B3=E3=83=97=E3=83=88=E3=81=AE?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E3=81=A8=E8=BB=B8=E3=82=92=E7=9D=A1=E7=9C=A0?= =?UTF-8?q?=E7=95=B0=E5=B8=B8=E3=82=92=E4=B8=BB=E3=81=A8=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/datastore/prompts/prompt-en.md | 12 ++++++------ backend/datastore/prompts/prompt-ja.md | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/backend/datastore/prompts/prompt-en.md b/backend/datastore/prompts/prompt-en.md index 4605edb..2c2c51f 100644 --- a/backend/datastore/prompts/prompt-en.md +++ b/backend/datastore/prompts/prompt-en.md @@ -1,9 +1,9 @@ -As a sleep and health expert for college students, analyze the sleep data in English. -Data is estimated from smartphone step counts. Precise times are not required as the purpose is trend analysis and anomaly detection. focus on conveying the information clearly in writing. +As a college student sleep expert, analyze the step-estimated sleep data in English. Goal: trend analysis and anomaly detection. Prioritize clear writing over specific figures. **Data format**: "date": ["bed_time", "wake_time"] -**Judgment**: bed_time at or after 03:00 on more than half the days, or standard deviation of bed_time > 1.5h → late-night tendency, otherwise → regular schedule +**Abnormal day**: bed_time ≥ median+2h late / sleep duration ≤ median-2h / under 5h / over 10h +**Judgment**: abnormal days ≥1/3→Needs Improvement / ≥1/5→Caution / else→Good Output in Markdown using the following format. @@ -11,14 +11,14 @@ Output in Markdown using the following format. ## 🧭 Sleep Pattern Judgment -(judgment result and rationale in 1 sentence) +(judgment and rationale in 1 sentence) ## 🔍 Analysis -(bullet points for strengths / areas to improve) +(bullet points for strengths/areas to improve; mention frequency and consecutive occurrences of abnormal days) ## 💡 Advice -(3 items tailored to the judgment result) +(3 items tailored to judgment; if Needs Improvement, include recommendation for sleep clinic or campus health center) ## ⚠️ Notes diff --git a/backend/datastore/prompts/prompt-ja.md b/backend/datastore/prompts/prompt-ja.md index 9881049..80f51a7 100644 --- a/backend/datastore/prompts/prompt-ja.md +++ b/backend/datastore/prompts/prompt-ja.md @@ -1,9 +1,9 @@ -大学生の睡眠・健康専門家として睡眠データを日本語で分析せよ。 -データはスマートフォンの歩数から推定した概算値。傾向把握・異常検知が目的なので精密な時刻でなくても問題ない。文章で丁寧に伝えることを意識する。 +大学生の睡眠専門家として歩数推定の睡眠データを日本語で分析せよ。傾向把握・異常検知が目的。具体的な数値より文章での説明を優先する。 **データ形式**: "日付": ["就寝時間", "起床時間"] -**判定**: 就寝03:00以降が半数超 or 就寝時刻の標準偏差1.5h超 → 夜更かし傾向、それ以外 → 規則正しい +**異常日**: 就寝が中央値+2h以上遅い / 睡眠時間が中央値-2h以上短い / 5h未満 / 10h超 +**判定**: 異常日が1/3以上→要改善 / 1/5以上→要注意 / それ以外→良好 Markdownで以下の形式で出力せよ。 @@ -11,14 +11,14 @@ Markdownで以下の形式で出力せよ。 ## 🧭 睡眠パターン判定 -(判定結果と根拠を1文) +(判定と根拠を1文) ## 🔍 分析結果 -(良い点/改善点を箇条書き) +(良い点・改善点を箇条書き。異常日の頻度・連続性に触れる) ## 💡 アドバイス -(判定結果に沿った3項目) +(判定に沿った3項目。要改善の場合は睡眠科・保健管理センターへの相談を含める) ## ⚠️ 注意事項 From 0cf95fb52349702523e1fe214235b2cb0757b9bd Mon Sep 17 00:00:00 2001 From: 273Do Date: Wed, 29 Apr 2026 15:59:38 +0000 Subject: [PATCH 25/32] =?UTF-8?q?fix:=20readme=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 3a3a451..01f33c0 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,11 @@ Thor の AI 駆動のフルスタック -https://github.com/273Do/Thor -https://github.com/273Do/Thor-Web-App-Frontend -https://github.com/273Do/Thor-Web-App-Backend +https://github.com/273Do/Thor ## アプリ概要 -本 web アプリは、iPhone のヘルスケアデータから睡眠パターンを推定・分析するWebサービスです。 +本 web アプリは、iPhone のヘルスケアデータから睡眠パターンを推定・分析し、LLM からフィードバックを取得するWebサービスです。 ### フロー @@ -38,10 +36,10 @@ https://github.com/273Do/Thor-Web-App-Backend - メール送信では応答速度より質を優先できます。グラフを伴わないテキストのみの出力になります。睡眠パター ンの詳細な分析・専門的見解・生活習慣への影響・具体的な改善アドバイスを含む包括的なフィードバックを返すプロンプトを使用しています。 -| 種別 | モデル | レスポンス内容 | レスポンス速度 | 対応経路 | -| ---------------------- | ----------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | -------------- | -------------------- | -| 専門的なフィードバック | [gemma3:27b](https://ollama.com/library/gemma3:27b) | 解析結果をもとにした睡眠パターンの詳細な分析・専門的見解・生活への影響・具体的な改善アドバイス | 1分程度 | メール経由のみ | -| 簡易的なフィードバック | [mistral-small3.1:24b](https://ollama.com/library/mistral-small3.1:24b) | 睡眠傾向のサマリーと、すぐに実践できる簡単なアドバイス | 10秒程度 | ブラウザ・メール経由 | +| 種別 | モデル | レスポンス内容 | レスポンス速度 | 対応経路 | +| ---------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------------ | -------------- | -------------------- | +| 専門的なフィードバック | [gemma3:27b](https://ollama.com/library/gemma3:27b) | 解析結果をもとにした睡眠異常・専門的見解・生活への影響・具体的な改善アドバイス | 1分程度 | メール経由のみ | +| 簡易的なフィードバック | [mistral-small3.1:24b](https://ollama.com/library/mistral-small3.1:24b) | 睡眠傾向のサマリーと、すぐに実践できる簡単なアドバイス | 10秒程度 | ブラウザ・メール経由 | ## プロジェクト構成 @@ -137,7 +135,7 @@ claude ## 公開設定 -- cloudflare tunnel を使用してアプリを公開します。 +- cloudflare tunnel を使用してアプリを公開します。(未対応) 1. [Cloudflareダッシュボード](https://dash.cloudflare.com)から [Zero Trust] > [Networks] > [Overview] > [Manage Tunnels] > [Create new cloudflared Tunnel] を選択します。 From ed400e5cff35e31864c6d230adcfaace14057b7d Mon Sep 17 00:00:00 2001 From: 273Do Date: Wed, 29 Apr 2026 16:00:09 +0000 Subject: [PATCH 26/32] =?UTF-8?q?feat:=20=E3=83=97=E3=83=AD=E3=83=B3?= =?UTF-8?q?=E3=83=97=E3=83=88=E3=81=AB=E5=89=8D=E6=8F=90=E6=9D=A1=E4=BB=B6?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/datastore/prompts/specialized-prompt-en.md | 3 ++- backend/datastore/prompts/specialized-prompt-ja.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/datastore/prompts/specialized-prompt-en.md b/backend/datastore/prompts/specialized-prompt-en.md index fad9f3f..f192c9f 100644 --- a/backend/datastore/prompts/specialized-prompt-en.md +++ b/backend/datastore/prompts/specialized-prompt-en.md @@ -3,12 +3,13 @@ You have knowledge in behavioral science and public health, and can provide evid ## Your Role -Analyze the **daily bed/wake time data** estimated from step count data, and provide **specialized and specific** feedback and advice on college students' health, lifestyle, and sleep habits. +The COVID-19 pandemic has drastically changed the learning environment, making it increasingly important to support college students in maintaining academic motivation and protecting their mental health. Analyze the **daily bed/wake time data** estimated from step count data, and provide **specialized and specific** feedback and advice on college students' health, lifestyle, and sleep habits. Note that college students tend to exhibit behavioral patterns that differ significantly from the general population. ## Background on the Estimation Method The following explains how the data is estimated. Use this to correctly understand the accuracy and limitations of the analysis. +- **Data used for the following estimates**: Step count data recorded by smartphones. - **Late-night detection**: Estimated using a machine learning model with features including hourly step totals, record counts, and a survey item on usual bedtime (before 3:00 AM = 0, at or after 3:00 AM = 1). - **Bed/wake time estimation**: - Non-late-night days: Traces steps from 21:00 to 25:00 (next day 01:00); the first record is the bed time. The first record from 04:15 to 12:00 is the wake time. diff --git a/backend/datastore/prompts/specialized-prompt-ja.md b/backend/datastore/prompts/specialized-prompt-ja.md index f919ad5..436382d 100644 --- a/backend/datastore/prompts/specialized-prompt-ja.md +++ b/backend/datastore/prompts/specialized-prompt-ja.md @@ -3,12 +3,13 @@ ## あなたの役割 -ユーザーから渡される歩数データから推定された**日毎の就寝・起床時刻データ**を解析し、大学生の健康状態・生活習慣・睡眠習慣について**専門的かつ具体的な**フィードバックとアドバイスを提供してください。 +コロナ禍で学びの環境が大きく変化し、大学生の学業への意欲の維持・向上・メンタルが低下している学生の心の健康支援が重要な課題になっています。ユーザーから渡される歩数データから推定された**日毎の就寝・起床時刻データ**を解析し、大学生の健康状態・生活習慣・睡眠習慣について**専門的かつ具体的な**フィードバックとアドバイスを提供してください。大学生がターゲットであるため、一般的な生活行動パターンとは異なる傾向にあることに注意してください。 ## 解析手法の背景知識 以下は本データの推定処理に関する説明です。分析の精度・限界を正しく把握するために参照してください。 +- **以下の推定に使用するデータ**:スマートフォンで記録される歩数データ。 - **夜更かし推定**:1時間毎の歩数合計・レコード数・アンケートによる普段の就寝時刻(3時前=0、3時以降=1)を特徴量とした機械学習モデルで推定。 - **就寝・起床時刻の推定**: - 夜更かしなしの日:21:00→25:00(翌1:00)の歩数を遡り最初のレコードを就寝時刻、04:15→12:00の最初のレコードを起床時刻とする。 From 89653f426d15dbd462b61b4f5f5bc1e11b281366 Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 5 May 2026 06:57:54 +0000 Subject: [PATCH 27/32] =?UTF-8?q?feat:=20llm=E3=83=95=E3=82=A3=E3=83=BC?= =?UTF-8?q?=E3=83=89=E3=83=90=E3=83=83=E3=82=AF=E3=81=AB=E3=81=A6fb?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=97=E3=82=92=E8=A8=AD=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/app/components/ai-feedback.tsx | 30 ++++++++++++------------- frontend/app/utils/types.ts | 1 + 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/frontend/app/components/ai-feedback.tsx b/frontend/app/components/ai-feedback.tsx index 7c56532..5bd4cbb 100644 --- a/frontend/app/components/ai-feedback.tsx +++ b/frontend/app/components/ai-feedback.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from "react"; +import { useEffect, useRef } from "react"; import { useTranslation } from "react-i18next"; import ReactMarkdown from "react-markdown"; @@ -36,12 +36,16 @@ export const AIFeedback = ({ id, models }: props) => { const { t, i18n } = useTranslation(); const { feedbackTrigger, isFeedbackMutating, feedbackData } = useAIFeedback(); - const [model, setModel] = useState(models[0]); + const initialModel = models[1]; + const selectLLMRef = useRef(initialModel); - const selectLLMRef = useRef(models[0]); - - const handleReGenFB = () => { - setModel(selectLLMRef.current); + const triggerFeedback = () => { + feedbackTrigger({ + id, + llm: selectLLMRef.current, + lang: i18n.language as LanguagesType, + is_specialized: false, + }); }; const handleReset = () => { @@ -49,13 +53,9 @@ export const AIFeedback = ({ id, models }: props) => { }; useEffect(() => { - feedbackTrigger({ - id, - llm: model, - lang: i18n.language as LanguagesType, - }); + triggerFeedback(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [model]); + }, []); return ( <> @@ -83,13 +83,13 @@ export const AIFeedback = ({ id, models }: props) => {
- diff --git a/frontend/app/utils/types.ts b/frontend/app/utils/types.ts index 240df4e..e7db9c5 100644 --- a/frontend/app/utils/types.ts +++ b/frontend/app/utils/types.ts @@ -65,6 +65,7 @@ export type LLMFeedbackRequest = { id: string; llm: string; lang: LanguagesType; + is_specialized: boolean; }; export type LLMFeedbackResponse = { From 510f236cdb4e8052fda63788752d7bfc648eb970 Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 5 May 2026 07:06:16 +0000 Subject: [PATCH 28/32] =?UTF-8?q?refactor:=20=E8=BB=BD=E5=BE=AE=E3=81=AA?= =?UTF-8?q?=E3=83=AA=E3=83=95=E3=82=A1=E3=82=AF=E3=82=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/app/components/ai-feedback.tsx | 3 ++- frontend/app/routes/home.tsx | 13 +------------ ollama/Modelfile.gemma3-12b | 10 ---------- 3 files changed, 3 insertions(+), 23 deletions(-) delete mode 100644 ollama/Modelfile.gemma3-12b diff --git a/frontend/app/components/ai-feedback.tsx b/frontend/app/components/ai-feedback.tsx index 5bd4cbb..6d0479e 100644 --- a/frontend/app/components/ai-feedback.tsx +++ b/frontend/app/components/ai-feedback.tsx @@ -36,7 +36,8 @@ export const AIFeedback = ({ id, models }: props) => { const { t, i18n } = useTranslation(); const { feedbackTrigger, isFeedbackMutating, feedbackData } = useAIFeedback(); - const initialModel = models[1]; + const initialModel = models[1]; // backend/datastore/models.jsonのllm順番を参考にする + const selectLLMRef = useRef(initialModel); const triggerFeedback = () => { diff --git a/frontend/app/routes/home.tsx b/frontend/app/routes/home.tsx index 9977201..7cf97d4 100644 --- a/frontend/app/routes/home.tsx +++ b/frontend/app/routes/home.tsx @@ -85,9 +85,6 @@ const Home = () => { } else bedtime_answer = 0; if (email) { - console.log("Email provided:", email); - // - await viaEmailTrigger({ xmlFile: file, req: { @@ -106,7 +103,7 @@ const Home = () => { const { id, step_data } = extractStepResult; - const result = await estimateSleepTrigger({ + await estimateSleepTrigger({ id, step_data, answers: { @@ -115,14 +112,6 @@ const Home = () => { bedtime_answer, }, }); - - console.log({ - charging_before_bed_answer: Number(chargingBeforeBedAnswer), - carrying_a_smartphone_answer: Number(carryingASmartphoneAnswer), - bedtime_answer, - }); - - console.log(result); } catch (error) { console.error(error); } diff --git a/ollama/Modelfile.gemma3-12b b/ollama/Modelfile.gemma3-12b deleted file mode 100644 index 04b3ecb..0000000 --- a/ollama/Modelfile.gemma3-12b +++ /dev/null @@ -1,10 +0,0 @@ -# 簡易的なフィードバックに使用するLLM - -FROM gemma3:12b - -PARAMETER temperature 0.6 -PARAMETER top_p 0.9 -PARAMETER top_k 50 -PARAMETER repeat_penalty 1.1 -PARAMETER num_ctx 8192 -PARAMETER num_predict 3000 \ No newline at end of file From 0319070a2243bc55b4e8517e149883ae9bac2c41 Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 5 May 2026 07:33:23 +0000 Subject: [PATCH 29/32] =?UTF-8?q?feat:=20=E3=83=97=E3=83=A9=E3=82=A4?= =?UTF-8?q?=E3=83=90=E3=82=B7=E3=83=BC=E9=A0=85=E7=9B=AE=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E8=A8=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/app/components/file-upload.tsx | 2 +- frontend/app/locales/translation-en.json | 1 + frontend/app/locales/translation-ja.json | 1 + frontend/app/routes/home.tsx | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/app/components/file-upload.tsx b/frontend/app/components/file-upload.tsx index 52a92d8..ff0e8c7 100644 --- a/frontend/app/components/file-upload.tsx +++ b/frontend/app/components/file-upload.tsx @@ -58,7 +58,7 @@ export const FileUpload = ({ file, onFileChange }: props) => { return (
{ {t("upload.title")} {t("upload.description")} + {t("upload.privacy")} From afbf81a29d40031c5e44a5f6238a2896bafc92fd Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 5 May 2026 08:28:01 +0000 Subject: [PATCH 30/32] =?UTF-8?q?fix:=20=E8=A1=A8=E7=A4=BA=E6=96=87?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/app/locales/translation-en.json | 2 +- frontend/app/locales/translation-ja.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/app/locales/translation-en.json b/frontend/app/locales/translation-en.json index 947c285..5af8ede 100644 --- a/frontend/app/locales/translation-en.json +++ b/frontend/app/locales/translation-en.json @@ -30,7 +30,7 @@ }, "email": { "title": "Receive Results", - "description": "Feedback takes time to generate, so we'll send the results to your email. If you don't provide an email, you can view the results on the screen.", + "description": "If you would like specialized feedback, we will deliver the results to your email. If left blank, you can view the results directly on screen.", "placeholder": "Enter your email address", "sentTitle": "Analysis received", "sentDescription": "We'll send the results to {{email}} once the analysis is complete." diff --git a/frontend/app/locales/translation-ja.json b/frontend/app/locales/translation-ja.json index 38251a7..6f370c5 100644 --- a/frontend/app/locales/translation-ja.json +++ b/frontend/app/locales/translation-ja.json @@ -30,7 +30,7 @@ }, "email": { "title": "結果を受け取る", - "description": " フィードバックには時間がかかるため結果をメールでお届けします。未入力の場合はそのまま画面上で結果を確認できます。", + "description": " 専門的なフィードバックを希望の場合はメールでお届けします。未入力の場合はそのまま画面上で結果を確認できます。", "placeholder": "メールアドレスを入力", "sentTitle": "分析を受け付けました", "sentDescription": "分析が完了次第、結果を {{email}} にお送りします。" From 4b47d43693660e554f2919bdb4960992177927e5 Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 5 May 2026 08:28:26 +0000 Subject: [PATCH 31/32] =?UTF-8?q?feat:=20=E3=83=95=E3=83=AD=E3=83=B3?= =?UTF-8?q?=E3=83=88=E3=81=AE=E5=9E=8B=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/app/routes/home.tsx | 1 + frontend/app/utils/types.ts | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/frontend/app/routes/home.tsx b/frontend/app/routes/home.tsx index 1763d28..53ff2fc 100644 --- a/frontend/app/routes/home.tsx +++ b/frontend/app/routes/home.tsx @@ -94,6 +94,7 @@ const Home = () => { bedtime_answer, }, lang: i18n.language as LanguagesType, + is_specialized: true, // メール経由の場合は専門的なfb email_to: email, }, }); diff --git a/frontend/app/utils/types.ts b/frontend/app/utils/types.ts index e7db9c5..d056cb9 100644 --- a/frontend/app/utils/types.ts +++ b/frontend/app/utils/types.ts @@ -49,11 +49,12 @@ export type EstimateSleepResponse = { export type LanguagesType = "ja" | "en"; // email経由の解析関連のスキーマ -export type ViaEmailRequest = { - answers: Answers; - lang: LanguagesType; - email_to: string; -}; +export type ViaEmailRequest = + | { + answers: Answers; + email_to: string; + } + | LLMFeedbackBase; export type ViaEmailArg = { xmlFile: File; @@ -61,9 +62,14 @@ export type ViaEmailArg = { }; // フィードバック関連のスキーマ -export type LLMFeedbackRequest = { - id: string; - llm: string; +export type LLMFeedbackRequest = + | { + id: string; + llm: string; + } + | LLMFeedbackBase; + +export type LLMFeedbackBase = { lang: LanguagesType; is_specialized: boolean; }; From 993fd470995e710ecc30930637ac19a0ccee2cfc Mon Sep 17 00:00:00 2001 From: 273Do Date: Tue, 5 May 2026 08:29:15 +0000 Subject: [PATCH 32/32] =?UTF-8?q?fix:=20email=E7=B5=8C=E7=94=B1=E3=81=AE?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E3=81=AE=E3=83=AA=E3=82=AF=E3=82=A8=E3=82=B9?= =?UTF-8?q?=E3=83=88=E5=9E=8B=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/routers/via_email.py | 8 ++++++-- backend/src/schemas/llm_feedback.py | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/backend/src/routers/via_email.py b/backend/src/routers/via_email.py index 126d23b..609f80a 100644 --- a/backend/src/routers/via_email.py +++ b/backend/src/routers/via_email.py @@ -3,6 +3,7 @@ from src.schemas.extract_steps import ExtractStepsQueryParams, validate_extract_params from src.schemas.via_email import ViaEmailRequest from src.usecases.estimate_sleep.run_estimate_sleep_usecase import run_estimate_sleep +from src.usecases.estimate_sleep.save_data_to_storage_usecase import get_llms from src.usecases.extract_steps.extract_steps_usecase import ( extract_steps_from_applehealthcare, ) @@ -70,10 +71,13 @@ async def via_email( estimate_sleep_json = [r.model_dump(mode="json") for r in estimated_data] clusters_json = [c.model_dump(mode="json") for c in clusters] + models = get_llms() + model = models[0] # backend/datastore/models.jsonのllm順番を参考にする + feedback = get_feedback( estimate_sleep_json, # type: ignore clusters_json, # type: ignore - via_email_req.llm, + model, via_email_req.lang, via_email_req.is_specialized, ) @@ -83,6 +87,6 @@ async def via_email( await send_email( via_email_req.email_to, feedback, - via_email_req.llm, + model, via_email_req.lang, ) diff --git a/backend/src/schemas/llm_feedback.py b/backend/src/schemas/llm_feedback.py index f1eeb56..8f7a66b 100644 --- a/backend/src/schemas/llm_feedback.py +++ b/backend/src/schemas/llm_feedback.py @@ -6,9 +6,6 @@ class LLMFeedbackParams(BaseModel): """LLM による睡眠フィードバックを取得する基底スキーマ""" - llm: str = Field(description="使用するLLM", examples=["thor-gemma3:latest"]) - """使用するLLM""" - lang: Literal["ja", "en"] = Field( description="LLM のフィードバック言語", examples=["en"] ) @@ -30,6 +27,9 @@ class LLMFeedbackRequest(LLMFeedbackParams): ) """データ識別用のID""" + llm: str = Field(description="使用するLLM", examples=["thor-gemma3:latest"]) + """使用するLLM""" + class LLMFeedbackResponse(BaseModel): """LLM による睡眠フィードバックを取得するレスポンススキーマ"""