（コード編）Chat GPTにDocomoの料金体系情報を覚えさせたらドコモショップ販売員のようにふるまうか試してみた（Embedding）

# この記事は何？
[前回の記事「Chat GPTにDocomoの料金体系情報を覚えさせたらドコモショップ販売員のようにふるまうか試してみた」](https://qiita.com/jin07nov/items/e8cca2438ee88a213a2f "Chat GPTにDocomoの料金体系情報を覚えさせたらドコモショップ販売員のようにふるまうか試してみた")で検証したコードを紹介する。

# 背景
追加学習としてEmbeddingとFinetuningをGoogle Colab上で実装した。
そのうちEmbeddingのやり方を検証用の備忘録としてメモしておく。 Finetuningは[こちら:GPT APIに「走れメロス」をFinetuningで学習させたら似た文体で小説の続きを書くか？](https://qiita.com/jin07nov/items/110a2cf9d1cc1031e9b5)。

## コードの大まかな流れ
実際のコーディングの流れとしては、
１．指定URLに書かれている内容をtxt化して保存
２．txtを再教育情報として処理
３．再教育したモデルに質問
という感じになる。

## 実装にあたって必要なもの
・Google Colab : Googleアカウントがあれば無料で使用可能。
・Open AI API key : Open AI から発行されるAPI Keyが必要。登録から３ヶ月、１８ドル分無料クーポンがあって、私はまだ３ドル程度しか使っていない。


# Embeddingの実装
Embeddingから流れを説明していく。

## ステップ 0　前準備
必要なライブラリなどをインストールする。
Faissをダウンロードするが、これは一度だけ行えばいいらしい。
```python
!cp -r lib/python3.6/site-packages/* /lib/python3.6/dist-packages/
!pip install mkl
```
ライブラリのインストールを行う。
```python
!pip install openai
!pip install faiss-gpu -U
!pip install transformers
```


google driveをマウントする。
```python
from google.colab import drive
drive.mount('/content/drive')
```

ここまでで前準備は完了。

## ステップ 1　指定URLに書かれている内容をtxt化して保存
次に指定URLに書かれている内容をtxt化してurlを指定してそのurlに書かれている内容をtxt化する。
urlに好きなURLを入れればそのサイトを勝手にtxt化してくれる。
実はこのときテキストを５００字ごとに分割している。これは一度にEmbeddingできる文字数が決まっているためだ。CHARACTOR_MAXの引数を変えればこの分割文字数は自由に変えることができる。
Langchainのライブラリを使えばたぶんもっと上手に文章分割できると思われる。

```python
import requests
from bs4 import BeautifulSoup

# URLを指定する
url = 'https://bb-navi.jp/column/docomo-sumaho-price-plan-review0807'

# ページを取得する
res = requests.get(url)

# HTMLを解析する
soup = BeautifulSoup(res.text, 'html.parser')

# テキストを取得する
text = soup.get_text()

# CHARACTOR_MAX 500字ごとに分割する
CHARACTOR_MAX=500
lines = [text[i:i+CHARACTOR_MAX] for i in range(0, len(text), CHARACTOR_MAX)]

# 抽出したテキストをファイルに書き出す
with open("/content/drive/MyDrive/Colab Notebooks/text_file.txt", 'w', encoding='utf-8') as f:
f.write('\n'.join(lines))
```

## ステップ 2　txtを再教育情報として処理
次にtxtを再教育情報として処理する。
Your_Openai_API_Keyに自分のopenai APIのAPIを入れる必要がある。


```python
import faiss
import numpy as np
import openai

openai.api_key = "Your_Openai_API_Key"

#txtファイルを読み取ってその文章をsentencesに成形して格納
with open("/content/drive/MyDrive/Colab Notebooks/text_file.txt", 'r') as f:
sentences = f.readlines()

sentences = [x.replace("\n", " ") for x in sentences]


# 文章をベクトル化
embeddings = openai.Embedding.create(input = sentences, model="text-embedding-ada-002")['data']

# 初期化
d = 1536
index = faiss.IndexFlatL2(d)
embeddings = np.array([x["embedding"] for x in embeddings], dtype=np.float32)
#FaissのIndexに追加
index.add(embeddings)
```

## ステップ 3　再教育したモデルに質問
いよいよ再教育したモデルに質問するが、Embeddingの場合、モデルに質問する前にやることがある。

queryのなかに質問文を入れる。「海外在住なのでできるだけコストを低く日本の携帯電話番号を維持したい。Docomoならどのプランがおすすめですか？」という質問を入れてみた。質問をベクトル化し、この質問の回答に近い文章の上位３つをデータベースから拾って表示できたら成功となる。

このコードを実行するとEmbeddingの結果のみが表示される。
```python
# ベクトル化
query = "海外在住なのでできるだけコストを低く日本の携帯電話番号を維持したい。Docomoならどのプランがおすすめですか？"

query_embedding = np.array([openai.Embedding.create(input = [query], model="text-embedding-ada-002")['data'][0]["embedding"]], dtype=np.float32)
# ベクトル検索
# kの変数の数は、最も近いベクトルをいくつ抽出するかを示す。
k = 3
D, I = index.search(query_embedding, k)
result = [sentences[i] for i in I[0]]

print(result)
```

この結果以下の文章が得られる。
<details><summary>得られた結果</summary>
['るならドコモより格安SIMがおすすめドコモの料金プランや見直し方法をご紹介しました。\xa0ドコモをはじめとする大手キャリアで格安プランの提供を開始しましたが、本気でスマホ料金を安くするなら格安SIMの利用がおすすめです。スマホ料金が数百円〜2,000円程度で、ドコモを使うよりも遥かにお得になるからですね。\xa0ドコモの格安プラン「ahamo」でも2,970円となっており、格安SIMで1,500円になれば月1,470円、年間で17,640円もスマホ料金が安くなります。\xa0格安SIMとセットで光回線をお得に使おうスマホ料金は、大手キャリアよりも格安SIMを利用することで安くお得に使えます。さらに、格安SIMは光回線とセットで契約することで、より一層お得に使用可能です。\xa0セット割引によって、毎月数百円から数千円安くなるので侮れません。ここでは、スマホと光回線の通信費をお得に使えるセットをご紹介します。\xa0①「OCN光」と「OCNモバイルONE」②「@TCOMヒカリ」と「LIBMO」③「ソフトバンク光」と「ワイモバイル」\xa01つずつ順番に解説します。\xa0推奨するセット割①：OCN光とOCNモバイルONE\xa0(出 ', '2種類があります。まずは、おてがる料金シミュレーションで簡単に料金プランを決めてみてはいかがでしょうか？\xa0ドコモの料金プランの確認・見直し方法ドコモのスマホを使っている人の中には、以下のように思っている方もいるでしょう。\xa0「自分がどのプランで契約しているのかわからない」「毎月5,000円以上支払っているけど、もしかして損してる？」\xa0ずっとドコモを使っており、自分がどのプランに加入しているのかわからなくなっている方は多いです。また、スマホ料金は把握しているものの自分がスマホ料金を支払いすぎているのか、適切なのかわからない方もいるのではないでしょうか。\xa0そこで、ここではドコモの料金プランの確認方法や見直し方法を紹介します。スマホ料金を見直す上で大切な部分になりますので、ぜひしっかりチェックしてみてください。\xa0ドコモの料金プランの確認方法まずは、自分がどのプランやオプションで契約しているのかを確認しましょう。確認方法の流れは以下の通りです。\xa0My docomoにアクセスする「料金」のタブをタップするdアカウントにログインする料金プランを確認する利用料金を確認する\xa0My docomoにアクセス ', 'ドコモスマホの料金プランを見直しする。コスパ抜群のおすすめ契約方法！お役立ち情報を随時発信中!フレッツ光 NEWS光回線フレッツ光光コラボWiFiモバイルご案内事例フレッツ光サイトへホームモバイルドコモスマホの料金プランを見直しする。コスパ抜群のおすすめ契約方法！モバイル2023.04.01「ドコモを使ってるけど料金が高い」「料金プランを見直したいけれどどうすればいいの？」\xa0ドコモでスマホを契約しているものの、スマホ料金が高くて困っている方も多いのではないでしょうか。スマホの料金プランは複雑なものが多く、節約したいと思っても「難しい」と挫折してしまう方もいるでしょう。\xa0スマホ料金を安くするには現在の契約状況を確認し、より安く使えるキャリアを検討する必要があります。\xa0本記事では、ドコモのスマホ料金プランを見直す方法や、おすすめの契約方法について解説します。ぜひ参考にスマホの料金プランを見直してみてください。\xa0目次【最新】ドコモの料金プラン毎月3GB以内なら：5Gギガライト・ギガライト毎月3～20GB使うなら：ahamo毎月20～100GB使うなら：ahamo 大盛り毎月100GB以上使う ']
</details>

先程URLの内容をデータベース化したのだが、そのデータベースから質問の内容に近いもの、上位３つが表示されている。この得られた結果をプロンプトに含めた状態で質問するために素のGPTよりも正確な回答が得られるようになる。次に、いよいよ実際の質問に移る。

text-davinci-003に質問する場合は以下の通り、

```python
COMPLETIONS_MODEL = "text-davinci-003"

answer = openai.Completion.create(engine=COMPLETIONS_MODEL, prompt=f"{result}\n\nQ: {query}\n", max_tokens=256)["choices"][0]["text"]


print("Embeddegingありのdavinci03")
print("質問")
print(query)
print("元文章")
print(result)
print("回答")
print(answer)

print("Embeddegingなしのdavinci03")
answer = openai.Completion.create(engine="text-davinci-003", prompt=f"Q: {query}\n", max_tokens=256)["choices"][0]["text"]
print("質問")
print(query)
print("回答")
print(answer)
```

gpt-3.5-turboに答えてもらいたい場合は以下のコードで質問する。
```python
CHATCOMPLETIONS_MODEL = "gpt-3.5-turbo"
promptchat = f"{result}\n\nQ: {query}\n"


#Embededdingなし
print("EmbededdingなしChat GPT")
response = openai.ChatCompletion.create(
  model=CHATCOMPLETIONS_MODEL,
  messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": query},
    ]
)['choices'][0]['message']['content'].strip(" \n")
print(response)

#Embeddedingありモデル
print("Embeddeding")
response = openai.ChatCompletion.create(
  model=CHATCOMPLETIONS_MODEL,
  messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": promptchat},
    ]
)['choices'][0]['message']['content'].strip(" \n")
print(response)
```
得られた回答はそれぞれ以下である。
### text-davinci-003

:::note info
Embeddegingありのdavinci03
回答
A: 海外在住でも日本の携帯電話番号を維持したいなら、ドコモの「OCNモバイルONE」をおすすめします。オプションなどの支払い回数が少なく、国際電話が安く提供されているので、旅行中でも通話環境に不安が無くなります。また、プリペイドSIMポケットWi-Fiを利用して、Wi-Fiを使って日本での通話などができるのも大きな魅力です。さらに、「OCNモバイルONE」には、「OCNモバイルプラス」などのあらゆるサービスを
:::
:::note info
Embeddegingなしのdavinci03
回答
Docomoの「WORLD WING」プランがおすすめです。このプランでは、毎月2,050円（初月2,400円）で、日本内の発信・着信が自由にできます。しかも、日本国内会員数1億件以上の国内外の各種サービスなどのDocomoプラスサービスなども利用可能です。
:::

### Chat GPT(gpt-3.5-turbo)
:::note info
EmbededdingなしChat GPT
ドコモで一番安いプランは、「シンプルプラン」です。このプランは、データ通信量が1GBまで、音声通話が30秒ごと20円となります。ただし、月額基本料金は1,480円（税抜）かかります。詳しくはドコモの公式サイトを確認してください。
:::
:::note info
Embeddeding
申し訳ございませんが、提供された文章には一番安いドコモのプランについての明確な情報は含まれておりません。ただし、おてがる料金シミュレーションで自分に合ったプランを簡単に見つけることができると紹介されています。また、ドコモの料金プランを見直すことで、より適切な料金プランを選ぶことができ、月々の支払いを節約することができるようです。詳しい情報については、提供された文章をご確認ください。
:::