3分で watsonx Assistant！『初めての Python プログラミングをカッコよく！』

![DALL·E 2023-11-02 11.34.40 - Digital illustration of a home office with a contemporary design, featuring two 16_9 monitors on a desk. The left monitor shows a development environm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/876b2e21-bb6c-675c-48c0-1ea00e0a2b40.png)

# はじめに

みなさん、**watsonx Assistant** を使ってますか！
なんといっても、**No Code** でチャットボットをサクッと作って、自社のホームページに簡単に設置できるのは魅力的ですね。

この **watsonx Assistant** は、「業務アプリケーションに組み込んで業務効率を上げたい」、「モバイル・アプリケーションに組み込んでユーザー体験を向上させたい」、というご要望にも答えられるように、**watsonx Assistant** の機能にアクセスできる **REST API** を公開しています。とはいえ **API** なのでプログラミングが必要になります。

ただし、ここで引いてはいけません笑

この記事では、昨今話題の生成AIを活用してプログラミングを行いますので、実際のプログラミングの量はグッと減り、まさに、 **Low Code** です。

# プログラム作成の方針

プログラム全体の見通しを良くし、将来のプログラム変更にも容易に対応できるように、**FastAPI** を使おうと思います。(ここが **『カッコよく』** の所以です)

ところで、みなさん、**FastAPI** って聞いたことありますか？

アプリケーション・プログラムから直接 **watsonx Assistant API** を呼び出すことはもちろん可能ですが、

:cloud_rain: アプリケーション・プログラムの中に認証用のコードを埋め込むため、セキュリティ的に問題がある
:cloud_lightning: 別のチャットボットエンジンの **API** に変更したい場合、アプリケーション・プログラムの修正が必要になり、アプリケーション・プログラム自体の汎用性が失われる

等、の問題があります。

:::note 
もっと根深い問題については、[こちら](https://ja.wikipedia.org/wiki/Web_Server_Gateway_Interface)のWikipediaの記事を参照ください。
:::

https://ja.wikipedia.org/wiki/Web_Server_Gateway_Interface

このような問題の解決策として、**WSGI（Web Server Gateway Interface）** という考え方があり、その実装の一例が **FastAPI** です。

ということで、今回は、アプリケーション・プログラムをサーバー・プログラムとクライアント・プログラムに分離して実装していきます。

前置きはこれぐらいにして、早速いってみましょう:bangbang:

# 本当に3分でできるのか:question:

３分で終わらせるためには、これからご紹介する 3 つの前提条件をクリアする必要がありますので、その点についてご説明します。

## 条件1: watsonx Assistant環境をお持ちで、Actionsで対話フローの作成が終わっていること

この条件をクリアするための情報は、こちらのQiita記事で扱っています。まだ、watsonx Assistant 環境をお持ちでない方は参考にしてみて下さい。

https://qiita.com/yanagih/items/b02db00d06de397bec64

https://qiita.com/yanagih/items/f98cff2b5b9ce3208fc4

こんな対話フローを作成しておきます。
シンプルながらも、現在時刻を表示してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/a03b297c-ee6c-4ddf-dccd-a4ab67c40451.png)


## 条件2: Python と VS Code の実行環境が導入済みであること 

この記事は、MacOS にて確認した内容ではありますが、Windows 環境であっても Python が導入済みであれば再現可能です。

この条件をクリアするための情報は、こちらの Qiita 記事が参考になると思います。
(先人の知恵をお借りします)

**Windows をお使いの方**

https://qiita.com/SAITO_Keita/items/ddcde4fdcdf5e5eaa933

**MacOS をお使いの方**

https://qiita.com/makaishi2/items/c6de3dbebef7b0abe5ae

## 条件3: GitHub Copilot が VS Code から使えるように設定する

この条件をクリアするための情報は、こちらのQiita記事で扱っていますので、まだ、環境をお持ちでない方は参考にしてみて下さい。

https://qiita.com/yanagih/items/9ffd7faaa68fff47897c

