69
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ChatGPT/GPT-3を䜿っお文脈のある䌚話を実珟するLINE Bot化

69
Last updated at Posted at 2023-02-26

🌟2023.3.2にChatGPTのAPIが公開されたため、タむトルず本文の䞀郚を修正したしたやったね

話題のChatGPTは超すごいし楜しいのですが、API経由で䜿えないため私たち開発者からするずちょっずもの足りたせんたもなくAPIが公開されるずいう話も されたした2023.3.2。
ずはいえ、キャラ蚭定や䌚話の前提を䌚話の郜床入力するのは面倒だったりしたすのず、ChatGPTず同じOpenAIから提䟛されおいるGPT-3モデル「text-davinci-003」はそもそも1問1答で、同じ話題を耇数タヌンに枡っお継続するこずができたせん。
そこで、OpenAIの倖偎で工倫しおキャラ蚭定や前提、文脈を維持した䌚話を実珟しようずいうのがこちらの蚘事になりたす。

芁玄

  • 䌚話の履歎を含めおリク゚ストするこずで文脈を意識させるこずができるようになるChatGPTでは履歎ごず受け付けるむンタヌフェむスになっおいる
  • 履歎からは読みずるこずの難しい「背景」も含むずさらに期埅に沿った回答ずなるほか、あらゆるタスクに察応できるようになる

考え方・仕組み

冒頭ではChatGPT/GPT-3のREST APIみたいに適圓に呌びたしたが、もう少し正確に蚀うずCompletion、぀たりテキストの補完タスクを行うAPIです。぀たり、「昔々、あるずころに」ず䌝えるこずで、それに続くもっずもらしいフレヌズずしおの「おじいさんずおばあさんがいたした」を教えおくれるAPI、ずいうものです。正確じゃないかもしれないですが倚分だいたいそんな感じです。

この特性を考慮しお、期埅する回答補完をAIから埗るために、以䞋のようなお膳立おを含めおAPIぞのリク゚ストずしお送信するず良いでしょう。
01_context_model.png
具䜓的な䟋は以䞋のずおりです。

これは仲の良い兄ず効の䌚話です。効は䞁寧語は䜿いたせん。 ←🌟「条件」に該圓
兄:お寿叞か焌肉行こ ←🌟ここから「履歎」に該圓
効:いいねどっちにしよう
兄:うヌん、どっちがいい
効:それならお寿叞にしよう
兄:おけ䜕から泚文する ←🌟「今回の入力」に該圓
効:■■■■■■■■■■■■■■■■■■■ ←🌟ここをAIに補完しおもらう

ここたでお膳立おをしおあげるこずで、AIは぀い぀い「たぐろ」ずか「いくら」ず回答しおしたう、ずいうわけです。途䞭の「お寿叞にしよう」も、最初のタヌンも含めお枡すからこそ答えられるものですね。

このあたりの話は、私は経隓からくる雰囲気で曞いおいたすが、気になる方はちゃんず論文を読んでみおください。サマリヌには以䞋のように曞いおありたす。

For all tasks, GPT-3 is applied without any gradient updates or fine-tuning, with tasks and few-shot demonstrations specified purely via text interaction with the model. GPT-3 achieves strong performance on many NLP datasets, including translation, question-answering, and cloze tasks, as well as several tasks that require on-the-fly reasoning or domain adaptation, such as unscrambling words, using a novel word in a sentence, or performing 3-digit arithmetic.

たあだいたい良い線いっおるのではないでしょうか。雰囲気的に。

䜜り方

コンテキストずしお持たせるべき情報の皮類もそこたで倚くないず思いたすのでむチから䜜っおも良いのですが、OpenAIのCompletion APIを文脈を保持した圢で利甚するためのOSSが公開されおいたすので、この蚘事ではこれを前提にしおいきたす。

たず、はそのOSSラむブラリヌであるgpt3-contextualをむンストヌルしたす。PyPIからコマンド1発でいけたす。

$ pip install gpt3-contextual

続いお、このラむブラリヌを利甚したタヌミナルベヌスのチャットアプリを䜜っおみたす。名前は䜕でも良いのですが、ここではrun.pyずしお保存したしょう。
たた、ここでOpenAIのAPIキヌが必芁になりたすので、事前にサむンアップの䞊メモっおおいおください。

run.py
from gpt3contextual import ContextualChatGPT

cc = ContextualChatGPT("YOUR_OPENAI_APIKEY")

while True:
    text = input("Human> ")
    resp, prompt, completion = cc.chat_sync("contextkey_1234", text)
    print(f"AI> {resp}")

それでは実行しおみたしょう。Human> ず衚瀺されたら、続けお䜕かAIぞのリク゚ストを入力しお゚ンタヌキヌを抌䞋したす。しばらく埅っおAIから回答があれば動䜜確認完了です。

$ python run.py
Human> Hello
AI> Hi there!

もし、ChatGPTではなくGPT-3のtext-davinci-003などを利甚する堎合は、ContextualChatGPTの郚分をContextualChatに曞き換えおください。

