Watson Assistantの更新をPythonから行う(Watson Assistant API v1を使用)

# はじめに
ここではPythonを用いてAPI経由で、IBM Cloud Watson Assistantの情報を更新する方法をメモとしてまとめておきたいと思います。(今回はSkillのNameとdescription, Intentを更新してみたいと思います。)


## Watson Assistantの構成
今回、Watson Assistantを触るのは初めてだったので、まずはじめに構成からおさらいします。

Watson Assistantを使ってみて、わかったこととしては、構成として
大きく分けてIntent, Dialog, Entityという3つの要素があるようです。

Intent: 質問の意図を定義するところ。
　oooな質問がきたら、Aのグループに。
　xxxな質問がきたら、Bのグループというように質問とそのグループを定義しているもの。

Dialog: 主に回答と会話の流れを定義しているところ。
　このグループの質問がきたら、この回答を返すと定義するところ。

Entity: 
　同義語などを定義。ユーザーの入力を情報を表す。
　公式サイトには以下と記載されていました。
> ユーザーが発言した入力テキストから抽出された意味付けされたキーワードが Entity です。
入力テキストから抽出された Entity は、ユーザーの「目的」の対象物を示したりします。

[公式サイト Watson Assistant (Watson Conversation) の使い方を学ぶ](https://developer.ibm.com/jp/technologies/conversation/tutorials/cc-watson-chatbot-conversation/) にWatson Assistantの使い方や構成についてわかりやすい記事があったので、これを見れば大まかにわかるはずです。

## Watson Assistant APIを呼んでみる
### v1, v2のAPI
現在Watson APIにはv1, v2と2つのAPIが存在するようです。
違いについては[こちら](https://qiita.com/ishida330/items/6dcdb664e4724e27764d)のQiitaにまとまっていたので参考にできるかと思いました。

各バージョンで使用できるメソッドは[公式サイト](https://cloud.ibm.com/docs/assistant-data?topic=assistant-data-api-methods)にまとめられていました。

今回は主にワークスペースの更新を行いたいためここではv1を使いたいと思います。

### Skillの更新

SkillはWatson Assistant上のskillsタブを開いた際のこの一つ一つのSkillのことです。
Skillの中にはさきほどざっくり説明した、Intent, Dialog, Entityなど会話に必要な要素を定めることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227613/53cfd853-194c-554f-f29c-982cd6f32c4b.png)

#### API経由でSkillのNameとDescriptionを更新する

今回は試しに、一番左の"テスト用"というSkillのスキル名(Name)とスキルの説明(description)をAPIから変更してみたいと思います。
まず現在の設定を確認しましょう。

Skillの右上にあるRenameボタンを押すと、現在のスキル名(Name)とスキルの説明(description)を確認することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227613/b71c79a1-8aa4-2cf4-72b4-8ec09ad09ff4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227613/48e33242-daf5-67b7-b90a-601af6bfded9.png)
ここではNameが"テスト用"、Descriptionが"テスト用のスキルです。"となってることが確認できました。

公式には各言語でのAPIを呼ぶためのコードは掲載されています。
今回は、Pythonから呼んでみます。

まず、ibm-watsonのSDKを環境にインストールする必要があります。
以下を実行してください。

```
$ pip install ibm-watson
```

更新するためのコードは以下になります。こちらは公式にも書いてあるものと同じになります。

(Skillという言葉とworkspaceという言葉がどちらも使われていますが、
以前はSkillではなくworkspaceという名前がついていて、v1のAPIを使用しているので
更新するための関数は公式の方で変更していないのかな・・・?と勝手におもっています。
ここでは公式が定めたAPIの関数以外はSkillという表記にします。)

```py:update_skill.py

import json
from ibm_watson import AssistantV1
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

authenticator = IAMAuthenticator('{apikey}')
assistant = AssistantV1(
    version='2020-04-01',
    authenticator = authenticator
)

assistant.set_service_url('{url}')

response=assistant.update_workspace(
    workspace_id='{skill_id}',
    name='テスト用スキルの更新テスト', # 更新したいスキル名にすること
    description='テスト用スキルの更新テスト用です。' # 変更したいスキルの説明文章にすること
).get_result()

print(json.dumps(response, indent=2))

```

またここに書かれている認証情報がのWatson Assistantのインスタンスのどこと対応しているかを解説します。
まずSkillの右上のView API Detailsを押してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227613/babaf4a2-31aa-479e-5265-ff56a9cea639.png)
このようなSkillの時詳細情報画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227613/21ea9d8b-d3bf-2adf-d068-91ee238f38dc.png)
コードとの対応は以下になります。
Skill ID: スキルを識別するためのIDです。
　-> コードの {skill_id}に対応します。
Legacy v1 workspace URL: Watson APIを使用する際のエンドポイントです。 
"https://api.地域名.assistant.watson.cloud.ibm.com" までを使用します。
　-> コードの{url}に対応します。~.comまでを記載してください。
API key: Watson APIを使用する際の認証情報です。
　-> {apikey}に対応します。

コードの中のnameとdescriptionにはそれぞれ、
更新したいテキストを記載してください。


更新後・・・再び先ほどのスキルのRenameを押して、以下の画面を開いて、
NameとDescriptionがさきほどコードの中で設定したテキストになっていれば更新成功です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227613/8c52bfb6-af25-b8a0-fdd7-44c124c8514e.png)

#### API経由でSkillのIntentを更新する

先ほどは一番わかりやすいNameとDescriptionの更新をやってみました。
Intentの更新についても軽く書いておきたいと思います。

今回行うのはSkill更新の際に、いくつかIntentを作成し、そのIntentに紐づくテキストを定義することです。
例えば、"greeting"というIntentを作成し、そのカテゴリに分類したいテキスト、"おはよう"・"こんにちは"・"おやすみ"を定義するといった感じです。

”カテゴリに分類したいテキスト”というのはWatson Assistant画面上でいうと、特定のIntentに紐づく
User Exampleの部分に対応します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227613/eab2260f-fa51-7ae4-f751-5e5ea339a442.png)
ではIntentの更新をコードから行ってみます。

Intent名がgreetingで、
User examplesが"グッとモーニング、ハロー"をデータとしてセットし、
update_workspaceの引数にIntentをセットします。他のコードは先ほどと同様になります。

```py:update_skill.py

import json
from ibm_watson import AssistantV1
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

authenticator = IAMAuthenticator('{apikey}')
assistant = AssistantV1(
    version='2020-04-01',
    authenticator = authenticator
)

assistant.set_service_url('{url}')

# intentのデータは以下のように書く。今回はgreetingというintentを作成する
let intents_list = [{
     "intent": greeting,
     "examples": [{"text": "グットモーニング"}, {"text": "ハロー"}]
}]

response=assistant.update_workspace(
     workspace_id='{skill_id}',
     intents = intents_list,
).get_result()

print(json.dumps(response, indent=2))

```

実行し、Watson　Assistantの画面でIntentを確認してみて、greetingというIntentに紐づくUser exampleの部分が変更されていれば成功です。
ちなみにこの更新は差分更新ではなく、workspaceごとの置き換えになるので注意してください。