:::note
コードを生成する AIとして、今回の記事では [GitHub Copilot](https://docs.github.com/ja/copilot/getting-started-with-github-copilot) を使用します。
:::

https://docs.github.com/ja/copilot/getting-started-with-github-copilot

# レッツ・プログラミング:bangbang: :writing_hand:

3 つのステップでプログラミングをしていきます。

1. サーバー・プログラムの作成と実行
1. テスト・プログラムの作成と実行
1. クライアント・プログラムの作成と実行

です。

## :one: サーバー・プログラムの作成と実行

### サーバー・プログラムの作成

サーバー・プログラムとして、**watsonx Assistant** に接続するための **Gateway Interface** を作成します。つまりは、**watsonx Assistant API** にアクセスするための仕掛けで、先にご紹介した **WSGI** の実装です。

これによって、アプリケーション・ロジックを埋め込むクライアント・プログラム側に認証用のコードを埋め込む必要がなくなります。

なんか難しそうに感じるかもしれませんが、そこはご安心を。

まずは VS Code を開き、**app.py** という名前のファイルを作成してください。
そして、**GitHub Copilot チャット**をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/f25bf9fd-2d7c-0e64-76c0-104755f3153b.png)


チャット・ウィンドウが表示されますので、
```
fastapiを使って、watson assistantへのgatewayサーバーを作成して下さい
```
と入力してサーバー・プログラムを生成します。こんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/6278ff24-e3dc-ea70-0692-e3eae5943243.png)

エンターキーを押すと。。。。
一気に大量のコードが生成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/4363ad68-a667-b89d-10a0-53981c5c614d.png)

ざっと眺める限り、**watsonx Assistant** の部分は問題がなさそうです。
**FastAPI** の部分は自分でコードを書いたことがないので自信がありませんが、なんとなく OK っぽい。

右上にある「カーソルに挿入」アイコンをクリックすると、生成されたコードが、エディター領域にコピーされます。
こんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/fd607056-6667-aae5-9413-88c1a77f6c87.png)

あとは、自分の環境に合わせて、この部分を修正します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/b2fef603-b9a2-c59b-54c8-7e35d6fe13ba.png)

### **assistant_id** について
各 Assistants の **Environemtsタブ**の **Settings** をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/04a70be3-1b28-6880-3d15-3dec551758c1.png)

API details タブの Environment ID が assistant_id です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/c8b64d13-53a1-1e40-11e9-9be728d61986.png)


### **url** と **api_key** について
watsonx Assistant の管理タブから値をコピーしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/56491bfc-df52-ff18-7896-a75d506fe94d.png)

### サーバー・プログラムの実行

出来上がった app.py を実行します。
実行方法も一緒に GitHub Copilot が教えてくれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/99acfb7e-ff63-91a7-254a-3c8b2093797e.png)

この指示に従って、サーバー・プログラムである app.py を実行してみます。

```shell
$ pip install fastapi uvicorn ibm-watson
$ uvicorn app:app --reload
```
エラーが発生することもなく、一発で実行できました。
成功すると、このような表示になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/44912f16-ce84-6339-e8c4-99592d9e59ba.png)

:::note
**FastAPI** を使うプログラムを起動する方法の詳細については、[こちら](https://fastapi.tiangolo.com/ja/tutorial/first-steps/)を参照してください。
:::

https://fastapi.tiangolo.com/ja/tutorial/first-steps/

## :two: テスト・プログラムの生成と実行
### テスト・プログラムの生成
サーバー・プログラムが正常に動作するかどうか、テストしてみます。
GitHub Copilot の出力を見ると、テストする方法が記載されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/b3bfa6d1-d7c8-00fe-2c68-b6e6648a3f22.png)

ただ、ここは、テストプログラムも生成して欲しいところです。
早速お願いしてみましょう。

```
以下のようなJSON形式のデータを含むPOSTリクエストをcurl形式で教えて下さい 
{ "text": "こんにちは" }
```
と入力します。こんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/b9ed17e9-79e3-5dc6-3631-1cfad6968c9f.png)
速攻で、cURLコマンドが出力されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/2c567b07-3857-29c4-1055-b8fac511376c.png)

