Skip to content

Latest commit

 

History

116 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AI Medical Scribe - 医療書記自動生成システム

リアルタイム音声認識とAIによるSOAPカルテ自動生成を実現する、医療従事者向けプロトタイプアプリケーション

目次

概要

本システムは、医師と患者の会話をリアルタイムで音声認識し、AIが自動的にSOAP形式(Subjective, Objective, Assessment, Plan)の電子カルテを生成するWebアプリケーションです。

開発背景

医療現場では、診察後のカルテ記入作業が医師の大きな負担となっています。本システムは、この作業を自動化し、医師が診察に集中できる環境を提供することを目的としています。

開発期間

基盤2-3時間、UIUX実装は2-3日の範囲内で実装可能なMVP(Minimum Viable Product)として設計されています。

主要機能

1. リアルタイム音声認識

  • Web Speech APIを使用したブラウザネイティブな音声認識
  • 連続認識モード対応
  • 日本語(ja-JP)完全対応
  • マイク許可管理

2. AI駆動のSOAPカルテ生成

OpenAI GPT-4/5の軽量モデルを使用した、以下の情報を含む詳細な医療記録の自動生成:

患者情報

  • 主訴(Chief Complaint)
  • 症状期間

S(Subjective - 主観的情報)

  • 現病歴の詳細
  • 症状リスト
  • 重症度評価
  • 発症様式
  • 随伴症状
  • 既往歴
  • 現在服用中の薬剤

O(Objective - 客観的情報)

  • バイタルサイン(血圧、脈拍、体温、呼吸数)
  • 身体所見
  • 検査所見

A(Assessment - 評価・診断)

  • 診断名(日本語)
  • ICD-10コード(国際疾病分類)
  • 鑑別診断リスト
  • 臨床的評価

P(Plan - 治療計画)

  • 治療方針
  • 処方薬詳細(薬剤名、用量、用法、期間)
  • 追加検査項目
  • 専門医への紹介
  • フォローアップ計画
  • 患者指導内容

3. カルテ音声読み上げ機能

生成されたSOAPカルテを音声で確認できる、Text-to-Speech(TTS)機能を搭載:

  • Web Speech Synthesis APIを使用したブラウザネイティブな音声合成
  • 日本語音声による自然な読み上げ
  • 読み上げ速度の調整機能(0.5x / 0.75x / 1.0x / 1.25x / 1.5x)
  • 複数の日本語音声から選択可能
  • SOAP全項目の構造化された読み上げ
    • 要約 → 患者情報 → S(主観的情報)→ O(客観的情報)→ A(評価・診断)→ P(治療計画)
  • 処方内容の詳細読み上げ(薬剤名、用量、用法、期間)
  • 再生/停止コントロール

音声読み上げの利点

  • 手が離せない状況でのカルテ確認
  • 視覚的な確認と聴覚的な確認による二重チェック
  • 長文カルテの内容把握がより容易に
  • アクセシビリティ向上(視覚障害のあるユーザー支援)

4. UI/UXデザイン

  • レスポンシブデザイン(PC/タブレット/スマートフォン対応)
  • リアルタイムステータス表示
  • 2カラムレイアウト(入力 | 出力)
  • PC版:リサイズ可能な分割ビュー、レイアウトプリセット機能
  • モバイル版:アコーディオン形式の切り替え
  • アクセシビリティ対応(ARIA属性、セマンティックHTML)

技術スタック

フロントエンド

技術 バージョン 用途
Next.js 16.1.6 Reactフレームワーク(App Router使用)
React 19.2.3 UIライブラリ
TypeScript 5.x 型安全性の確保
Tailwind CSS 4.x ユーティリティファーストCSS

バックエンド

技術 用途
Next.js API Routes サーバーサイドAPI
OpenAI API GPT-4/5によるテキスト生成
OpenAI Embeddings API text-embedding-3-small によるセマンティック医療辞書検索

ブラウザAPI

技術 用途
Web Speech API (Recognition) ブラウザネイティブ音声認識(音声→テキスト)
Web Speech API (Synthesis) ブラウザネイティブ音声合成(テキスト→音声)

