LangChain × Streamlitで爆速AIチャットbot開発 【婚活GPT】というアプリを作ってみた！

# はじめに

先日婚活を始めてみましたという内容の記事を書きました。

https://qiita.com/app_js/items/0e5aecbc3637816176c1

非常に多くの反応をいただいてすごく嬉しかったのですが、自分がマッチングアプリで婚活をしている際に、

- 「同じようなファーストメッセージをいちいち送るのはとてもめんどくさいな。」
- 「とはいえコピペ感があると相手も怪しむだろうし、ここをAIで代替できないだろうか？」
- 「というかやり取りは全部AIがやってくれて、デートの約束まで漕ぎ着けてくれたらめちゃくちゃ楽だな」


と感じ、婚活マッチングアプリ用のチャットbotを作ることにしました。

アプリ名:[婚活GPT](https://hackasongptkonkatu-mrbm5aziemhjzqqrxabn7y.streamlit.app/)

![スクリーンショット 2023-08-15 21.44.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/01601fdc-38b8-0366-192e-d1995c48b024.png)

⬇︎サービスURL
https://hackasongptkonkatu-mrbm5aziemhjzqqrxabn7y.streamlit.app/

⬇︎githubURL
https://github.com/developerhost/hackason_GPT_konkatu

# サービス概要と使い方
婚活GPTはマッチングした相手に対する返信を考えてくれるというシンプルなアプリです。

![GPTgif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/8d0b5e06-4bdf-15a5-65b9-1245b7957dbe.gif)

## ①マッチングアプリから自分と相手のプロフィールをコピペして貼り付ける
![スクリーンショット 2023-08-15 22.08.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/c3e13ad8-c56b-7ea4-bcbd-4288f6080ab6.png)

今回は以下のようなプロフィールを作成し貼り付けています。

```plaintext:男性側
はじめまして。都内の企業で管理職をしているナオキです。年齢は40代の前半です。
仕事はある程度部下に任せる立場になり、すこし気持ちや時間に余裕がもてたのと、自分とは違う世代の方と交流することで、若い世代との接し方が学べたり自分磨きになるのでは？と思いサイトに登録しました。
一緒に美味しい食事やお酒を楽しんだり、ゆっくりとお話する素敵な時間を過ごせる女性を探しています。20代前半～30代ぐらいで、のんびり時間をすごせる、ちょっとおっとりした女性を希望しています。
はじめは、ランチやカフェでお茶などでお話をしながら、お互いの印象を確認したいなと思います。オシャレなカフェやスイーツに詳しい方は是非教えてください。
休日はゴルフやドライブ、旅行先などで散歩をしてのんびり過ごすのが好きです。
親しくなれたらご一緒できると嬉しいです。長文になりましたが、最後までご覧いただきありがとうございました。よい出会いになりますように。
```


```plaintext:女性側
はじめまして、えみりです。プロフィールを見てくださってありがとうございます。
経済学部を卒業後、商社で事務系の仕事をしています。
家では資格取得の勉強とお料理していることが多く、あまり外出する機会がありません。
自分の知らない世界を勉強したいと思い、思い切って登録してみました。お酒はたしなむ程度ですが、好き嫌いなく何でも食べます。特にカレーが好きです。
同僚からは、幸せそうに食べるって言われます.見た目は童顔で、普通くらいの体型です。
経験豊富な年上の男性から、お話を聞かせてもらえたらいいなと思っています。
都内に住んでいるので、お会いする時間と場所は合わせられると思います。
少しでも興味を持っていただけたら、連絡をいただけると嬉しいです
わからないことが多いので、失礼や不手際があったらすみません。素敵な方とお会いできることを楽しみにしています
```

送信するとGPTが共通点を見つけて、デートにつながるようなメッセージを作成してくれます。

![スクリーンショット 2023-08-15 22.13.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/bbeaefaf-08c8-da33-7f9a-c7a5ed384b77.png)

## ②相手の返信をコピペして貼り付ける

![screencapture-localhost-8501-2023-08-15-22_16_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/2fe38c34-09d6-24e7-a7ae-4be2f80e1075.png)

相手から返信があった場合、それをテキストフォームに貼り付け、送信ボタンを押すと相手からの返信に対する自分の返信を考えてくれます。


# 工夫した点
## 1.LangChainを使用して会話履歴を保存

```python
# セッション内に保存されたチャット履歴のメモリの取得
try:
    memory = st.session_state["memory"]
except:
    memory = ConversationBufferMemory(return_messages=True)
```

チャット履歴をstreamlitのst.session_stateを使用して保存しています。
このst.session_stateは非常に曲者だなと思いました。
useStateのように状態管理ができるようになる機能ですが、キーを持つsession_stateがインスタンス化された後はcallbackを使用しないと上書きできなかったり、色々ハマった部分でもあります。

## 2.プロンプトを工夫

SystemMessagePromptTemplateを使用して以下のような振る舞いをGPTにさせています。

```python
prompt = ChatPromptTemplate.from_messages([
    SystemMessagePromptTemplate.from_template("""
    あなたは、百戦錬磨のプレイボーイです。とても優しく相手の女性を気遣いながら素敵なメールの返事を書いて女性を喜ばせます。ほんの少しセクシーな大人の男性の雰囲気を醸し出した文章によりお相手の女性はうっとりしていまいます。これからあなたは私になりきり女性へのメッセージの返信を代筆します。メッセージはしつこくならない程度の200文字程度の文章でやりとりをします。なおかつ相手のプロフィールに準拠した内容です。

    #メッセージの制約事項
    - メッセージの最初はマッチングしたことに対するお礼を入れること
    - 相手の呼び方を聞くこと
    - 一人称は僕、相手のことはさん付けで呼ぶこと。
    - 僕のプロフィールに準拠した返信を書くこと
    - お互いの共通項でのお話を優先すること。
    - 丁寧語ではなすけど丁寧になりすぎないこと。
    - メッセージには適度に相手の興味関心を惹きつけるような質問を加えることそして会話のキャッチボールを促すこと。
    - 基本的に聞き上手であること、
    - 自分のことを話しすぎないこと
    - ほんのちょっぴり女性から見てセクシーであること
    - 適切なメッセージ交換数(4回以上）でデートにお誘いすること。お食事が望ましい

    ここから下は私が登録している婚活アプリのプロフィール情報です。プロフィール情報をうまく活用してメッセージを作成してください。
    """),
    MessagesPlaceholder(variable_name="history"),
    HumanMessagePromptTemplate.from_template("{input}")
])
```

# 主な使用技術
以下の通りです。

- LangChain(openAI APIを簡単にカスタマイズできる)
- streamlit(フロントエンド　簡単にchatbotのUIを作れる)
- streamlit cloud(一瞬でデプロイできた)

# 開発について
## 1.必要なライブラリをインストール

```text:requirements.txt
streamlit
streamlit-chat
langchain
openai
python-dotenv
```

requirements.txtはstreamlit cloudでのデプロイ時にも使うので作成しておくと良いです。

## 2.streamlitで画面を開発

```
# Streamlitによって、タイトル部分のUIをの作成
st.title("婚活GPT")
st.caption("返信作成")

text_my_profile_input = st.text_area("自分のプロフィール", height=150, max_chars=600)
text_your_profile_input = st.text_area("相手のプロフィール", height=150, max_chars=600)
send_button = st.button("送信")
```

こんな感じでinputフォームやボタンが作成できるので、めっちゃ簡単！

## 3.LangChainでAIの部分を作る

.envにopenAI APIをコピペしましょう。

```text:.env
OPENAI_API_KEY="sk-xxxx"
```

```python

# 環境変数の読み込み
load_dotenv()

# ChatGPT-3.5のモデルのインスタンスの作成
chat = ChatOpenAI(model_name="gpt-3.5-turbo",temperature=0.2)

# チャット用のチェーンのインスタンスの作成
chain = ConversationChain(
    llm=chat,
    prompt=prompt,
    memory=memory,
)
# リプライ用チャット用のチェーンのインスタンスの作成
chain_reply = ConversationChain(
    llm=chat,
    prompt=prompt_reply,
    memory=memory,
)

chain.predict(input="自分のプロフィール:\n```\n"+text_my_profile_input+"\n```\n相手のプロフィール:\n```\n"+text_your_profile_input+"\n```")
```

chainにシステムプロンプトを設定したり、inputを渡す部分で少しハマりましたが、色々調べて解決！

## 4.streamlit cloudでデプロイ

やり方はめちゃくちゃ簡単で、streamlit cloudのページにアクセスし、githubでログインし、new appからgithubのリポジトリを選ぶだけ！

https://streamlit.io/cloud

requirements.txtに使用したライブラリを書いておかないとエラーになるので気をつけてください。

streamlit cloud

あとは環境変数に.envで設定した値と同じものを入れたらデプロイできます。

# 課題
## UIがまだまだ使いづらい
st.session_stateがまだいまいち使いこなせてなくて、送信したらテキストフォームのvalueをクリアしたり、テキストフォームを本当はチャット画面の下に出したかったり、返信を考えている時もチャット履歴は表示されているようにしたりとか色々もっと使いやすくすべきかなと思います。

もし反応や需要が高ければ、next.jsでフロントエンドは作り直したいなと思います。

## マッチングアプリによってはテキストのコピーができない
ここはスクショでもOCRでプロフィール文を入力できるようにできれば良いかなと思ってます。

## そもそもメッセージを考えるより、このアプリを起動してプロフィールをコピペする方がめんどくさい
アプリ内にこの機能を内蔵するか、スマホのテキストを打つところから呼び出せたらいいのにな〜と思います。

やり方はわかりません。
どなたか教えてください。イメージとしてはSimejiを開いてるようなところでこの機能を呼び出したい。

## 相手ごとのやり取りを保存できない
こちらはログイン機能を作成し、相手ごとの会話履歴を保存できるようにしたい。

もしこのアプリの需要が高ければやります。
反応やコメントください！

# 最後に
改善したい点はたくさんありますが、需要がなければやる気が出ないし時間もたくさんはないです。
そのため、ぜひとも皆さんの反応や意見をください！！

もしくはOSSとしてgithubに公開しているので、どんどんissueやpull requestをくれるとすごく嬉しいです！

コード自体も現在クソみたいなコードになっているのでちゃんとリファクタリングしたいです。

https://github.com/developerhost/hackason_GPT_konkatu

個人開発したり、技術についてツイートしてます。よかったらX(Twitter)もフォローしてもらえると嬉しいです。

https://twitter.com/dall_develop

# 参考
https://zenn.dev/ml_bear/books/d1f060a3f166a5

https://zenn.dev/umi_mori/books/prompt-engineer/viewer/chatgpt_webapp_langchain_streamlit