### テスト・プログラムの実行
実行してみます。
```shell:cURL
curl -X POST "http://localhost:8000/message" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{\"text\":\"こんにちは\"}" | jq .
```
エラーが発生することもなく、一発で実行できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/d0d493a8-9dca-bf49-b5f7-049f99bc93ff.png)

現在時刻も取得できています。

## :three: クライアント・プログラムの生成と実行
### クライアント・プログラムの生成
テストが成功したので、クライアント・プログラムを生成します。
```
クライアント側のpythonコードを作成して下さい
```
と入力します。こんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/9ea8b102-194b-b1af-2d2f-4dd6dea73c45.png)

速攻で、クライアント・プログラムが出力されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/6f87b6a9-30e6-ee82-dcc0-c8dd81a66c98.png)

### クライアント・プログラムの実行
実行に必要なモジュールをインストールします。
```shell:pip
$ pip install requests
```
実行してみます。
```shell:python
python client.py
```
エラーが発生することもなく、一発で実行できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/4b02dc1e-9f1a-6b6c-ab19-2d9bf50ab0a0.png)

現在時刻も取得できています。

# 結果（まとめ)
![DALL·E 2023-11-03 12.00.04 - Digital illustration of an AI chatbot represented as a holographic interface in a cozy home office environment. The hologram is a friendly, gender-neu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52151/c58ae93a-a56c-23f1-8bd4-7b4837531a5f.png)

簡単なプログラムとはいえ、GitHub Copilot を使うことで、自分でコードを 1 行たりとも書かずに、一発で、サーバー・プログラムとクライアント・プログラムを生成することができました。
**Low Code** どころか、**No Code** でした :smiley:
さらに、**No Error** です:bangbang:

始める前は、watsonx Assistant の API コール部分は、**requests** を使った実装になるのかなと想像していたのですが、それはいい意味で裏切られ、Python SDKを使ったシンプルなPythonコードが生成されました。
GitHub Copilot は IBM Watson のPython SDK も学習しているのですね。ある意味感動しました:grin:


# 終わりに
最後まで読んでくれた皆さんと感動を共有するために、生成されたコードを載せておきます。
時間がある方は試してみてください。

3分で終わるはずです。。。:sweat_smile:

### サーバー・プログラム
```python:app.py
from fastapi import FastAPI
from pydantic import BaseModel
from ibm_watson import AssistantV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

# Watson Assistantの設定
assistant_id = 'YOUR_ASSISTANT_ID'
api_key = 'YOUR_API_KEY'
url = 'YOUR_URL'

# FastAPIのインスタンスを作成
app = FastAPI()

# リクエストボディのモデルを定義
class Item(BaseModel):
    text: str

# Watson Assistantへの接続を作成
authenticator = IAMAuthenticator(api_key)
assistant = AssistantV2(
    version='2020-04-01',
    authenticator=authenticator
)
assistant.set_service_url(url)

# /messageエンドポイントを作成
@app.post("/message")
async def send_message(item: Item):
    response = assistant.message_stateless(
        assistant_id=assistant_id,
        input={
            'message_type': 'text',
            'text': item.text
        }
    ).get_result()

    return response
```
### テスト用 cURL コマンド
```shell: curl
curl -X POST "http://localhost:8000/message" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{\"text\":\"こんにちは\"}"
```
### クライアント・プログラム
```python:client.py
import requests

url = "http://localhost:8000/message"
data = {
    "text": "こんにちは"
}

response = requests.post(url, json=data)

print(response.json())
```

# 参考

https://ja.wikipedia.org/wiki/Web_Server_Gateway_Interface

https://qiita.com/yanagih/items/b02db00d06de397bec64

https://qiita.com/yanagih/items/f98cff2b5b9ce3208fc4

https://qiita.com/SAITO_Keita/items/ddcde4fdcdf5e5eaa933

https://qiita.com/makaishi2/items/c6de3dbebef7b0abe5ae

https://qiita.com/yanagih/items/9ffd7faaa68fff47897c

https://docs.github.com/ja/copilot/getting-started-with-github-copilot

https://fastapi.tiangolo.com/ja/tutorial/first-steps/

https://qiita.com/advent-calendar/2023/watsonx