1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenAIを実装してスマートシティ向けヘルスケアシステムを構築してみた

Last updated at Posted at 2025-03-04

AIで健康診断から医療機関への連携、服薬リマインド、訪問看護師の手配、緊急連絡先への通知までをシームレスに管理する

やりたい事
1.健康診断の結果を入力
2.診断結果を分析し、緊急度などを評価
3.診断結果に応じて医療機関や訪問看護師へ自動通知
4.家族へメールで診断結果とアクションを通知
5.毎日指定時間に服薬リマインドを実行(スケジューリング機能)
6.診断履歴やアクションログも残しておく

以下のライブラリ等が無い場合は事前にインストールしておきます。

# pip install flask flask-sqlalchemy flask-wtf wtforms

まずは以下1のメインとなる以プログラムをサーバとして起動しておきます。またこのプログラムと連携する各データ入力確認画面とその遷移までをざっくりと解説します。

1.ヘルスケアメインプログラム

import os
import json
import logging
import smtplib
from datetime import datetime
from flask import Flask, render_template, request, redirect, url_for, jsonify
from flask_sqlalchemy import SQLAlchemy
from email.mime.text import MIMEText
from openai import OpenAI

# Flaskアプリ設定
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///healthcare.db'
app.config['SECRET_KEY'] = 'your_secret_key'
db = SQLAlchemy(app)

# OpenAI API 初期化
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

# ログ設定
logging.basicConfig(filename='healthcare.log', level=logging.INFO, format='%(asctime)s - %(message)s')

