医療系チャットボットの作成（Python×ChatGPT）

皆さん、こんにちは。東京都でクリニックを開業している医師の森　維久郎と申します。

今日はこれから何回かに分けて、医療現場での課題を、Chat GPTを使って解決するために制作したプロダクトの開発過程を共有したいと思います。

私自身はプログラマーではなく、プログラミングについては少し学んだ程度なので、この記事はプログラミングに興味がある医療現場の方々や、医療現場の課題について理解を深めたいプログラマーの方々向けになっています。

あくまでも、現場の医師として作り上げたものなので、改善点などがあればぜひ教えてください。



## 概要

●長期目標：データーベース（PDF、textファイル、Googleドキュメントなど）を参照にユーザーの質問に答えるQ&Aチャットボットを作成する。

●今回の記事の内容：Google Colabを使用してテキストファイル（text.txt）からデータベースを作成し、ユーザーの質問に答えるQ&Aチャットボットを作成する

●使う機能：Googleコラボ、ChatGPT

## ポイント

今回のポイントは、「ベクトル化」という概念について理解を深めることです。

ベクトル化についてchatGPTに問い合わせると、次のような回答が返ってきます。

:::note info
ベクトル化とは、一般的に、データをベクトル（方向と大きさを持つ量）として表現することを指します。ベクトル化により、大量のデータを効率的に扱うことが可能になります。また、ベクトル化は機械学習やAIの分野で頻繁に使用され、データをモデルに入力する前に必要な前処理となることが多いです。

特に自然言語処理においては、文章や単語をベクトル化することで、テキストデータに対する計算や比較、理解が容易になります。例えば、単語をベクトル化することで、単語間の意味的な距離を計算できるようになり、それによって文章の意味を解析することが可能となります。
:::

いまいちよくわからないですねww

簡単に言うと、ベクトル化はQ&Aの際、ユーザーからの質問とデータベースの内容を比較するとき、その効率を良くする作業のことと理解していただくと良いでしょう。それすら分かりづらいと感じるかもしれません。もし興味がある方は、以下の動画をご参照ください。

https://www.youtube.com/watch?v=RKCFi3nqVFw

## 今日やることの流れ

①データベースのベクトル化: 次に、データベースの各エントリ（テキスト行）をベクトル化します。これは、OpenAIのEmbedding APIを使用して行います。ベクトル化とは、テキストを数値のリスト（ベクトル）に変換することを意味します。このベクトルは、元のテキストの意味的な情報を保持しています。

②ユーザーの質問のベクトル化: ユーザーから質問が来たら、その質問もベクトル化します。これもOpenAIのEmbedding APIを使用します。

③最も類似した回答の検索: ユーザーの質問がベクトル化されたら、データベース内のベクトルと比較して、最も類似性の高いエントリ（回答）を見つけます。これは、各データベースエントリのベクトルと質問のベクトルとの間の類似性（通常はコサイン類似性）を計算することで行います。

④回答の提供: 最も類似性の高いデータベースエントリが見つかったら、そのエントリ（テキスト）をユーザーに回答として提供します。

## 具体的なコード

### ライブラリのインストール
以下のコードをGoogle Colabのセルに入力し、実行します。

```
!pip install openai
```
このコードは、Pythonのパッケージ管理システムであるpipを使用して、openaiライブラリをインストールします。

### テキストファイルをアップロード
google colaboにtext.txtをアップロードします。尚、今回はtext.txtの内容を「CKD治療におけるSGLT2阻害薬の適正使用に関するrecommendation」の一部を抜粋して作りました。

https://jsn.or.jp/medic/newstopics/formember/ckdsglt2recommendation.php
### テキストファイルの読み込み
以下のコードを新しいセルに入力し、実行します。
```
with open('text.txt', 'r') as file:
    database = file.read().splitlines()
```
このコードは、Pythonの組み込み関数openを使用してテキストファイルを読み込みます。'r'は読み取りモードを意味します。file.read().splitlines()は、ファイルの内容を読み取り、各行をリストの要素として保存します。このリストがデータベースとなります。

### データベースの各エントリをベクトル化

この作業は、OpenAIのEmbedding APIを使用して行います。