開発ツール

ツール 用途
ESLint コード品質チェック
PostCSS CSS処理
Git バージョン管理

システムアーキテクチャ

全体構成

┌─────────────────────────────────────────────────────────┐
│                        Browser                          │
│  ┌───────────────────────────────────────────────────┐  │
│  │            React Component (page.tsx)             │  │
│  │                                                   │  │
│  │  ┌────────────┐          ┌──────────────────┐   │  │
│  │  │ Web Speech │          │  User Interface  │   │  │
│  │  │    API     │─────────▶│  - Input Panel   │   │  │
│  │  │ (ja-JP)    │          │  - Output Panel  │   │  │
│  │  └────────────┘          │  - Controls      │   │  │
│  │                          └──────────────────┘   │  │
│  └───────────────────────────────────────────────────┘  │
│                            │                            │
│                            │ HTTP POST                  │
│                            ▼                            │
│  ┌───────────────────────────────────────────────────┐  │
│  │     Next.js API Route (/api/analyze)             │  │
│  │  - リクエスト検証                                  │  │
│  │  - プロンプト構築                                  │  │
│  │  - OpenAI API呼び出し                             │  │
│  └───────────────────────────────────────────────────┘  │
│                            │                            │
└────────────────────────────┼────────────────────────────┘
                             │
                             ▼
                    ┌─────────────────┐
                    │   OpenAI API    │
                    │   GPT-6 Luna    │
                    │  JSON Response  │
                    └─────────────────┘

ディレクトリ構造

medical-scribe-demo/
├── src/
│   └── app/
│       ├── api/
│       │   └── analyze/
│       │       ├── route.ts          # OpenAI API統合
│       │       ├── prompt.ts         # システムプロンプト定義
│       │       └── types.ts          # TypeScript型定義
│       ├── globals.css               # グローバルスタイル
│       ├── layout.tsx                # ルートレイアウト
│       └── page.tsx                  # メインページ(音声認識・読み上げ・UI)
├── .env.local                        # 環境変数(APIキー)
├── package.json                      # 依存関係
└── README.md                         # このファイル

セットアップ

前提条件

  • Node.js 18.x 以上
  • npm または yarn
  • OpenAI APIキー(現在稼働テストとして設定中)
  • Chromeまたは最新のブラウザ(Web Speech API対応)

インストール手順

  1. リポジトリをクローン
git clone https://github.com/BoxPistols/medical-scribe-demo.git
cd medical-scribe-demo
  1. 依存関係をインストール
npm install
  1. 環境変数を設定

プロジェクトルートに .env.local ファイルを作成:

OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

OpenAI APIキーは OpenAI Platform で取得できます。

  1. 開発サーバーを起動
npm run dev
  1. ブラウザでアクセス
http://localhost:3000

使い方

基本的な操作フロー

  1. 録音開始

    • 「録音」ボタンをクリック
    • ブラウザがマイクへのアクセス許可を要求(初回のみ)
    • 録音中は「録音中」ステータスが表示される
  2. 会話の入力

    • 音声で会話を入力
    • または、テキストエリアに直接入力も可能
  3. SOAPカルテ生成

    • 「カルテ生成」ボタンをクリック
    • AIが会話を解析(5-15秒程度)
    • 右パネルに詳細なSOAPカルテが表示される
  4. カルテの音声読み上げ(オプション)

    • カルテパネル右上の「読み上げ」ボタンをクリック
    • SOAP全項目が日本語音声で読み上げられる
    • 読み上げ中は「停止」ボタンで中断可能
    • 速度調整: 0.5倍速〜1.5倍速まで選択可能
    • 音声選択: 利用可能な日本語音声から選択可能(ブラウザ・OSに依存)
    • 手が離せない状況や、聴覚的な確認をしたい場合に便利
  5. 結果の確認

    • 要約、患者情報、SOAP各セクションを確認
    • バイタルサイン、処方内容などの詳細情報を閲覧
  6. クリア

    • 「クリア」ボタンで全データをリセット

サンプル会話文

以下のような会話を入力してテストできます:

医師: 今日はどうされましたか?
患者: 2週間くらい前から頭痛がひどくて、特に朝起きたときに痛みます。ズキズキする感じです。
医師: 他に症状はありますか?
患者: 少しめまいと吐き気があります。あと最近疲れやすいです。
医師: 既往歴はありますか?何か薬を飲んでいますか?
患者: 高血圧で5年前からアムロジピンを飲んでいます。
医師: では診察しますね。血圧を測りましょう。
患者: はい。
医師: 血圧は145/95、少し高めですね。体温は36.8度、脈拍は78です。目を見せてください。瞳孔は正常ですね。
医師: 頭のCTは必要ないと思いますが、念のため血液検査をしましょう。処方箋を出しますね。
患者: ありがとうございます。
医師: ロキソプロフェン60mgを1日3回、食後に7日分出します。あとアムロジピンは継続してください。1週間後にまた来てください。

API設計

エンドポイント

POST /api/analyze

会話テキストを受け取り、SOAP形式のカルテを生成します。

リクエスト

{
  text: string  // 会話テキスト(必須)
}

レスポンス(成功時)

{
  summary: string,
  patientInfo: {
    chiefComplaint: string,
    duration: string
  },
  soap: {
    subjective: {
      presentIllness: string,
      symptoms: string[],
      severity: string,
      onset: string,
      associatedSymptoms: string[],
      pastMedicalHistory: string,
      medications: string[]
    },
    objective: {
      vitalSigns: {
        bloodPressure: string,
        pulse: string,
        temperature: string,
        respiratoryRate: string
      },
      physicalExam: string,
      laboratoryFindings: string
    },
    assessment: {
      diagnosis: string,
      icd10: string,
      differentialDiagnosis: string[],
      clinicalImpression: string
    },
    plan: {
      treatment: string,
      medications: Array<{
        name: string,
        dosage: string,
        frequency: string,
        duration: string
      }>,
      tests: string[],
      referral: string,
      followUp: string,
      patientEducation: string
    }
  }
}

レスポンス(エラー時)

{
  error: string  // エラーメッセージ
}

APIの内部処理

  1. 入力検証

    • テキストの存在確認
    • モデルIDの検証とフォールバック
    • レート制限チェック(gpt-6-luna: 50回/日)
  2. セマンティック医療辞書検索

    • 入力テキスト(先頭1000文字)を text-embedding-3-small でベクトル化
    • 事前計算済み医療用語データセットとCosine Similarity検索
    • 上位5件(類似度 >= 0.3)の医療用語・ICD-10コードを取得
    • 失敗時は検索スキップ(フォールバック)
  3. プロンプト構築

    • 静的システムプロンプト(医療記録専門家ロール + JSON出力形式)
    • 動的医療コンテキスト(検索結果の注入)
    • ストリーミング/非ストリーミング両対応
  4. OpenAI API呼び出し

    • モデル: gpt-6-luna
    • レスポンス形式: json_object
    • トークン上限: 16000
  5. レスポンス処理

    • JSON パース
    • トークン使用量・コスト計算
    • エラーハンドリング(401/429/SyntaxError)
    • クライアントへの返却

データフロー

1. 音声入力フロー

User Speech
    ↓
Web Speech API (Browser)
    ↓
Recognition Event
    ↓
State Update (React)
    ↓
Transcript Display

2. AI解析フロー

User Click "Generate"
    ↓
Fetch API Call
    ↓
Next.js API Route (/api/analyze)
    ↓
┌─── セマンティック医療辞書検索 ───┐
│  入力テキスト(先頭1000文字)     │
│       ↓                          │
│  text-embedding-3-small (dim=256)│
│       ↓                          │
│  Cosine Similarity検索            │
│  (事前計算済み50エントリと比較)    │
│       ↓                          │
│  上位5件の医療用語・ICD-10を      │
│  システムプロンプトに注入          │
└──────────────────────────────────┘
    ↓
System Prompt + Medical Context + User Text
    ↓
OpenAI API (GPT-6 Luna)
    ↓
JSON Response
    ↓