# **データベースモデル**
class CitizenHealth(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    age = db.Column(db.Integer, nullable=False)
    symptoms = db.Column(db.String(255), nullable=False)
    medications = db.Column(db.String(255), nullable=False)
    diagnosis = db.Column(db.String(255), nullable=True)
    emergency_contact = db.Column(db.String(100), nullable=False)
    status = db.Column(db.String(50), nullable=True, default="未診断")

class Nurse(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    contact = db.Column(db.String(50), nullable=False)
    specialty = db.Column(db.String(100), nullable=False)

class MedicalCenter(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    location = db.Column(db.String(200), nullable=False)
    contact = db.Column(db.String(50), nullable=False)

# DB 初期化
with app.app_context():
    db.create_all()

# **健康データ登録**
@app.route('/health', methods=['GET', 'POST'])
def register_health():
    if request.method == 'POST':
        name = request.form['name']
        age = request.form['age']
        symptoms = request.form['symptoms']
        medications = request.form['medications']
        emergency_contact = request.form['emergency_contact']

        new_health = CitizenHealth(name=name, age=age, symptoms=symptoms,
                                   medications=medications, emergency_contact=emergency_contact)
        db.session.add(new_health)
        db.session.commit()

        # **GPT-4o による診断**
        diagnosis = analyze_health_status(name, age, symptoms)
        new_health.diagnosis = diagnosis
        new_health.status = "診断済み"
        db.session.commit()

        log_action(f"{name} さんの診断結果: {diagnosis}")

        # **緊急度が高い場合、医療機関と看護師を手配**
        if "" in diagnosis:
            notify_medical_center(new_health)
            dispatch_nurse(new_health)
            notify_family(new_health)
            new_health.status = "緊急対応"
            db.session.commit()
        elif "" in diagnosis:
            notify_family(new_health)
            new_health.status = "要注意"
            db.session.commit()
        else:
            new_health.status = "軽度"
            db.session.commit()

        return redirect(url_for('health_list'))

    return render_template('register_health.html')

# **健康データ一覧**
@app.route('/health_records')
def health_list():
    health_records = CitizenHealth.query.all()
    return render_template('health_records.html', health_records=health_records)

# **リアルタイム診断ログを表示**
@app.route('/logs')
def view_logs():
    with open('healthcare.log', 'r') as file:
        logs = file.readlines()
    return render_template('logs.html', logs=logs)

# **GPT-4o による健康チェック**
def analyze_health_status(name, age, symptoms):
    prompt = f"""
    {name} さん({age}歳)の健康状態を評価してください。
    【症状】{symptoms}
    診断結果:
    - 緊急性: (低 / 中 / 高)
    - 推奨対応: (例: 医療機関を受診 / 訪問看護師の派遣 / 経過観察)
    - コメント: (追加のアドバイス)
    """

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": prompt}],
        max_tokens=200
    )

    return response.choices[0].message.content

# **医療機関へ通知**
def notify_medical_center(health_data):
    medical_centers = MedicalCenter.query.all()
    if not medical_centers:
        return

    selected_center = medical_centers[0]
    log_action(f"🏥 {health_data.name} さんを {selected_center.name} に連絡")

# **訪問看護師を手配**
def dispatch_nurse(health_data):
    nurses = Nurse.query.all()
    if not nurses:
        return

    nurse = nurses[0]
    log_action(f"🚑 {health_data.name} さんに {nurse.name} 看護師を派遣")

# **家族へ通知**
def notify_family(health_data):
    log_action(f"📩 家族へ通知を送信: {health_data.name} さんの健康状態")

# **アクションログを記録**
def log_action(message):
    logging.info(message)

# **Flaskアプリ起動**
if __name__ == '__main__':
    app.run(debug=True)

2.医療機関登録画面

<form method="POST">
    <label>医療機関名:</label>
    <input type="text" name="name" required><br>
    <label>所在地:</label>
    <input type="text" name="location" required><br>
    <label>連絡先:</label>
    <input type="text" name="contact" required><br>
    <button type="submit">登録</button>
</form>
<a href="{{ url_for('medical_center_list') }}">医療機関一覧</a>

3.看護師登録画面

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>看護師登録</title>
</head>
<body>
    <h2>看護師の登録</h2>
    <form method="POST">
        <label>名前:</label>
        <input type="text" name="name" required><br>
        <label>連絡先:</label>
        <input type="text" name="contact" required><br>
        <label>専門分野:</label>
        <input type="text" name="specialty" required><br>
        <button type="submit">登録</button>
    </form>
    <a href="{{ url_for('nurse_list') }}">看護師一覧</a>
</body>
</html>

4.健康状態入力画面

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>健康データ登録</title>
</head>
<body>
    <h2>市民の健康データ登録</h2>
    <form method="POST">
        <label>名前:</label>
        <input type="text" name="name" required><br>
        <label>年齢:</label>
        <input type="number" name="age" required><br>
        <label>症状:</label>
        <input type="text" name="symptoms" required><br>
        <label>服薬情報:</label>
        <input type="text" name="medications" required><br>
        <label>緊急連絡先:</label>
        <input type="text" name="emergency_contact" required><br>
        <button type="submit">登録</button>
    </form>
    <a href="{{ url_for('health_list') }}">健康データ一覧</a>
</body>
</html>

早速、これらのプログラムを実行してみしょう。

5000番ポートで健康データを待受けています。(URLは取合えず自前の環境です)

$ python app.py
 * Serving Flask app 'app'
 * Debug mode: on
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit
 * Restarting with watchdog (windowsapi)
 * Debugger is active!
 * Debugger PIN: 822-618-541

ほか各データ登録及び確認はFlaskに紐ずくそれぞれのURLで行います。

看護師登録: http://127.0.0.1:5000/nurse
医療機関登録:http://127.0.0.1:5000/medical_center
看護師一覧: http://127.0.0.1:5000/nurses
健康データ登録: http://127.0.0.1:5000/health
健康データ一覧: http://127.0.0.1:5000/health_records
診断履歴とアクションログ:http://127.0.0.1:5000/logs


実行結果については紙幅の関係で省略しますが、詳細はまもなくリリースするアプリ(サンプル)版でも確認して頂けます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?