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

---
AIで健康診断から医療機関への連携、服薬リマインド、訪問看護師の手配、緊急連絡先への通知までをシームレスに管理する
---
:::note info
やりたい事
１．健康診断の結果を入力
２．診断結果を分析し、緊急度などを評価
３．診断結果に応じて医療機関や訪問看護師へ自動通知
４．家族へメールで診断結果とアクションを通知
５．毎日指定時間に服薬リマインドを実行（スケジューリング機能）
６．診断履歴やアクションログも残しておく
:::
以下のライブラリ等が無い場合は事前にインストールしておきます。
```
# pip install flask flask-sqlalchemy flask-wtf wtforms
```
#### まずは以下１のメインとなる以プログラムをサーバとして起動しておきます。またこのプログラムと連携する各データ入力確認画面とその遷移までをざっくりと解説します。
#### １．ヘルスケアメインプログラム
```python
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)

```
#### ２．医療機関登録画面
```python
<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.看護師登録画面
```python
<!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>
```
#### ４.健康状態入力画面
```python
<!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で行います。
 :::note
看護師登録: 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
:::
---
実行結果については紙幅の関係で省略しますが、詳細はまもなくリリースするアプリ（サンプル）版でも確認して頂けます。