Validation & Error Handling
    ↓
State Update (React)
    ↓
SOAP Display with Structured Data

3. 音声読み上げフロー

User Click "Read Aloud"
    ↓
Extract Text from SOAP Note
    ↓
Format for Natural Speech
  - 要約 → 患者情報 → S → O → A → P
  - 区切り文字、読点の最適化
    ↓
Create SpeechSynthesisUtterance
  - Language: ja-JP
  - Rate: 0.5x ~ 1.5x (User Setting)
  - Voice: Selected Japanese Voice
    ↓
Web Speech Synthesis API (Browser)
    ↓
Audio Output (Speaker/Headphone)

制御機能:

  • 再生中: 停止ボタンで即座に中断
  • 速度調整: リアルタイムで変更可能
  • 音声選択: ブラウザ対応の日本語音声から選択

プロンプトエンジニアリング

システムプロンプトの設計思想

本システムの核心は、OpenAI APIに送信するプロンプトの品質にあります。以下の戦略で医療記録の質を最大化しています。

1. ロール設定

あなたは経験豊富な医療記録専門家です。

明確なロールを設定することで、AIの出力品質を向上させています。

2. 詳細な出力構造の指定

JSONスキーマを明示的に指定し、以下を実現:

  • 構造化されたデータ出力
  • フィールドの一貫性
  • クライアント側の処理簡略化

3. 医学的妥当性の指示

会話から推測できる情報を最大限に活用し、臨床的に妥当な詳細を補完してください

限られた会話情報から、臨床的に矛盾のない記録を生成するよう指示しています。

4. 専門用語の使用

医学用語を適切に使用し、実際の診療記録としての完成度を高めてください

実際の医療現場で使用される表現を優先させています。

5. 不確実性の明示

不明な情報は「記載なし」と明記してください

推測と事実を明確に区別し、医療安全を確保しています。

6. セマンティック医療辞書検索によるコンテキスト注入

SOAP生成の精度を向上させるため、text-embedding-3-smallを使ったセマンティック検索で関連する医療用語・ICD-10コードを動的にプロンプトへ注入しています。

仕組み
音声テキスト「2週間前から頭が痛い、朝起きた時にズキズキする、めまいと吐き気もある」
    ↓
[1] text-embedding-3-small でテキストをベクトル化 (256次元)
    ↓
[2] 事前計算済み医療用語データセット (50エントリ) とCosine Similarity比較
    ↓
[3] 上位5件の関連医療用語を取得:
    - 片頭痛 (G43.9) - 類似度: 0.78
    - 頭痛 (R51) - 類似度: 0.75
    - めまい (R42) - 類似度: 0.62
    - 本態性高血圧症 (I10) - 類似度: 0.45
    - 脳梗塞 (I63.9) - 類似度: 0.38
    ↓
[4] システムプロンプトの末尾に参考情報として注入
    ↓
[5] LLMがこの参考情報を踏まえてSOAPノートを生成
従来との比較
項目 従来(プロンプトのみ) セマンティック検索導入後
ICD-10コード LLMの学習済み知識に依存。コードの記憶違いや存在しないコードを生成するリスクあり 実在するICD-10コードを参考情報として提供。正確なコードが出力されやすい
診断名の表記 口語表現のまま(例: 「頭痛」)出力されることがある 正式な病名(例: 「片頭痛 G43.9」)が参照可能
鑑別診断 LLMの推論のみで生成 類似度ベースで関連疾患が提示されるため、見落としが減少
関連症状の網羅性 会話に明示された症状のみ 各疾患に紐づくキーワード(関連症状)が提示され、確認漏れを防止
処理コスト embedding APIコールなし +1回のembedding API呼び出し($0.000002/リクエスト、事実上無料)
レイテンシ なし +約100-200ms(embedding生成 + cosine similarity計算)
医療用語データセット

50エントリの事前構築データセットで、日本のプライマリケアの主要疾患をカバーしています。