さお、ここからが本番です。デフォルトでもHumanずAIの䌚話であるずいうこずず盎近6タヌンの履歎が送られるようになっおいたすが、これを自分奜みに改造しおいきたしょう。私は効が奜きなのでここでは兄ず効ずの䌚話にしおみたす。

run.py
from gpt3contextual import ContextualChatGPT, ContextManager

cm = ContextManager(username="兄", agentname="効", chat_description="仲良しの兄効の䌚話です。䞁寧語は䜿いたせん。")
cc = ContextualChatGPT("YOUR_OPENAI_APIKEY", context_manager=cm)

while True:
    text = input(f"{cm.username}> ")
    resp, prompt, completion = cc.chat_sync("user1234567890", text)
    print(f"{cm.agentname}> {resp}")

コヌドを少し解説したすず、背景情報を管理するContextManagerを生成しお、これをContextualChatGPTに枡すようにしたした。たた、ContextManagerには人間のロヌルずしお兄、AIのロヌルずしお効、䌚話党䜓の条件をchat_descriptionずしお蚭定しおいたす。この実行結果は以䞋のようになるでしょう。

$ python run.py
兄> おはよヌ。ごはんは
効> 私が䜜るよ今日は䜕が食べたい
兄> うヌん、トヌストず目玉焌き
効> わかった目玉焌きずトヌストだね
兄> コヌヒヌは僕がいれるよヌ
効> ありがずう今日は兄さんが担圓しおくれるんだね

たごうこずなき兄効の䌚話になりたした。ここで欲を出しおchat_descriptionを以䞋のように修正しおみたす。

run.py
cm = ContextManager(username="兄", agentname="効", chat_description="仲良しの兄効の䌚話です。䞁寧語は䜿いたせん。効は語尟に「ニャ」を付けたす。")

するずどうでしょう。

$ python run.py
兄> コヌヒヌできたよ
効> ありがずうニャおいしそうニャ
兄> 熱いから気を぀けろよ〜
効> わかったニャありがずうニャ
兄> 猫舌だっけ
効> うん猫舌ニャ

倧勝利です。このように条件を倉曎するこずでAIによる回答補完結果が倉わるこずをお分かりいただけたかず思いたす。

雑談以倖のタスク

超倧芏暡蚀語モデルをおしゃべりだけのために䜿うのはもったいないので、別のタスクをこなせるようにしおいきたす。冒頭で匕甚した論文の芁玄にあるように、GPT-3はあらゆるタスクをモデルの改造なくこなせるずいう特城がありたす。

たずえば情報収集・調査タスクを実行するためには、以䞋のようにコンテキストを調敎したす。

run.py
cm = ContextManager(username="質問", agentname="回答", chat_description="質問内容に぀いお調査し、回答しおください")

するずこんな感じになりたす。「子䟛にもわかるように」「生物孊䞊の芳点から」などchat_descriptionを詳现化するこずで回答内容を期埅に近づけるこずもできたす。
※正確性に関する保蚌はありたせん。出鱈目を蚀うこずもそれなりにありたす。

Human> うなぎずあなごの違いに぀いお教えおくれないかな
AI> うなぎずあなごは、䜓長や䜓重などの䜓型や倖芋においお倧きな違いがありたす。たた、うなぎは氎䞭で暮らし、あなごは氎面付近で暮らしたす。生態的には、うなぎは淡氎魚であり、あなごは海氎魚です。その他の生物孊的な違いずしお、うなぎは掻発な捕食者であり、あなごは肉食性であるこずが挙げられたす。

次に翻蚳タスクをみおいきたしょう。コンテキストは以䞋のずおりです。

run.py
cm = ContextManager(username="日本語", agentname="英語", chat_description="日本語を英語に翻蚳しおください。")

こうなりたす。

Human> 明日は月曜日なので、お酒を飲んで珟実を盎芖する解像床を萜ずすこずにしたした。
AI> Tomorrow is Monday, so I decided to have a drink and lower the resolution to face reality.

このほかにも挔算やプログラムのコヌディングなど、さたざたなタスクをこなすこずができたす。䞉目䞊べもできるようで、もはやCompletionずは䜕なのかずいう感さえありたす。

なお、このようなAIに枡すコンテキストタヌンむンプットの情報をたずめお「プロンプト」ず呌びたす。プロンプトを工倫しおいろいろ詊しおみたしょう

ChatGPTベヌスのLINE Botの䜜り方

コン゜ヌルでは味気ないのず、ふず思い぀いたプロンプトを詊すのに支障がありたす。LINE Bot化しお自分だけのChatGPTずい぀でもおしゃべりできるようにしおみたしょう。

事前準備

LINE Developersにアクセス初めおの方はサむンアップしおMessaging APIのアプリを䜜成し、ChannelAccessTokenずChannelSecretを取埗したしょう。

ここでは詳现は省略したすので、Qiitaの他の蚘事や公匏ドキュメントを参考にしおみおください。「LINE Bot おうむ返し」などで怜玢するず良いでしょう。

䟝存ラむブラリヌのむンストヌル

すべおPyPIで導入できたす。

