Tuneupで問い合わせ対応AIを半日以下で実装する

カシカン( https://casican.me )ではユーザーからの要望や課題を把握するため、問い合わせへのナビゲーションを優先的に表示しています。

その甲斐あって様々なフィードバックが寄せられ、日々の改善に役立てることが出来ています。

一方で、ユーザーが増えるに従って一般的な使い方の質問や、どうしても質問が発生しないようなUI/UXの実現が難しい部分もあり、どうしても問い合わせ対応のコストが上がってしまう問題が発生していました。

また、問い合わせの場合どうしても人が介在するため、ユーザーが気軽に問題を送信できず、そのため重要であっても埋もれてしまう課題がある、という問題もあります。

そこで今回、AIを使った問い合わせ対応のフォームを作成し、ユーザーの声を拾い上げ、対応コストを下げ、ユーザーは即時に回答を得ることの出来る状態を作ることにしました。

まだリリースして日が浅いですが、結果としては

- 実装にかかったのは数時間。想起からリリースまで即日で行えた
- AIの導入で問い合わせの件数が増え、ユーザーの課題把握につながった
- 人が対応する問い合わせの対応コストが下げられた

と言った効果が出ました。

## 利用するサービス

問い合わせ対応のAPIとしてTuneup (https://tuneup.cc) を利用します。

Tuneupは自社（や個人）が所有するデータを登録することで、テキスト生成時に記憶領域としてそのデータを使うことが出来るようになるサービスです。

TuneupではブログのXMLやRSS、CSVでのデータを読み込むことが出来るので、それらを使っていきます。

## データの取り込み

### ブログ記事の取り込み

まずは過去記事を一気に取り込むため、利用しているブログのバックアップ機能を使い、XMLファイルの書き出しを行いました。TuneupではWordpressやbloggerから出力される形式が使えます。

出力されたファイルを新しく作成したコレクションに読み込みます。

![Screenshot_from_2023-06-28_07-26-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946/07fffa99-89bc-228c-eff3-cc881e4ad4ac.png)

過去のブログをすべて取り込んだ後は、新着データの取り込みをRSSで設定しておきます。

![Screenshot_from_2023-06-28_07-26-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946/76c1fc1b-8357-982a-ad88-b71934ef6b1f.png)

これで過去の情報と新着の情報を同期する準備が出来ました。今回の取り込みではブログ記事が110件程度で、今後記事を公開するごとに情報源となるデータは増えていきます。

### 過去の問い合わせ対応の取り込み

カシカンの場合、今までの問い合わせ対応をスプレッドシートで保管していたので、こちらは別のコレクションを作成してCSVで取り込みました。

このデータは内部の個人情報や企業名、メールアドレスなどを匿名化し、一般的な内容として利用できるようにデータを下処理しています。

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946/63dbabf2-a330-4fef-f990-bef3f59e0bb8.png)

![Untitled 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946/ee2db4cd-9709-a286-e265-498a1e339207.png)

ちなみに、普段の問い合わせ対応はブログと同期したコレクションをベースにTuneupで生成しています。コレクション内に既知の情報がある場合はGPT-4でかなり精度の高い回答を作成してくれるので、この時点で既に対応コストが下げられます。

### アクセストークンの取得

Tuneupを外部から利用するため、アクセストークンを作成します。

![Screenshot_from_2023-06-28_07-48-40-edited.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946/7850f12c-9945-1b79-bcc9-784a25f3bbfa.png)

作成したTokenはクライアントから直接利用したいため、アクセス元となるドメインに制限をかけておきます。

### 回答データを貯めるコレクションを作成

TuneupのAPIを叩いて回答を生成すると、新しくドキュメントやフラグメント（個別の質問と回答）が作成されます。

上で作成したブログデータのコレクションや問い合わせ対応のコレクションを回答の生成に使うことも出来ますが、その場合データが混ざってしまうので好ましくありません。

そこで、新しく自動回答生成用のコレクションを作成し、そのコレクションのデータソースとしてブログと過去の問い合わせ対応を指定しました。

![Untitled 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946/93d4d998-034f-7526-f4a9-f7fb06d2ad51.png)

新しいコレクションを作成したら、右上のドロップダウンから他のコレクションを選択して、情報源として利用したいコレクションを指定します。今回のケースでは過去の問い合わせ対応のデータと、ブログのデータを利用します。

これで、このコレクション内で生成する時は、このコレクション内のデータに加えて、別のコレクションからの情報も参照して生成されます。

## AIからの回答実装

コレクションを使ったAIからの回答の実装は非常にシンプルです。

`yarn add @tuneup/client-js` でライブラリを追加して、apiKeyと上で作成したコレクションのIDを紐付けます。

```jsx
import { createClient } from '@tuneup/client-js'

const apiKey = 'your-access-token'
const collectionId = `your-collection-uuid`
const tuneup = createClient(apiKey)

const TuneupInquiry = () => {

  const [answer, setAnswer] = useState('')
  const [question, setQuestion] = useState('')
  const [loading, setLoading] = useState(false)

  const submit = async () => {
    if(!question) return

    setLoading(true)
    await tuneup.ask({
      question,
      collectionId,
      model: 'gpt-3.5-turbo'
      onUpdate: setAnswer,
      onComplete: (last)=> {
        setAnswer(last + t('inquiry.ai.thanks'))
        setLoading(false)
      },
    })
  }
  ...
}
```

基本的には `tuneup.ask` を呼び出すだけで回答の生成と表示を行うことが出来ます。この例はReactですが、vueなどでも利用できると思います。

## 回答データの確認と改善

AIが生成する回答は完全ではなく、誤った情報を含む場合があります。特に過去のデータに登録のない質問が来た場合など、知らないことに対する回答の精度は著しく落ちます。

Tuneupでは生成された回答はそのコレクション内のドキュメントに蓄積されていくため、回答の確認と改善を行うことが出来ます。

一例として、この回答を見てみましょう。

### 質問

書籍QRコード発行

### 回答

> 図書館や書店で利用されているように、力シカンでも貸し出しする書籍に専用のQRコードを貼り付けることができます。これにより、カシカン上でその書籍を借りる際の手間を省くことができます。
書籍のORコードを発行するには、まずは書籍をカシカンの「本棚」に登録する必要があります。本棚に登録された 書籍の詳細画面にある「QRコードを出力する」ボタンをクリックすると、QRコードが画面に表示されます。「ダ ウンロード」ボタンをクリックして、PNG形式で保存すれば、QRコードをあとでプリントアウトすることができます。
QRコードをプリントアウトしてからは、切り取って書籍に貼り付けるだけで、QRコードを使った貸出しや予約に対応した書籍として利用できるようになります。QRコードは、書籍の背表紙や裏表紙に貼り付けるのが一般的ですが、本のサイズに合わせて使い勝手の良い貼り方を探してみましょう。
> 

こちらの回答の場合、前提やあとがきは問題ないものの、肝心のQRコード発行の方法が微妙に間違えています。カシカンには「本棚」という機能はありません。そこで、この回答を編集します。

### 回答

> 図書館や書店で利用されているように、カシカンでも貸し出しする書籍に専用のQRコードを貼り付けることができます。これにより、カシカン上でその書籍を借りる際の手間を省くことができます。
> 
> 
> 書籍のQRコードを発行するには、まずは書籍をカシカンに登録する必要があります。登録された書籍の詳細画面にあるシェアボタンをクリックすると、QRコードが画面に表示されます。PNG形式で保存すれば、QRコードをあとでプリントアウトすることができます。
> 
> 一度に複数のQRコードを発行したい場合は、グループ設定画面から一括で出力することが出来ます。
> QRコードの作成方法に関する詳しい情報はブログにも掲載していますので、こちらをご参照下さい。
> [https://casican.blogspot.com/2021/03/qr.html](https://casican.blogspot.com/2021/03/qr.html)
> 
> QRコードをプリントアウトしてからは、切り取って書籍に貼り付けるだけで、QRコードを使った貸出しや予約に対応した書籍として利用できるようになります。QRコードは、書籍の背表紙や裏表紙に貼り付けるのが一般的ですが、本のサイズに合わせて使い勝手の良い貼り方を探してみましょう。
> 

回答を編集後「更新」を押すことで、データの利用状態が「AIデータ利用」に変わります。この状態のデータは以降の回答生成時に使用されるようになるため、今後の回答の精度向上が期待できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946/4f96b101-fa3f-2f45-2ae9-5007d77a30bf.png)

データの件数が少ないうちは、多少コストはかかりますがGPT-4を利用して回答の品質を上げ、データが溜まったらGPT-3に切り替える、というのも良いと思います。

### プロンプトのテンプレート設定

上の回答では、過去の情報に存在しない内容を生成してしまいました。テキスト生成AIは、デフォルトでは未知の内容でも知っているかのような文章を生成する傾向にあります。

このままではユーザーに対し、適当な回答を返してしまいますので、テンプレートのプロンプトを編集して、こちらの期待に沿った出力を行うように調整しましょう。

![Untitled 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946/f9cc3c06-862a-ce5a-38ba-00a7ed45e8ea.png)

今回はテンプレートを以下の形で設定してみました。

```markdown
過去の情報
{context}
-----
あなたはユーザーサポートの担当者です。
今回ユーザーからの問い合わせで「{input}」という質問が入りました。この質問への回答を書いて下さい。

- 過去の情報だけを参考にし、カシカンに無関係の内容や一般的な情報は記載しないで下さい
- 過去の情報に記載がない場合「大変申し訳ございません、情報が見つからないため、お答えできません。問い合わせフォームよりご連絡下さい」と回答して下さい
```

問い合わせ対応の場合はブログ記事などとは違い、ドキュメントのタイトル（`doc.title`）は不要なので入れていません。

テンプレートを編集した上で、改めて回答を生成してみます。

### 質問

時間単位で貸出物を管理したい

### 回答

> 「時間単位で貸出物を管理したい」場合、貸出物設定画面から「時間貸し可能」を選択することで、時間単位での予約が可能になります。 詳しい設定方法は、以下の手順をご確認ください。
> 
> 1. カシカンのアカウントにログインし、貸出物の編集画面にアクセスしてください。
> 2. 貸出物の設定から「時間貸し可能」を選択して保存して下さい。
> 
> これで、予約が時間単位で行われるようになります。
> ご不明な点がございましたら、お気軽にお問い合わせください。
> 

明らかに前回の回答とは異なり、ユーザーサポート感のある回答が生成できています。生成される回答の品質を確認しながら、プロンプトの改善を進めることが可能です。

## まとめ

この記事ではTuneupを使って問い合わせ対応AIを簡単に&高速に実装しました。OpenAI等のAPIやPineconeと言ったVectorDBを直接利用する場合はサーバーの実装と維持が必須になりますが、Tuneupではサーバーサイドの実装を不要としていることで実装から検証まで高速に回すことが出来ます。

普段からデータを貯めたり、取り込みやすい形式で持っていると何かと役立つことが分かったので、これからもデータを貯めて増やして行きたいと思います。

フォームの実装自体は数時間で終わるのがメリットですが、回答の精度向上やプロンプトの編集など、Tuneupの改善が必要な点も見えてきたので、この辺りは順次改善予定です。（プロンプトのテンプレート利用は記事公開前に実装し、ブログ内に追記しました。）

改善予定のポイント

- プロンプトのテンプレート利用
- 回答時のTemperature, Frequency penaltyの調整
- 回答の生成速度

また、今回はコストを抑えるためGPT-3.5-turboを使っていますが、こちらは利用できるコンテキストが小さいため、近日GPT-3.5-16kを導入予定です。

Tuneupは月額料金や初期費用もなく使った分だけ支払う方式なので、気軽に検証利用が可能です。

みなさんも是非AIを使った問い合わせ対応を実装してみて下さい。

Tuneup: https://tuneup.cc
カシカン: https://casican.me