カテゴリ エントリ数 代表的な疾患例
呼吸器系 6 急性上気道炎(J06.9)、肺炎(J18.9)、気管支喘息(J45.9)
消化器系 5 急性胃腸炎(K52.9)、逆流性食道炎(K21.0)、過敏性腸症候群(K58.9)
循環器系 5 本態性高血圧症(I10)、狭心症(I20.9)、心房細動(I48.9)
内分泌・代謝 5 2型糖尿病(E11.9)、脂質異常症(E78.5)、甲状腺機能低下症(E03.9)
筋骨格系 6 腰痛症(M54.5)、変形性膝関節症(M17.9)、痛風(M10.9)
神経系 3 片頭痛(G43.9)、不眠症(G47.0)、てんかん(G40.9)
精神科 3 うつ病(F32.9)、全般性不安障害(F41.1)、パニック障害(F41.0)
感染症 4 インフルエンザ(J10.1)、COVID-19(U07.1)、帯状疱疹(B02.9)
皮膚科 3 蕁麻疹(L50.9)、湿疹(L30.9)、アトピー性皮膚炎(L20.9)
泌尿器系 2 膀胱炎(N30.9)、前立腺肥大症(N40)
症状・症候 5 発熱(R50.9)、胸痛(R07.9)、腹痛(R10.4)、めまい(R42)、頭痛(R51)
その他 3 鉄欠乏性貧血(D50.9)、結膜炎(H10.9)、中耳炎(H66.9)

各エントリは以下の情報を持ちます:

  • ICD-10コード: WHO国際疾病分類コード
  • 病名(日本語・英語): 正式名称
  • 別名・口語表現: 音声認識で入力される可能性のある表現(例: 「風邪」「おなかの風邪」)
  • 関連症状キーワード: 疾患に紐づく主要症状
技術仕様
  • embeddingモデル: text-embedding-3-small (OpenAI)
  • ベクトル次元数: 256(デフォルト1536から削減、ファイルサイズと精度のバランス)
  • 事前計算済みファイル: src/data/medical-terms-embedded.json (約235KB)
  • 検索閾値: cosine similarity >= 0.3
  • 返却件数: 上位5件
  • フォールバック: embedding API呼び出し失敗時は従来通り(コンテキストなし)でSOAP生成を継続
データセット更新方法
# 1. 元データを編集(embeddingなし)
# src/data/medical-terms-source.json を編集

# 2. embeddingを再生成
pnpm generate:embeddings

# 3. 生成されたファイルをcommit
# src/data/medical-terms-embedded.json

UI/UXデザイン

デザインコンセプト

"Clinical Professionalism meets Modern Web"

医療現場の信頼性と、モダンWebアプリケーションの使いやすさを両立しています。

カラーパレット

/* ベースカラー - 清潔感のあるクリニカルパレット */
--bg-primary: #fafbfc;      /* 背景 */
--bg-secondary: #ffffff;     /* パネル */

/* アクセントカラー - ティール(医療的で落ち着いた印象) */
--accent-primary: #14b8a6;   /* プライマリアクション */
--accent-warm: #f59e0b;      /* 録音ボタン */

/* SOAPカラー - 視覚的識別性 */
--soap-s: #ef4444;  /* 主観的情報(赤) */
--soap-o: #3b82f6;  /* 客観的情報(青) */
--soap-a: #10b981;  /* 評価(緑) */
--soap-p: #8b5cf6;  /* 計画(紫) */

タイポグラフィ

用途 フォント 特徴
UI全般 DM Sans 可読性が高く、モダンな印象
データ表示 JetBrains Mono 等幅で、医療データの視認性向上

レスポンシブブレークポイント

/* モバイル */
@media (max-width: 640px)

/* タブレット */
@media (max-width: 1024px)

/* デスクトップ */
@media (min-width: 1024px)

アクセシビリティ

  • セマンティックHTML(<header>, <main>, <section>)
  • ARIA属性(aria-label, aria-pressed)
  • キーボードナビゲーション対応
  • フォーカス表示
  • カラーコントラスト比(WCAG AA準拠)

キーボードショートカット

本システムは豊富なキーボードショートカットを備えており、クロスプラットフォーム対応を実装しています。

OS自動判定

