ChatGPTのAPIを叩いてみた
昨年から、ChatGPTというツールが話題になっている。ChatGPTはOpen AIという会社が開発したチャット系のAIであり、ChatGPTに何かを質問したり、話しかけたりするとまるで人間と話しているかのように文章を返す人工知能だ。
さまざまな分野で話題となっているChat GPTについて、今回はAPIを叩いてみた。その中でできたこと・苦労したことなどを本記事では述べていきたい。
APIについて
ChatGPTを使ったことがある人なら、あのブラウザ画面を思い浮かべる人も多いだろう。しかしそのブラウザ画面以外でもChatGPTの機能を使えるようにするためにAPIが提供されている。先日gpt-4のAPIが一般ユーザ向けに提供された、といったニュースがあったが今回使用したのはgpt3.5-turboだ。
食べログがChatGPTを使っておすすめの店を検索できるようにしたといったニュースがあったが、それはプラグインとして実装されている。プラグインにはChatGPTで最新のニュースを確認できるようなものや、最近話題のcode interpreterがある。code interpreterはChatGPT上でpythonのコードを実行できる仕組みを実装したものであり、データの分析や画像加工などができるようになっている。今回はそのようなプラグインではなくAPIを叩いてみた。
作成したもの
上記のようなLINEを模したbotを作成してみた。作成には以下のwebサイトが非常に参考になった。
let messageHistory = []; let textData = ''; const inputspace = document.getElementById("chat-input"); async function appendAssistantResponse(assistantMessage) { messageHistory.push({ 'role': 'assistant', 'content': assistantMessage }); } $('#chat-form').on('submit', async function (event) { event.preventDefault(); let userMessage = $('#chat-input').val(); let naturalMessage = htmlentities(userMessage); inputspace.disabled = true; messageHistory.push({ 'role': 'system', 'content': "あなたは友達です" }); messageHistory.push({ 'role': 'user', 'content': userMessage }); const formData = $(this).serialize(); const url = 'https://api.openai.com/v1/chat/completions'; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'your token', }, body: JSON.stringify({ 'model': 'gpt-3.5-turbo', 'stream': true, 'messages': messageHistory, }), }); if (!response.ok) { console.error('Error:', await response.text()); return; } const reader = response.body.getReader(); const textDecoder = new TextDecoder(); let buffer = ''; while (true) { const { value, done } = await reader.read(); if (done) { break; } buffer += textDecoder.decode(value, { stream: true }); while (true) { const newlineIndex = buffer.indexOf('\n'); if (newlineIndex === -1) { break; } const line = buffer.slice(0, newlineIndex); buffer = buffer.slice(newlineIndex + 1); if (line.startsWith('data:')) { if (line.includes('[DONE]')) { $('#chat-history').append('<div class="responseArea"><img class="icon" src="icon.png" alt="icon"> <p class="you">' + textData + '</p></div>'); textData = ''; let removeImg = document.getElementById("thinking"); removeImg.remove(); inputspace.placeholder = "質問を入力してEnterで送信"; inputspace.disabled = false; return; } const jsonData = JSON.parse(line.slice(5)); if (jsonData.choices && jsonData.choices[0].delta && jsonData.choices[0].delta.content) { const assistantMessage = jsonData.choices[0].delta.content; textData += assistantMessage; await appendAssistantResponse(assistantMessage); } } } } });
上記のコードは実装時のコードの一部だ。 考えていたよりもお手軽に実装でき、それも精度の高い反応が返ってくるので、既存のアプリに取り込むなど様々な活用法が思い浮かんだ。特に面白いと感じたのは、’system’というパラメーターだ。ここにはChatGPTに役割を指定でき、うまいこと記述すると友達になってくれたり、カフェの店員になってくれたりと色々な会話をすることができた。指定が曖昧だと変な回答が返ってくることもあったが、それも含めて面白いと感じた。
ChatGPTのトークン
Open AI APIを使ってみる中で苦労した点は、料金に関することだ。Open AI APIの料金体系は従量課金制であり、使った分だけお金が発生する。それ自体は公式の説明にも書いてあるのだが、特に日本語でChat GPTを使用する際に発生するお金を計算することに苦労した。
理由は「トークン」と呼ばれる単位が関係するからだ。googleでトークンと調べてみると、暗号資産関連の話題やプログラミング関連の話題など様々な意味があることがわかる。ChatGPTはOpen AIが開発しているtiktokenと呼ばれる、トークナイザーを用いて文章を一定の規則で分割して管理している。この分割に関する単位をトークンと呼ぶ。このトークン単位で課金が発生する。ソースコード上の文字列を英語の場合、原則1単語が1トークンに値する。このトークンの使用量に応じて料金が発生するらしい。日本語の場合は、ひらがな1文字に対して1トークンの場合が多いようだ。例えば「パソコン」という4文字のトークン量は4トークンだ。しかし中には1文字に対して2トークンの場合もあったり、漢字の場合は1文字に対して3トークンが割り当てられることもあるようだ。「わたし」という3文字に対してトークン量は4トークンとなる。具体的には「わ」のみ2トークンとなる。具体的に、任意の文字列に対してどのくらいのトークンが割り当てられるのかについては、以下の公式サイトを参考にしてみてほしい。
このように英語に比べて日本語は、単語ではなく文字によって料金に変動があるため、料金体系の理解や実装する際にどれくらいお金がかかるのかを予想することが英語に比べて難しいと感じた。
使ってみて
実際に作成してみて、柔軟な対応ができるbotが簡単に作成できることがわかった。今回はLINE風に作成したが、デザインを変更したり役割を変更したりすることによって様々工夫があるように感じた。以下はOpenAIが出したChatGPT関連の論文についてわかりやすく解説してくれている記事だ。