OpenAIのAPIキーを設定します。このキーは、OpenAIのウェブサイトから取得できます。以下のコードを新しいセルに入力し、実行します。
```
import openai
# OpenAIのAPIキーを設定します
openai.api_key = 'your-api-key'
```
次に、テキストをベクトル化する関数を定義します。以下のコードを新しいセルに入力し、実行します。
```
def get_embedding(text, model="text-embedding-ada-002"):
    response = openai.Embedding.create(
        model=model,
        input=text
    )
    return response["data"][0]["embedding"]
```
この関数get_embeddingは、与えられたテキストをベクトル化します。具体的には、OpenAIのEmbedding APIを呼び出し、テキストのembedding（ベクトル）を取得します。

この関数を使用してデータベースの各エントリをベクトル化します。以下のコードを新しいセルに入力し、実行します。
```
database_embeddings = [get_embedding(text) for text in database]
```
このコードは、Pythonのリスト内包表記を使用して、データベースの各エントリに対してget_embedding関数を呼び出し、結果のベクトルをリストに保存します。

### ユーザーの質問をベクトル化
OpenAIのEmbedding APIを使用します。

まず、ユーザーからの質問を定義します。以下のコードを新しいセルに入力し、実行します。
```
question = "Your question here"
#今回は「SGLT2阻害薬は糖尿病でなくても使ってよい？」という内容にしました。
```
次に、この質問をベクトル化します。以下のコードを新しいセルに入力し、実行します。
```
question_embedding = get_embedding(question)
```
### ユーザーからの質問とデーターベースの類似性の計算の準備
ここらへんからカオスになりますがとりあえず動けばよいので気にしないでください、へ～で良いと思います。

次に、最も類似した回答をデータベースから検索します。これは、各データベースエントリのベクトルと質問のベクトルとの間の類似性（通常はコサイン類似性）を計算することで行います。

まず、コサイン類似性を計算する関数を定義します。以下のコードを新しいセルに入力し、実行します。
```
import numpy as np

def cosine_similarity(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
```
この関数cosine_similarityは、2つのベクトルのコサイン類似性を計算します。コサイン類似性は、-1から1までの値を取り、1に近いほど2つのベクトルが類似していることを意味します。

### ユーザーからの質問とデーターベースの類似性の計算の実行
質問のベクトルとデータベースの各エントリのベクトルとの間の類似性を計算し、最も類似性の高いエントリを見つけます。以下のコードを新しいセルに入力し、実行します。
```
similarities = [cosine_similarity(question_embedding, db_embedding) for db_embedding in database_embeddings]
best_match_index = np.argmax(similarities)
```
このコードは、リスト内包表記を使用して、質問のベクトルとデータベースの各エントリのベクトルとの間の類似性を計算し、結果をリストに保存します。次に、np.argmax関数を使用して、最も類似性の高いエントリのインデックスを見つけます。

### 最も類似性の高いデータベースエントリをユーザーに回答として提供
以下のコードを新しいセルに入力し、実行します。
```
answer = database[best_match_index]
print(answer)
```

Google Colabを使用してテキストファイルからデータベースを作成し、ユーザーの質問に答えるQ&Aチャットボットを作成する手順です。このプロセス全体は、ユーザーの質問に対して最も適切な回答をデータベースから見つけるためのものです。ベクトル化は、テキストの意味的な情報を数値の形で捉え、それに基づいてテキスト間の類似性を計算するための手段です。
## 実行してみた
綺麗にできました！綺麗に期待通りの返答が返ってきました。
```
質問：SGLT2阻害薬は糖尿病でなくても使ってよい？

回答：SGLT2阻害薬は、糖尿病合併・非合併にかかわらず、慢性腎臓病(CKD)患者において腎保護効果を期待するため、リスクとベネフィットを十分に勘案して積極的に使用を検討する。
```

## 次回の記事
今回はtextファイルからやってみました。次回はPDFから読み取るコードを作成したいと思います。
https://qiita.com/ikuro_mori/items/1bb79cc54c01902cb1c8?fbclid=IwAR0ZvopL2Tt5ClSIftDHO7M7jAyQkRyYJnoqwAqU5fJ-BJ54kd0nq0ckQDI