OS 修飾キー 例
macOS Cmd Cmd + R
Windows/Linux Ctrl Ctrl + R
  • ブラウザのnavigator.platformとnavigator.userAgentでOSを自動判定
  • ショートカットの動作・表示が自動的にOSに最適化される
  • ユーザーによるカスタマイズも可能(設定モーダルから変更)

主なショートカット

機能 デフォルトキー 修飾キー付き
録音開始/停止 R Cmd/Ctrl + R
カルテ生成 A Cmd/Ctrl + A
読み上げ開始/停止 V Cmd/Ctrl + V
ショートカット設定 K -
ヘルプ H -

※ 「修飾キー付き」モードは設定から切り替え可能

今後の拡張可能性

Phase 1: 機能強化(短期)

  • ✅ 完了: カルテ音声読み上げ機能(速度調整、音声選択)
  • 計画中 (Issue #2): データエクスポート/インポート機能
    • JSON形式エクスポート/インポート
    • CSV形式エクスポート(Excel対応)
    • PDF形式エクスポート
  • カルテのコピー機能(クリップボード)
  • 履歴機能(LocalStorage/IndexedDB)
  • 音声認識精度の表示
  • 複数言語対応(英語、中国語)

Phase 2: データ統合(中期)

  • ✅ 完了: セマンティック医療辞書検索(text-embedding-3-small + ICD-10、50エントリ)
  • 計画中: 医療用語データセット拡充(50 → 500エントリ)
  • 計画中: MANBYO辞書・MEDIS標準マスター連携
  • RxNorm API統合(標準薬剤名称)
  • FHIR形式でのデータエクスポート
  • 電子カルテシステムとの連携

Phase 3: AI機能拡張(中期)

  • GPT-4による高精度解析
  • ファインチューニングモデルの導入
  • 医療画像解析統合
  • リアルタイムAI提案機能

Phase 4: エンタープライズ機能(長期)

  • ユーザー認証・権限管理
  • 患者データベース統合
  • 監査ログ機能
  • HIPAA/GDPR準拠のセキュリティ
  • マルチテナント対応
  • クラウドバックアップ

技術的な拡張

  • WebSocket によるリアルタイム通信
  • PWA 対応(オフライン機能)
  • E2Eテスト(Playwright/Cypress)
  • パフォーマンス最適化
  • CDN統合

注意事項

重要な制限事項

  1. デモンストレーション用途のみ

    • 本システムは概念実証(PoC)として開発されています
    • 実際の臨床現場での使用は想定していません
  2. 医療機器ではありません

    • 薬機法(医薬品医療機器等法)の適用外です
    • 診断や治療の根拠として使用しないでください
  3. AI生成内容の不確実性

    • GPT-6 Lunaの出力は100%正確ではありません
    • 必ず医師による確認・修正が必要です
    • 幻覚(Hallucination)により事実と異なる内容が生成される可能性があります
  4. プライバシーとセキュリティ

    • 実際の患者情報は入力しないでください
    • OpenAI APIに送信されたデータは30日間保存されます
    • 医療機関で使用する場合は、適切なデータ保護対策が必要です
  5. ブラウザ互換性

    • Web Speech APIはChrome/Edgeで最適に動作します
    • SafariおよびFirefoxでは機能が制限される場合があります

コスト

OpenAI APIの使用料金が発生します:

  • GPT-6 Luna: $0.10 / 1M input tokens, $0.50 / 1M output tokens(src/app/api/analyze/types.tsのAVAILABLE_MODELSが正)
  • 1回の解析あたり約$0.001-0.005(会話の長さによる)

法的考慮事項

  • 個人情報保護法: 実際の患者情報を扱う場合は適用対象
  • 医療法: 医療広告規制に注意
  • 利用規約: OpenAI利用規約の遵守が必要

ライセンス

MIT License

作成者 @BoxPistols / Ito Atsushi

開発期間: メイン機能 2-3時間 / UIUXリファクタリング2-3日 技術スタック: Next.js 14, TypeScript, OpenAI API, Web Speech API

参考資料

Releases

Packages

Contributors

Languages