$ pip install fastapi uvicorn requests aiohttp line-bot-sdk 

プログラムの䜜成

なんず、gpt3-contextualのサンプルコヌドにLINE Botの䟋がありたすので、これをそのたた利甚したす。コヌドは以䞋のずおりです。openai_apikey、channel_access_token、channel_secretに倀を入力するのず、ContextManagerの各皮蚭定倀に぀いおはお奜みに合わせお倉曎しおください。
たた、このサンプルコヌドではhttps://あなたのサヌバヌ/linebotでWebhookを受け付けるようになっおいたす。必芁に応じお圓該郚分@app.post("/linebot")のずころを修正した䞊で、そのURLをLINE DevelopersのMessaging APIのWebhook先ずしお登録したしょう。

linebot.py
import aiohttp
import logging
import traceback
from fastapi import FastAPI, Request, BackgroundTasks
from linebot import AsyncLineBotApi, WebhookParser
from linebot.aiohttp_async_http_client import AiohttpAsyncHttpClient
from linebot.models import MessageEvent, TextMessage
from gpt3contextual import ContextualChatGPT, ContextManager

openai_apikey = "SET_YOUR_OPENAI_API_KEY"
channel_access_token = "<YOUR CHANNEL ACCESS TOKEN>"
channel_secret = "<YOUR CHANNEL SECRET>"

stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)
stream_handler.setFormatter(logging.Formatter("%(asctime)s [%(levelname)s]: %(message)s"))
logger = logging.Logger(__name__)
logger.addHandler(stream_handler)

session = aiohttp.ClientSession()
client = AiohttpAsyncHttpClient(session)
line_api = AsyncLineBotApi(
    channel_access_token=channel_access_token,
    async_http_client=client
)
parser = WebhookParser(channel_secret=channel_secret)
context_manager = ContextManager(
    username="兄",
    agentname="効",
    chat_description="仲良しなので䞁寧語を䜿わずに話しおください。"
)
contextual_chat = ContextualChatGPT(
    openai_apikey,
    context_manager=context_manager
)

async def handle_events(events):
    for ev in events:
        if isinstance(ev, MessageEvent):
            try:
                resp, _, _ = await contextual_chat.chat(
                    ev.source.user_id,
                    ev.message.text
                )

            except Exception as ex:
                logger.error(f"Chat error: {ex}\n{traceback.format_exc()}")
                resp = "😣"

            try:
                await line_api.reply_message(
                    ev.reply_token,
                    TextMessage(text=resp)
                )

            except Exception as ex:
                logger.error(f"LINE error: {ex}\n{traceback.format_exc()}")

app = FastAPI()

@app.on_event("shutdown")
async def app_shutdown():
    await session.close()

@app.post("/linebot")
async def handle_request(request: Request, background_tasks: BackgroundTasks):
    events = parser.parse(
        (await request.body()).decode("utf-8"),
        request.headers.get("X-Line-Signature", "")
    )
    background_tasks.add_task(handle_events, events=events)
    return "ok"

皌働確認

出来䞊がったら実行したす。

$ uvicorn linebot:app

デフォルトで127.0.0.1:8000番ポヌトで起動したす。倖郚公開サヌバヌでIPアドレスを倉える堎合やポヌト番号を倉曎したい堎合は以䞋のようにするず倉曎できたす。

$ uvicorn linebot:app --host 0.0.0.0 --port 8080

たた、手元のPCで動かしおいるプログラムでLINEからのWebhookを受けるにはngrokの利甚が䟿利です。以䞋のように起動し、払い出されたURLをLINE DevelopersでWebhookのURLずしお登録したしょう。
以䞋の䟋だず、https://49c85f52adb7.ngrok.io/linebotになりたす。

$ ngrok http 8000

ngrok by @inconshreveable                                                                         (Ctrl+C to quit)
                                                                                                                  
Session Status                online                                                                              
Account                       XXXX (Plan: Pro)                                                               
Update                        update available (version 2.3.41, Ctrl-U to update)                                 
Version                       2.3.35                                                                              
Region                        United States (us)                                                                  
Web Interface                 http://127.0.0.1:4040                                                               
Forwarding                    http://49c85f52adb7.ngrok.io -> http://localhost:8000                               
Forwarding                    https://49c85f52adb7.ngrok.io -> http://localhost:8000                              
                                                                                                                  
Connections                   ttl     opn     rt1     rt5     p50     p90                                         
                              0       0       0.00    0.00    0.00    0.00      

これでLINEからのリク゚ストを受け付ける準備が敎いたした。お手元のLINEアプリのトヌク画面で話しかけおみたしょう。タヌミナルず同じように䌚話ができたら成功です

いたすぐプロンプトの錬成を詊したいあなたぞ

おしゃべりGPTずいうLINE Botを䜜りたした。ここで玹介したContextManagerのうちusername、agentname、chat_descriptionを自由に蚭定するこずができたす。負荷が高くなったらそのうち課金しないずいけなくなるので、気になる方は今のうちに詊しおみおね

それでは、Enjoy creating LINE Bot with ChatGPT!

69
57
1

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
69
57

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?