先日、都内で開催された「Qiita × FastDOCTOR Health Tech Hackathon」に同大学の友人ら3人でShimekiri_Keeper
として参加してきました。
このハッカソンは オンライン診療×AI
をテーマに、医療業界のDX化を推進しようという目的で開催された、2日間に渡るハッカソンです。
この記事では私たちの開発した「医療業務効率化システム『KarteLink』」の紹介を技術面での説明を加えならがしていこうと思います。
解決する課題とアイデア
我々は現在の日本では、慢性的な医療従事者不足に悩まされていることに対する解決策を打ち出したいと考えました。そもそもの医者の数を技術の力で増やすことはそう簡単ではないので、医者の日々の診察関連の業務の効率化を図ることができるプロダクトを開発しようと考えました。
当日、FastDoctorのエンジニアの方などの話を聞いた結果、医者などの医療従事者は患者と関わることがメインの業務であるにも関わらず、カルテやその他の書類の作成にかなりの時間を割いているという現状を知ることができました。
また問診時に注目してみます。現在でも事前問診を診察前に記入するケースはよくありますが、それだけでは不足している情報などがあります。その情報を事前に見いだして置けると、診察時間を減らすことができ、より多くの患者と向き合うことができるようになります。
そこで私たちは診察前・中・後の3ステップで以下のように技術面でのサポートを行い、上記の課題、医療業務の効率化、及びそれによる対応できる患者数の増加と本来の業務以外の時間の削減を実現しようとしました。
運用の流れ
KarteLinkの役割は先述の通り診察前・中・後と3ステップに分割されます。それぞれでのユーザー(患者および医者)の動作を簡易的に説明していきます。
1. 診察前 - 患者の事前問診
対象ユーザー:患者
患者は診察前に、KarteLinkの事前問診システムに入力を行います。自動で生成されるいくつかの質問に回答していくと、診断結果と医師への事前問診結果共有用のQRコードが表示されます。患者はこのQRコードを持参し、医者のもとへと出向きます。
2. 診察中 - 事前問診の確認と会話録音
対象ユーザー:医者
次に実際に医者と患者の問診がスタートします。
医者は患者が提示してきたQRコードをスキャンし、事前問診の結果及び医者向けの情報(考えられる病気や深堀りすべき情報など)がAIによる提示されます。これで医者はより効率の良い診断を実施することができます。
また同時に会話の録音と文字起こし・保存を行います。医者と患者との会話を文字起こしし、記録しておき、後からの分析に用いることができるようになります。
3. 診察後 - 診断結果・カルテの完全自動生成
対象ユーザー:医者
最後に診断後です。これまでのフローにより以下の3つの情報が保存されています。
- 患者による事前問診の結果
- 事前問診から得られるAIによるまとめ
- 医者と患者の会話データ
これらのデータからAIにより症状のまとめ、診断結果、治療内容が生成され表示されます。またカルテを書く際の一般的な形式であるSOAP形式でのカルテがPDFで自動生成されます。
使用技術
以下の技術を使用しました。選定理由は使い慣れていることやプロトタイプの開発であるため変更が容易なこと(DB)が主にあげられます。
バックエンドもNext.jsでまとめています。
- Next.js, React
- Firebase
- Gemini API
また今回はVibe Codingの知見を積極的に取り入れてみました。
Vibe Codingではチームとして以下の生成AIサービスを活用しました。
- Claude Code
- Github Copilot
- ChatGPT
- Claude
機能と技術的紹介
3人で分担して開発をしたので、詳しくない部分もあるのですが、全体的に技術的な観点から紹介したいと思います。
事前問診システム
事前問診システムの役割は、患者の状態を診断において必要十分な情報を取得し、AIに事前に可能性のある病気や注目すべき点を生成させることです。
最初に患者が今回の症状を打ち込むと、AIが先の症状から病名を予測できるような質問を10問程度自動で生成します。その質問に一問ずつ患者は答えていきます。患者の入力はフリー入力形式になっています。
すべての質問への回答が終わると、AIによる診断結果が表示されます。
以下の画像は頭痛に関する診断結果です。考えられる症状や症状のサマリーなどが患者向けに表示されるようになっています。
また回答終了と同時に、ShinsatsuId
が生成され、事前問診結果とともにDBに保存されるようになっています。今後の処理はこのShinsatsuId
をベースに診察が進んでいきます。
事前問診結果ページにはShinsatsuId
が仕込まれたURLが表示され、医者側でスキャンすることで、事前問診に対する医者向けの情報が医者側で表示されることとなります。
事前問診共有と概要表示
次は医者側の機能の紹介となります。
患者が持ってきたShinsatsuId
入りのQRコードをシステム上でスキャンすると、事前問診結果に加え、医者向けの情報が表示されます。具体的には緊急度や診断候補、症状の要点や診察準備情報、重点項目などです。
これにより医者は患者と話す前に、患者の容態をある程度知ることができ、効率的に診察を進めることができるようになります。同時に複数の医者がいる病院では、事務員的な人が、患者の症状に応じてその症状を得意とする医者に患者を振り分けることがあるようです。そういう点でも活用できるよ考えています。
QRコードの読み取りにはZXing
を用いました。医者向けの情報は、患者が事前問診に回答した時点でAIに生成させてDBに保存しているものを表示するだけのシステムです。
また事前問診結果以外にも後述する機能へのリンクが貼られるなどダッシュボードとしての役割を担っています。
会話音声文字起こし
医者と患者の診察中の会話の文字起こしをしてDBに文字起こし結果を保存する機能です。会話データを元に最終的な診察結果やカルテを作成するために行います。
文字起こしができるいくつかのサービスやAPIを探したところGemini APIが結局一番精度よく文字起こしをすることができ、またプロジェクト全体でもGemini APIを用いていることから、Gemini APIを採用することにしました。
Gemini APIには音声データを投げると、その音声データを元に要約を生成したり、音声データに関する質問、今回の文字起こしなどができるようです。生成AIの機能も加わったおかげなのか、医療の専門用語に関しても精度よく分析をおこなってくれました。
Gemini APIでは、一つの音声ファイルを渡すと、その音声ファイルと与えたプロンプトに沿った結果を返してくれる機能しかなく、リアルタイムでの文字起こしなどは標準機能では難しい状態です。
一度、5分程の音声ファイルを文字起こししてみましたが、そこそこ時間がかかることが分かりました。そのため、録音後長いデータを一回で処理しようとすると、待機時間が長くなりシステムの本来の目的である効率的とは遠くなります。
そこで逐次文字起こしをする形に変更しました。リアルタイムの処理には対応していないので、録音を10秒ごとに開始・停止を繰り返して10秒の音声データ、チャンクをスタックしていきます。
文字起こしの処理は1チャンクごとに行うことで、疑似リアルタイム文字起こしを実現しました。これにより録音最後に長い時間待たされることもなく、分割して処理することでシステム的にも実現可能にしました。
(文字起こしのUIは文字起こしされるだけなので、スクリーンショットは割愛します)
この部分は僕が担当した実装の中でもかなり苦戦した部分なので、この部分だけに絞って実装など詳しく書いた記事をいつか書きたいところです...
カルテの自動生成
現在DBには事前問診結果と診察中の会話データが保存されています。この情報からカルテの一般的な形式であるSOAP形式でのカルテを自動生成します。
カルテの生成にもGemini APIを用いています。PDFの生成はhtml2pdf.js
を用いました。
詳しい話は実装を担当したチームメンバーが記事を書いているのでそちらを参照してください↓↓↓
今回できなかったこと / 可能性を感じたこと
-
医者による追加気づきの入力
現在は事前問診と会話データからしか診察結果が出ません。このシステムはあくまでも医者主体の仕組みであるのだから、医者の気づきや診察結果も反映できるようにするべきです。 -
過去のカルテとの同期
上記と同様に過去のカルテや患者データベースとの連携をすると強そうです。 -
事前問診データの連携
余談ではありますが、世の中には既にオンラインで問診出来るUbieなどのサービスが存在しています。そのようなサービスと連携することができると、より高度な事前問診も可能になると思いました。 -
事前問診の質問内容の適宜変更
現在の事前問診の質問は最初に全て生成する方式です。しかし、回答によっては最初の予想と異なる方向に向かっていくかもしれません。そのようなケースにもきちんと対応できるように過去の回答から新たな質問を生成できると良いかもしれません。
でも事前問診システムは、今回のカルテ作成とはほぼ独立しているので、上記の他サービスとの連携をすると良いという説もあります。 -
音声文字起こしの精度検証
今回実装した文字起こしでは長い会話データなどで実際に動くかのテストをしていません。そのためその調査が必要です。またGemini APIでは人物を識別して、誰が喋っているかの情報も生成できる気がしているので、より精度の高い会話データの取得のためにそのような工夫を入れると好ましかったです。
ex) [doctor]: 頭痛はいつ頃に発症しましたか?
他にも医者が本当に必要としている情報は何なのかという調査や、カルテの形式、カルテの他にどのような書類の作成が必要かという課題も残っています。
ハッカソンの感想
さてこの記事の投稿締め切りまで残りあと約10分、今感想を書き始めました。
Shimekiri_keeper
というチーム名の由来は、チーム結成と参加申し込みが締め切り30分前で、ギリギリすぎる行動だったからです。ついでに初日の会場入りも開始1分前とかでギリギリでした。
今回の記事投稿もギリギリのようです。
↑こんなこと書くので時間使わずに早く感想を書け!という話ではある。
私含めチームメンバー3人とも全員がハッカソン初参加でした。
これまでWebサービスの開発をして数年ですが、このような2日間という短い期間でかつチーム開発は初めてで、発表まできちんと出来るか不安でしたが、どうにかなってよかったです。
Web方面の経験があまりないメンバーへの各ツール等の教え方やGit/Githubの操作などまだまだ未熟なことも多かったです。
(残り4分)
また今回のハッカソンは医療×ITという、自分の未経験の分野での挑戦でした。医療現場の実情を聞くとシステム化やAIで解決できる課題もまだありそうだなと感じたとともに、現在の法規制や医療体制で導入が難しい面もあるように感じました。
技術の力以外でも世の中を変えていけるような様々な人や機関との連携も大切だと感じたイベントになりました。
そしてハッカソンという会場において日頃関わりの少ない、実際に働いているエンジニアの方や医療従事者ともお話をしたり、アイデア・成果物に対するフィードバックを受けることができるいい機会となりました。またハッカソンがあれば参加したいと思います。その時はWeb技術じゃなく、機械学習やRAGなどの技術も使えるようになりたいです。
では1分前!バイバイ!