IBM Watson Discovery v1 と v2 の API のバージョン間で Request / Response を比較してみました(トレーニングデータ関連)

# はじめに

- [IBM Watson Discovery v1 の非推奨の発表](https://www.ibm.com/blogs/solutions/jp-ja/ibm-watson-discovery-v1-deprecation-announcement/) を受けて、v1 から v2 へのアプリ改修にどの程度のインパクトがありそうか、v1 と v2 の API のバージョン間で Request / Response を比較してみました。
- 今回は、[API バージョンの比較](https://cloud.ibm.com/docs/discovery-data?topic=discovery-data-migrate-to-v2-api) を参考にトレーニングデータ関連にフォーカスしてまとめたいと思います。

# 前提

- [Watson Developer Cloud Python SDK](https://github.com/watson-developer-cloud/python-sdk) を使用した確認になります。
- Python のバージョンは 3.10.4 です。 

# 調査対象

|操作| v1 API | v1 API サンプルコード | v2 API | v2 API サンプルコード | 
|:-|:-|:-|:-|:-|
|1. トレーニングクエリのリスト|[関数 list_training_data()](https://cloud.ibm.com/apidocs/discovery?code=python#listtrainingdata)|[list.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v1/training/list.py)|[関数 list_training_queries()](https://cloud.ibm.com/apidocs/discovery-data?code=python#listtrainingqueries)|[list.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v2/training/list.py)|
|2. トレーニングクエリの追加|[関数 add_training_data()](https://cloud.ibm.com/apidocs/discovery#addtrainingdata)|[create.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v1/training/create.py)|[関数 create_training_query()](https://cloud.ibm.com/apidocs/discovery-data#createtrainingquery)|[create.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v2/training/create.py)|
|3. 全てのトレーニングクエリの削除|[関数 delete_all_training_data()](https://cloud.ibm.com/apidocs/discovery#deletealltrainingdata)|[delete_all.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v1/training/delete_all.py)|[関数 delete_training_queries()](https://cloud.ibm.com/apidocs/discovery-data?code=python#deletetrainingqueries)|[delete_all.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v2/training/delete_all.py)|
|4. トレーニングクエリの詳細取得|[関数 get_training_data()](https://cloud.ibm.com/apidocs/discovery?code=python#gettrainingdata)|[list.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v1/training/list.py)|[関数 get_training_query()](https://cloud.ibm.com/apidocs/discovery-data?code=python#gettrainingquery)|[list.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v2/training/list.py)|
|5. トレーニングクエリの削除|[関数 delete_training_data()](https://cloud.ibm.com/apidocs/discovery?code=python#deletetrainingdata)|[delete.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v1/training/delete.py)|[関数 delete_training_query()](https://cloud.ibm.com/apidocs/discovery-data?code=python#deletetrainingquery)|[delete.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v2/training/delete.py)|
|6. トレーニングクエリ例のリスト|[関数 list_training_examples()](https://cloud.ibm.com/apidocs/discovery?code=python#listtrainingexamples)|[list.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v1/training/list.py)|[関数 get_training_query()](https://cloud.ibm.com/apidocs/discovery-data?code=python#gettrainingquery)|[list.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v2/training/list.py)| 
|7. トレーニングクエリ例の追加|[関数 create_training_example()](https://cloud.ibm.com/apidocs/discovery#createtrainingexample)|[create.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v1/training/create.py)|[関数 create_training_query()](https://cloud.ibm.com/apidocs/discovery-data?code=python#createtrainingquery)|[create.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v2/training/create.py)|
|8. トレーニングクエリ例の削除|[関数 delete_training_example()](https://cloud.ibm.com/apidocs/discovery?code=python#deletetrainingexample)|[delete.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v1/training/delete.py)|[関数 update_training_query()](https://cloud.ibm.com/apidocs/discovery-data?code=python#updatetrainingquery) に統合|[update.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v2/training/update.py)|
|9. トレーニングクエリ例のラベルまたは相互参照の変更|[関数 update_training_example()](https://cloud.ibm.com/apidocs/discovery?code=python#updatetrainingexample)|[update.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v1/training/update.py)|[関数 update_training_query()](https://cloud.ibm.com/apidocs/discovery-data?code=python#updatetrainingquery) に統合|[update.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v2/training/update.py)|
|10. トレーニングクエリ例の詳細取得|[関数 get_training_example()](https://cloud.ibm.com/apidocs/discovery#gettrainingexample)|[list.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v1/training/list.py)|廃止 (関数 get_training_query() で代用)|[list.py](https://github.com/to-tomo/ws-samples/blob/main/scripts/discovery_v2/training/list.py)|

# 1. トレーニングクエリのリスト

## v1 API の Request / Response
### 関数 (Request)
```python
list_training_data(self,
        environment_id: str,
        collection_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "collection_id": "1425ab9a-126d-45cd-ac6c-4d3a0a561452",
  "environment_id": "95263fa3-c345-4c11-93d6-515458f265a5",
  "queries": [
    {
      "natural_language_query": "ハローキティ",
      "filter": "",
      "examples": [
        {
          "document_id": "73bacbd1c545057035827ddaa32fac24",
          "cross_reference": "スマートフォン",
          "relevance": 10,
          "created": "2022-08-22T10:14:42.922Z",
          "updated": "2022-08-22T10:14:42.963Z"
        },
        (繰り返しのため省略)
      ],
      "query_id": "4a1c9a4487c02d0e5e6b52adc99fd00ca4499d89",
      "created": "2022-08-22T10:14:42.944Z",
      "updated": "2022-08-22T10:14:42.944Z"
    }
  ]
}
```
## v2 API の Request / Response
### 関数 (Request)
```python
list_training_queries(self,
        project_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "queries": [
    {
      "query_id": "c944292f19e0b285ac17c74b6c377280a4d8ba60",
      "natural_language_query": "日本語",
      "filter": "",
      "created": "2022-08-19T02:58:02.863Z",
      "updated": "2022-08-19T02:58:02.863Z",
      "examples": [
        {
          "document_id": "01d20221509f9a5a71bc2ea26549a1cf",
          "relevance": 10,
          "collection_id": "dd68ff7b-db42-88b5-0000-0182afa29602",
          "created": "2022-08-19T02:58:02.843Z",
          "updated": "2022-08-19T02:58:02.931Z"
        },
        (繰り返しのため省略)
      ]
    },
    (繰り返しのため省略)    
  ]
}
```
## 比較結果
- v2 API では、`environment` の概念はなく、`collection` は `project` で編成するように変更されており、関数の引数が異なります。
- v1 API: `list_training_data()` から v2 API: `list_training_queries()` に関数名が変更されています。

# 2. トレーニングクエリの追加

## v1 API の Request / Response
### 関数 (Request)
```python
add_training_data(self,
        environment_id: str,
        collection_id: str,
        *,
        natural_language_query: str = None,
        filter: str = None,
        examples: List['TrainingExample'] = None,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "natural_language_query": "ハローキティ",
  "filter": "",
  "examples": [
    {
      "document_id": "73bacbd1c545057035827ddaa32fac24",
      "cross_reference": "スマートフォン",
      "relevance": 10,
      "created": "2022-08-22T10:14:42.922Z",
      "updated": "2022-08-22T10:14:42.963Z"
    },
    (繰り返しのため省略) 
  ],
  "query_id": "4a1c9a4487c02d0e5e6b52adc99fd00ca4499d89",
  "created": "2022-08-22T10:14:42.944Z",
  "updated": "2022-08-22T10:14:42.944Z"
}
```
## v2 API の Request / Response
### 関数 (Request)
```python
create_training_query(self,
        project_id: str,
        natural_language_query: str,
        examples: List['TrainingExample'],
        *,
        filter: str = None,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "query_id": "c944292f19e0b285ac17c74b6c377280a4d8ba60",
  "natural_language_query": "日本語",
  "filter": "",
  "created": "2022-08-22T02:35:03.248Z",
  "updated": "2022-08-22T02:35:03.248Z",
  "examples": [
    {
      "document_id": "ce24328ce8a97b1efc22234dd301f1ea",
      "relevance": 10,
      "collection_id": "dd68ff7b-db42-88b5-0000-0182afa29602",
      "created": "2022-08-22T02:35:03.231Z",
      "updated": "2022-08-22T02:35:03.287Z"
    },
    (繰り返しのため省略) 
  ]
}
```
## 比較結果
- v2 API では、`environment` の概念はなく、`collection` は `project` で編成するように変更されており、関数の引数が異なります。
- v1 API: `add_training_data()` から v2 API: `create_training_query()` に関数名が変更されています。

# 3. 全てのトレーニングクエリの削除

## v1 API の Request / Response
### 関数 (Request)
```python
delete_all_training_data(self,
        environment_id: str,
        collection_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
なし (ステータスコードのみ)
```
## v2 API の Request / Response
### 関数 (Request)
```python
delete_training_queries(self,
        project_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
なし (ステータスコードのみ)
```
## 比較結果
- v2 API では、`environment` の概念はなく、`collection` は `project` で編成するように変更されており、関数の引数が異なります。
- v1 API: `delete_all_training_data()` から v2 API: `delete_training_queries()` に関数名が変更されています。
  
# 4. トレーニングクエリの詳細取得

## v1 API の Request / Response
### 関数 (Request)
```python
get_training_data(self,
        environment_id: str,
        collection_id: str,
        query_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "natural_language_query": "ハローキティ",
  "filter": "",
  "examples": [
    {
      "document_id": "73bacbd1c545057035827ddaa32fac24",
      "cross_reference": "スマートフォン",
      "relevance": 10,
      "created": "2022-08-22T10:14:42.922Z",
      "updated": "2022-08-22T10:14:42.963Z"
    },
    (繰り返しのため省略)
  ],
  "query_id": "4a1c9a4487c02d0e5e6b52adc99fd00ca4499d89",
  "created": "2022-08-22T10:14:42.944Z",
  "updated": "2022-08-22T10:14:42.944Z"
}
```
## v2 API の Request / Response
### 関数 (Request)
```python
get_training_query(self,
        project_id: str,
        query_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "query_id": "c944292f19e0b285ac17c74b6c377280a4d8ba60",
  "natural_language_query": "日本語",
  "filter": "",
  "created": "2022-08-19T02:58:02.863Z",
  "updated": "2022-08-19T02:58:02.863Z",
  "examples": [
    {
      "document_id": "01d20221509f9a5a71bc2ea26549a1cf",
      "relevance": 10,
      "collection_id": "dd68ff7b-db42-88b5-0000-0182afa29602",
      "created": "2022-08-19T02:58:02.843Z",
      "updated": "2022-08-19T02:58:02.931Z"
    },
    (繰り返しのため省略)
  ]
}
```
## 比較結果
- v2 API では、`environment` の概念はなく、`collection` は `project` で編成するように変更されており、関数の引数が異なります。
- v1 API: `get_training_data()` から v2 API: `get_training_query()` に関数名が変更されています。
  
# 5. トレーニングクエリの削除

## v1 API の Request / Response
### 関数 (Request)
```python
delete_training_data(self,
        environment_id: str,
        collection_id: str,
        query_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
なし (ステータスコードのみ)
```
## v2 API の Request / Response
### 関数 (Request)
```python
delete_training_query(self,
        project_id: str,
        query_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
なし (ステータスコードのみ)
```
## 比較結果
- v2 API では、`environment` の概念はなく、`collection` は `project` で編成するように変更されており、関数の引数が異なります。
- v1 API: `delete_training_data()` から v2 API: `delete_training_query()` に関数名が変更されています。

# 6. トレーニングクエリ例のリスト

## v1 API の Request / Response
### 関数 (Request)
```python
list_training_examples(self,
        environment_id: str,
        collection_id: str,
        query_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "examples": [
    {
      "document_id": "73bacbd1c545057035827ddaa32fac24",
      "cross_reference": "スマートフォン",
      "relevance": 10,
      "created": "2022-08-22T10:14:42.922Z",
      "updated": "2022-08-22T10:14:42.963Z"
    },
    (繰り返しのため省略)
  ]
}
```
## v2 API の Request / Response
### 関数 (Request)
```python
get_training_query(self,
        project_id: str,
        query_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "query_id": "c944292f19e0b285ac17c74b6c377280a4d8ba60",
  "natural_language_query": "日本語",
  "filter": "",
  "created": "2022-08-19T02:58:02.863Z",
  "updated": "2022-08-19T02:58:02.863Z",
  "examples": [
    {
      "document_id": "01d20221509f9a5a71bc2ea26549a1cf",
      "relevance": 10,
      "collection_id": "dd68ff7b-db42-88b5-0000-0182afa29602",
      "created": "2022-08-19T02:58:02.843Z",
      "updated": "2022-08-19T02:58:02.931Z"
    },
    (繰り返しのため省略)
  ]
}
```
## 比較結果
- v2 API では、`environment` の概念はなく、`collection` は `project` で編成するように変更されており、関数の引数が異なります。
- v1 API: `list_training_examples()` から v2 API: `get_training_query()` に関数名が変更されています。

# 7. トレーニングクエリ例の追加

## v1 API の Request / Response
### 関数 (Request)
```python
create_training_example(self,
        environment_id: str,
        collection_id: str,
        query_id: str,
        *,
        document_id: str = None,
        cross_reference: str = None,
        relevance: int = None,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "document_id": "a78d4badca5f9650b84efc0406127bb9",
  "cross_reference": "放射線",
  "relevance": 10,
  "created": "2022-08-22T12:50:06.124Z",
  "updated": "2022-08-22T12:50:06.321Z"
}
```
## v2 API の Request / Response
### 関数 (Request)
```python
create_training_query(self,
        project_id: str,
        natural_language_query: str,
        examples: List['TrainingExample'],
        *,
        filter: str = None,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "query_id": "c944292f19e0b285ac17c74b6c377280a4d8ba60",
  "natural_language_query": "日本語",
  "filter": "",
  "created": "2022-08-22T02:35:03.248Z",
  "updated": "2022-08-22T02:35:03.248Z",
  "examples": [
    {
      "document_id": "ce24328ce8a97b1efc22234dd301f1ea",
      "relevance": 10,
      "collection_id": "dd68ff7b-db42-88b5-0000-0182afa29602",
      "created": "2022-08-22T02:35:03.231Z",
      "updated": "2022-08-22T02:35:03.287Z"
    },
    (繰り返しのため省略)
  ]
}
```
## 比較結果
- v2 API では、`environment` の概念はなく、`collection` は `project` で編成するように変更されており、関数の引数が異なります。
- v1 API: `create_training_example()` から v2 API: `create_training_query()` に関数名が変更されています。
- v1 API の関数 `create_training_example()` のように単体のトレーニングクエリ例を追加する関数は廃止され、v2 API では関数 `create_training_query()` を使用して、`TrainingExample` の配列を渡して、`natural_language_query` 毎にトレーニングクエリ例を追加します。あくまで、`natural_language_query` 単位であるため、`document_id` 毎にトレーニングクエリ例を追加できません。また、v1 API の関数 `create_training_example()` の `cross_reference` も廃止されているようです。

# 8. トレーニングクエリ例の削除

## v1 API の Request / Response
### 関数 (Request)
```python
delete_training_example(self,
        environment_id: str,
        collection_id: str,
        query_id: str,
        example_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
なし (ステータスコードのみ)
```
## v2 API の Request / Response
### 関数 (Request)
```python
update_training_query(self,
        project_id: str,
        query_id: str,
        natural_language_query: str,
        examples: List['TrainingExample'],
        *,
        filter: str = None,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "query_id": "57bc9b968d814dbd177099aeeee1e38f68bf6226",
  "natural_language_query": "映画",
  "filter": "",
  "created": "2022-08-22T02:35:05.122Z",
  "updated": "2022-08-22T06:05:20.707Z",
  "examples": [
    {
      "document_id": "50cdf899fd622db1451046c9c9ccd423",
      "relevance": 10,
      "collection_id": "dd68ff7b-db42-88b5-0000-0182afa29602",
      "created": "2022-08-22T02:35:05.106Z",
      "updated": "2022-08-22T06:05:20.707Z"
    },
    (繰り返しのため省略)
  ]
}
```
## 比較結果
- v2 API では、`environment` の概念はなく、`collection` は `project` で編成するように変更されており、関数の引数が異なります。
- v1 API: `delete_training_example()` から v2 API: `update_training_query()` に関数名が変更されています。正確には、関数 `update_training_query()` に統合されています。
- v1 API の関数 `delete_training_example()` のように単体のトレーニングクエリ例を削除する関数は廃止され、v2 API では関数 `update_training_query()` を使用して、`TrainingExample` の配列を渡して、`natural_language_query` 毎にトレーニングクエリ例を洗い替えすることによってトレーニングクエリ例の削除と同様の挙動をします。

# 9. トレーニングクエリ例のラベルまたは相互参照の変更

## v1 API の Request / Response
### 関数 (Request)
```python
update_training_example(self,
        environment_id: str,
        collection_id: str,
        query_id: str,
        example_id: str,
        *,
        cross_reference: str = None,
        relevance: int = None,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "document_id": "73bacbd1c545057035827ddaa32fac24",
  "cross_reference": "スマートフォン",
  "relevance": 10,
  "created": "2022-08-22T14:16:10.877Z",
  "updated": "2022-08-22T14:16:11.049Z"
}
```
## v2 API の Request / Response
### 関数 (Request)
```python
update_training_query(self,
        project_id: str,
        query_id: str,
        natural_language_query: str,
        examples: List['TrainingExample'],
        *,
        filter: str = None,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "query_id": "57bc9b968d814dbd177099aeeee1e38f68bf6226",
  "natural_language_query": "映画",
  "filter": "",
  "created": "2022-08-22T02:35:05.122Z",
  "updated": "2022-08-22T06:05:20.707Z",
  "examples": [
    {
      "document_id": "50cdf899fd622db1451046c9c9ccd423",
      "relevance": 10,
      "collection_id": "dd68ff7b-db42-88b5-0000-0182afa29602",
      "created": "2022-08-22T02:35:05.106Z",
      "updated": "2022-08-22T06:05:20.707Z"
    },
    (繰り返しのため省略)
  ]
}
```
## 比較結果
- v2 API では、`environment` の概念はなく、`collection` は `project` で編成するように変更されており、関数の引数が異なります。
- v1 API: `update_training_example()` から v2 API: `update_training_query()` に関数名が変更されています。
- v1 API の関数 `update_training_example()` のように単体のトレーニングクエリ例を更新する関数は廃止され、v2 API では関数 `update_training_query()` を使用して、`TrainingExample` の配列を渡して、`natural_language_query` 毎にトレーニングクエリ例を洗い替えすることによってトレーニングクエリ例の更新と同様の挙動をします。

# 10. トレーニングクエリ例の詳細取得

## v1 API の Request / Response
### 関数 (Request)
```python
get_training_example(self,
        environment_id: str,
        collection_id: str,
        query_id: str,
        example_id: str,
        **kwargs
    ) -> DetailedResponse
```
### Response の具体例
```json
{
  "document_id": "73bacbd1c545057035827ddaa32fac24",
  "cross_reference": "スマートフォン",
  "relevance": 10,
  "created": "2022-08-22T10:14:42.922Z",
  "updated": "2022-08-22T10:14:42.963Z"
}
```
## v2 API の Request / Response
- 廃止
## 比較結果
- v2 API では、`example_id` を指定してピンポイントでトレーニングクエリ例を取得できませんが、関数 `get_training_query()` でクエリに関連付いている全てのトーレーニングクエリ例の配列を取得した後、そこから必要なトーレーニングクエリ例を取得できます。

# 終わりに

v1 から v2 へのアプリ改修へのインパクトという点では、以下が主な違いでした。
- environment から project への構成変更に伴い、引数が変わった
    - 具体的には、 `environment_id` から `project_id` に変更
- `1. トレーニングクエリのリスト` 〜 `9. トレーニングクエリ例のラベルまたは相互参照の変更` は関数名が変わった
    - 具体的には、[**調査対象**の表](#調査対象) を参照
- さらに、`7. トレーニングクエリ例の追加` 〜 `9. トレーニングクエリ例のラベルまたは相互参照の変更`は `TrainingExample` クラスに纏めた配列を渡す形に引数が変わった
- `10. トレーニングクエリ例の詳細取得` は廃止され、`6. トレーニングクエリ例のリスト` で代用
- その他 v1 と v2 の機能比較については [こちら](https://cloud.ibm.com/docs/discovery-data?topic=discovery-data-version-choose#version-choose-comparison) を参照してください

なお、v2ではプロジェクトの中にコレクションを作る構成になりましたが、v1から移行する場合は、プロジェクト対コレクションの関係を １:１ にすると移行がシンプルになると思います。

# 参考

- [Qitta 記事 | Watson Discoveryをv1からv2に移行してみた](https://qiita.com/nsatoh/items/1f9638cd58730213a4e5#4-discovery-v1%E3%81%AE%E9%96%A2%E9%80%A3%E6%80%A7%E3%83%88%E3%83%AC%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B)
- [IBM ソリューションブログ | IBM Watson Discovery v1 の非推奨の発表](https://www.ibm.com/blogs/solutions/jp-ja/ibm-watson-discovery-v1-deprecation-announcement/)
- [IBM Cloud 資料 | API バージョンの比較](https://cloud.ibm.com/docs/discovery-data?topic=discovery-data-migrate-to-v2-api)
- [IBM Cloud 資料 | Discovery > Training data](https://cloud.ibm.com/docs/discovery-data?topic=discovery-data-migrate-to-v2-api#migrate-to-v2-api-trainingd-data)

# お断り

このサイトの掲載内容は私自身の見解であり、必ずしも所属会社の立場、戦略、意見を代表するものではありません。 記事は執筆時点の情報を元に書いているため、必ずしも最新情報であるとはかぎりません。 記事の内容の正確性には責任を負いません。自己責任で実行してください。