【イベント参加レポート】プロンプト・エンジニアリング入門~watsonx.ai Dojo #3~(その2)

毎月開催されているwatsonx.ai Dojoのハンズオンの内容の復習の続きになります。

今回は2部構成の後半ですが、前回とは切り離して行える形です。

イベントページ

ibm-developer.connpass.com

今回の内容はプロンプト・エンジニアリング入門ということで、プロンプトに具体例を含めるFew-ShotをIBMCloud上にデプロイ、Pythonからアクセスしてみるという内容となります。

前回の演習内容

uepon.hatenadiary.com

3回目ではプロンプト・エンジニアリング、次回以降はRAG、ファインチューニングと続くようです。そろそろ自分の事前知識を超えてきた内容も増えてきたようなので、個人的な感想としては、操作にあまり慣れていないこともあり雲行きが怪しいです😫😫😫

資料はConnpassページにもありますが、念の為こちらにも掲載しておきます。今回は最後にPythonでのコードの実行に関しては、初回参加時のエントリーで行った準備作業が必要になります。自分もやってみようという方はそちらも参考にしてください。

資料

speakerdeck.com

資料(GitHub

github.com

【動画】

video.ibm.com

演習の概要

内容は以下のような流れになっています。演習2と演習3は前後関係がある形になっています。

  • 前回へ)【演習1】プロンプト・ラボのフリー・フォームを使ってプロンプトを作る
  • 【演習2】プロンプト・ラボの構造化フォームを使ってプロンプトを作り、Web APIとしてデプロイする
  • 【演習3】デプロイ済みのWeb APIへアクセスする

【演習2】プロンプト・ラボの構造化フォームを使ってプロンプトを作り、Web APIとしてデプロイする

このパートでは、前回のプロンプトを構造化し、更にWebサービスへのデプロイ行います。

https://github.com/IBM/japan-technology/blob/main/watsonx.ai/dojo/03/02-structured-prompt/readme.md

前回のプロジェクトを使用します。作成していない方は以下を参照してください。作成済みの方は読み飛ばして次の節に進んでください。プロジェクト作成済みの方はこちらをクリックしてください。

プロジェクトを未作成の方はここから始めてください

まずはwatsonx.aiのページにログインを行い、今回使用するプロジェクトを作成しておきます。

jp-tok.dataplatform.cloud.ibm.com

IBMCloudからwatsonx.aiへいくよりも直接watsonx.aiへ直接アクセスをしたほうが良いでしょう。ログインすると以下の画面に遷移します。

下にスクロールすると、プロジェクトリストがあるので、その左上にある新規プロジェクトの作成ボタンである【+】ボタンをクリックします。

プロジェクトの作成画面にきたら、【名前】のフィールドに入力し、【作成】ボタンをクリックします。今回私はDojo#03というプロジェクト名にしました。

ちなみにこの画面にはストレージというフィールドがありますが、以前プロジェクトの作成時に使用していた値が自動的に格納されます。初回の場合には前回の内容を確認して、オブジェクトストレージの設定を行ってください。

参考エントリ

uepon.hatenadiary.com

プロジェクト作成後、画面がダッシュボードの表示に戻りプロジェクト作成が行われたことがわかります。

続いてこのプロジェクトにWatson Machine Learningサービスを関連付ける作業を行います。【管理】タブをクリックし、左側のペンから【サービスおよび統合】をクリック、右側にある【サービスの関連付け】ボタンをクリックします。

サービスの関連付けのダイアログが表示されるので、関連付けるWatson Machine Learningにチェックをつけて、【アソシエイト】ボタンをクリックします。

Watson Machine Learningの設定についても前述した前回のエントリなどを見て確認してもらえればと思います。

プロジェクトを作成済みの方はここから始めてください

ここまででプロジェクトの作成が終わっているので以下のリンクからwatsonx.aiにログインし、プロジェクト一覧を表示させます。

jp-tok.dataplatform.cloud.ibm.com

今回は作成済のプロジェクトを使用するので、Dojo#3を選びクリックします。

Dojo #3の概要ページに遷移するので、作業の開始欄にある【ファウンデーション・モデルを使用したチャットとプロンプトの作成】をクリックします。

【Prompt Lab】の画面が開いたら、【構造化】タブをクリックし、モデル設定をgranite-8b-japaneseに選択してください。

【セットアップ】セクションにある【命令 (オプション)】フィールドに、次のテキストを入力します。

あなたは素晴らしいマーケティング・スペシャリストです。日本全国各地の魅力を発信するための文章を作ります。その土地や文化を知らないけれど、有名な芸能人やメーカー名、誰もが知っている名所、美味しい食事などの話を紹介しながら、その地方への旅行を大歓迎する文章を考えてください。

【試行】セクションにある【プロンプトのテスト】の【入力】フィールドに、次のテキストを入力します。 似た名前の箇所が複数あるので入力時はよく確認してください

愛知県を知らない人に向けて、愛知県への旅行をお勧めする文章を作ってください。例があればその例を参考にして、次の「見出し一覧」にある項目を含めて書いてください。文章の最後は「魅力あふれる愛知県にお越しください!」としてください。同じ内容を繰り返さないでください。

「見出し一覧」:
- 愛知県にある観光名所3ヶ所
- 愛知県出身の有名人、芸能人4人
- 愛知県で有名なレストラン3つ
- 愛知県がモデルとなっているアニメ作品3つ

続いて画面の右上側にある【モデル・パラメータ】ボタンをクリックするとモデル・パラメータの設定ペインが開きます。

モデル・パラメータのペイン内の3つのパラメータ値を設定していきます。

パラメータ名
シーケンスの停止 ↵↵ (入力ボックス内でEnterキーを2回押すその後 【+】をクリックする)
最小トークン数 450
最大トークン数 500

【シーケンスの停止】では↵↵ (入力ボックス内でEnterキーを2回押すその後 【+】ボタンをクリックすると以下のような表示になります。入力後には必ず【+】ボタンをクリックしてください。

ここまでの設定が終わったら画面右下の【生成】ボタンをクリックします。

結果が【出力】フィールドに表示されます。それっぽい内容も多いですが、ハルシネーションも含まれていると思います。

では、先程の入力プロンプトに【例】となる情報を与えてFew Shotプロンプトにしていきます。

ウインドウの上のほうにある【例(オプション)】のフィールドに以下の様にテキストを入れていきます。項目追加する際は【例の追加+】ボタンを押してください。その後、画面下の【出力のクリア】ボタンをクリックしてから、【生成】ボタンをクリックして結果を得ます。

入力 出力
愛知県の有名なレストランを3つ教えてください。 - 矢場とん:名古屋名物みそかつの老舗で、特製みそだれと柔らかい豚肉の相性が抜群です。
- 山本屋本店:創業300年以上の味噌煮込みうどんの名店で、コシのある麺と濃厚な味噌スープが特徴です。
- 世界の山ちゃん手羽先唐揚げで全国的に有名になった居酒屋チェーンです。
愛知県出身の有名人、芸能人を4人教えてください。 - 舘ひろし(歌手としても活躍し紅白歌合戦出場):名古屋市
- 松井玲奈(アイドル歌手時代にSKE48乃木坂46のメンバーとして活躍しSKE48では紅白歌合戦出場):豊橋市
- 松平健(俳優):豊橋市
- 森川葵(ファッションモデル):東海市
愛知県がモデルとなっているアニメ作品を3つ教えてください。 - 負けヒロインが多すぎる:豊橋市
- 八十亀ちゃんかんさつにっき:全域
- やっとかめ探偵団名古屋市

前回とは異なり、例として与えた情報を基に作成をしてくれていると思います。

またパラメータを変更することで別の出力を得ることができます。 特にデコードのパラメータには以下のような特徴が出てきます。

Greedyはシンプルで一貫性があり、同じ入力に対して常に同じ出力を生成する傾向があります。逆にSamplingは多様性をもった、よりランダムな出力を生成できます。

パラメータ
デコード Sampling
温度 0.9
上位P(中核サンプリング) 1
上位K 75
ランダム・シード 65534
反復ペナルティ 1
最小トークン数 530
最大トークン数 600

その後、画面下の【出力のクリア】ボタンをクリックしてから、【生成】ボタンをクリックして結果を得ます。かなり文面の印象が変わったことがわかるのではないでしょうか。

プロンプト変数を使用する

続いてはプロンプト変数を使用していきます。【試行】-【プロンプトのテスト】の【入力】フィールドに{input}を入力し、【出力のクリア】ボタンをクリックします。

{input}

【{x}】画面右上のプロンプト変数のボタンをクリックし、

【新規変数 +】ボタンをクリックし、プロンプト変数を作成します。

以下のようにデータを入力してください。

変数 デフォルト値
input 愛知県を知らない人に向けて、愛知県への旅行をお勧めする文章を作ってください。例があればその例を参考にして、次の「見出し一覧」にある項目を含めて書いてください。文章の最後は「魅力あふれる愛知県にお越しください!」としてください。同じ内容を繰り返さないでください。
「見出し一覧」:
- 愛知県にある観光名所3ヶ所
- 愛知県出身の有名人、芸能人4人
- 愛知県で有名なレストラン3つ
- 愛知県がモデルとなっているアニメ作品3つ

また、モデル・パラメータを元の値に戻します。

パラメータ
デコード Greedy
最小トークン数 450
最大トークン数 500

その後、画面下の【出力のクリア】ボタンをクリックしてから、【生成】ボタンをクリックして結果を得ます。 プロンプト変数Pythonでいうとプロンプトをf文字列として設定した場合での外部の変数を埋め込む方法に似ています。プロンプト変数を用いることで、プロンプト内を固定ではなく、可変の値にすることができるので便利な機能です。

Pythonのf文字列(フォーマット文字列)は、文字列内で変数や式を簡単に埋め込むことができる便利な機能です。f文字列は、Python 3.6以降で使用できます。

画面上側にある【💾】をクリックし、プルダウンメニューで表示される【名前をつけて保存】をクリックします。

【作業の保存】ダイアログが表示されるので、【資産タイプ】にプロンプト・テンプレートを選択し、【名前】に保存する名前を指定して、【保存】ボタンをクリックします。

WebAPIとしてデプロイを行う

ここからは、ここまで作成したプロンプトをWebAPIとしてデプロイする作業を行います。

画面上にあるプロジェクト / Dojo #3 / 保存名 が表示されている 【Dojo #3】の部分をクリックします。

画面表示が変わったら【アセット】タブをクリックし、【すべての資産】にリスト表示されている先ほど保存したプロジェクト・テンプレートを探し、右にある【…】 (オーバーフロー・メニューを開く/閉じる)をクリックし、

プルダウンメニューから【スペースへのプロモート】をクリックします。

【スペースへのプロモート】ダイアログが表示されます。ターゲット・スペースにある【スペースの選択または作成】をクリックして【新しいデプロイメントスペースの作成】をクリックします。

すると【デプロイメント・スペースの作成】ダイアログが表示されます。以下のように値を入力し、完了したら【作成】ボタンをクリックします。

パラメータ
名前 wxaiSpace-(イニシャルや好きな英数字)
今回はwxaiSpace-20241112-UXとしました
デプロイメント・ステージ 実動
機械学習サービスの選択(オプション) 機械学習サービスの新規作成】のプルダウンにある既存のWatson Machine Learningのサービス名

【スペースを準備しています】というダイアログ表示が行われ、【スペースの準備が完了しました】という表示になるのを確認します。

【スペースへのプロモート】に戻ります。【プロモート後、スペース内のプロンプト・テンプレートに移動】にチェックを入れ【プロモート】ボタンをクリックします。

プロモーションが進行中の表示がされます。

処理が完了すると以下のような表示になります。この画面で【新規デプロイメント】ボタンをクリックします。

資料ではここで以下の表示が行われるとのことなのですが、

[スペースに関連付けられた機械学習サービス・インスタンスはありません]と表示されるので、[スペース設定に移動]をクリックします。

自分は表示はされませんでした。その後のインスタンスの関連付けの設定も行われていたようなので問題はないようです。

【wxaiSpace-】で始まる名前の画面から【資産】タブをクリックします。

Welcome-Aichi-templateのプロンプト・テンプレートを見つけ、【…】をクリックして、【デプロイ】ボタンをクリックします。

【デプロイメントの作成】ダイアログが表示されるので以下を入力して、最後に【作成】ボタンをクリックします。

パラメータ
名前 depWS
サービス提供名 wst01_(好きな英数字 ※英字は小文字のみ)

この処理でデプロイ済みであることを確認します。画面はこのままにしておきます。

引き続き演習3に進みます。

【演習3】デプロイ済みのWeb APIへアクセスする

このパートでは先程デプロイしたWebサービスPythonのプログラムからアクセスして応答を得ることを行います。

https://github.com/IBM/japan-technology/blob/main/watsonx.ai/dojo/03/03-invoke-webapi/readme.md

さすがに長くなってきたのでここからはかなり要点に絞って行きます。

先ほどのデプロイメントの確認画面でデプロイ済みの対象(今回はdepWS)をクリックします。 この画面で【デプロイメントID:】の右側にあるIDをクリックして、メモ帳などに控えておきます。 あとでこちらを使用します。

この画面で続けて【テスト】タブをクリックします。テスト画面が表示されるので、右下の【生成】ボタンをクリックします。

クリックしてしばらくすると【プロンプト結果】のダイアログが表示されます。タブを切り替えることでJSONデータの確認も可能です。

では、今度はPythonからデプロイをしたプロンプトの呼び出しを行ってみます。前回から使用しているWSLのUbuntu環境にログインし、以下のように実行します。例ではshizchat.pyとファイル名がなっていましたが、私はaichichat.pyという名前にしています。

$ cd ~/wxai
$ source venv/bin/activate
$ pip install ibm_watsonx_ai
$ code aichichat.py

続いて、Pythonプログラムからアクセスするため、以下の情報を集めます。

パラメータ
(1)IBM CloudのAPIキー 下記リンクを参考に取得してください
(2)wxaiSpace-で始まる名前のスペース GUID 以下の取得方法から取得してください
(3)depWSのデプロイメントID 以下の取得方法から取得してください

(1)IBM CloudのAPIキーの取得方法

新規に作成する場合には、こちらを参照して取得してください

わたしのブログでで前回取得した方法も参考に載せておきます。【参考:取得方法】

(2)wxaiSpace-で始まる名前のスペース GUID

このリンクにアクセスし、デプロイメント画面の【スペース】タブをクリックし、

作成したスペースをクリック、

スペースの【管理】タブをクリックした場所にスペースGUIDがあるのでこちらをコピーします。

(3)depWSのデプロイメントIDの取得方法

重複がありますが丁寧に書くことにします😊

このリンクにアクセスし、デプロイメント画面の【スペース】タブをクリックし、

作成したスペースをクリック、

スペースの【デプロイメント】タブをクリックし、デプロイ済みのデプロイメントがあるのでこちらをクリックします。

すると概要箇所にデプロイメントIDが表示されるのでコピーします。

これでPythonのプログラムに必要な3つのパラメータが準備できました。

Pythonプログラムからの実行

演習のテキストからPythonのプログラムコピーして修正して実行を行います。実行環境はWSL上のUbuntuです。過去のエントリで設定した環境です。

参考

uepon.hatenadiary.com

ソースコードの修正のポイント

  • 各種パラメータの値の格納
# api_key: IBM Cloud IAMから取得したAPIキーを入れてください (param1)
api_key = "XXXXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-XXX"
# space_id: wxaiSpaceのスペース GUIDを指定してください (param2)
space_id ="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
# deployment_id: depWSのデプロイメントIDを指定してください (param3)
deployment_id="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  • プロンプトの修正

修正ポイントは2つで、静岡県と愛知県の置換、プロンプト変数が{your_input}ではなく{input}になっていた点を修正しています。

修正後のプロンプト

# プロンプト変数の設定
prompt_var = {
    "input": "愛知県を知らない人に向けて、愛知県への旅行をお勧めする文章を作ってください。例があればその例を参考にして、次の「見出し一覧」にある項目を含めて書いてください。文章の最後は「魅力あふれる愛知県にお越しください!」としてください。同じ内容を繰り返さないでください。\n\n「見出し一覧」:\n- 愛知県にある観光名所3ヶ所\n- 愛知県出身の有名人、芸能人4人\n- 愛知県で有名なレストラン3つ\n- 愛知県がモデルとなっているアニメ作品3つ"
}  

修正後のソースコード

# aichichat.py
import requests, json 
from ibm_watsonx_ai import APIClient
from ibm_cloud_sdk_core import IAMTokenManager
from ibm_watsonx_ai.foundation_models import ModelInference
from ibm_watsonx_ai.metanames import GenTextParamsMetaNames as GenParams

# api_key: IBM Cloud IAMから取得したAPIキーを入れてください (param1)
api_key = "XXXXXX_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-XXX"
# space_id: wxaiSpaceのスペース GUIDを指定してください (param2)
space_id ="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
# deployment_id: depWSのデプロイメントIDを指定してください (param3)
deployment_id="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"

# wml_urlは 東京リージョンと想定します。
# 米国ダラスの場合は、"https://us-south.ml.cloud.ibm.com"とします。
wml_url ="https://jp-tok.ml.cloud.ibm.com"

# アクセス・トークンの取得用関数(IBM CloudのIAMからAPIキーを取得すること)
def get_auth_token():
    access_token = IAMTokenManager(apikey=api_key,url="https://iam.cloud.ibm.com/identity/token").get_token()
    print ("access_token:"+access_token)
    return access_token

# プロンプト・テンプレートの呼び出し
def invoke_prompt_template(url, api_key,space_id, deployment_id, prompt_vars):
    credentials = {
        "url": url,
        "apikey": api_key
    }
    client = APIClient(credentials)
    client.set.default_space(space_id)
    params={"prompt_variables": prompt_vars}
    generated_response = client.deployments.generate_text(deployment_id, params=params)

    print("--- プロンプト・テンプレートのWeb API呼び出し ---")
    print("Response: " + generated_response)
    print("-------------------------------------------")

    return generated_response

headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "Authorization": "Bearer "+get_auth_token()
}
# プロンプト変数の設定
prompt_var = {
    "input": "愛知県を知らない人に向けて、愛知県への旅行をお勧めする文章を作ってください。例があればその例を参考にして、次の「見出し一覧」にある項目を含めて書いてください。文章の最後は「魅力あふれる愛知県にお越しください!」としてください。同じ内容を繰り返さないでください。\n\n「見出し一覧」:\n- 愛知県にある観光名所3ヶ所\n- 愛知県出身の有名人、芸能人4人\n- 愛知県で有名なレストラン3つ\n- 愛知県がモデルとなっているアニメ作品3つ"
}     
print("prompt_var = "+json.dumps(prompt_var, indent=2))
# デプロイ済みのプロンプト・テンプレートの呼び出し
resString = invoke_prompt_template(wml_url, api_key, space_id, deployment_id, prompt_var)

実行すると以下のようになりました。ちょっと結果がおかしいけど…

おわりに

今回のハンズオンでは、プロンプト・エンジニアリングの基本として、Few-Shotプロンプトの作成からWebサービスとしてのデプロイ、そしてPythonからの呼び出しまでを一通り体験してみました。正直なところ、最後のPythonでの実行結果は期待通りとは言えない感じでしたが、多分自分が編集した設定が微妙なのかも…😅、プロンプトの構造化や変数の活用、デプロイの流れなど、多くの学びがありました。

一番むずかしかった点はプロジェクト、スペース、デプロイメントの関係性と作業の進捗が見えない点かもしれません。設定でいろいろ画面の表示をきりかえていることは多いのですが、全体を通した作業の進捗(ワークフロー)がみえるとわかりやすくなるのかなと感じます。とかくWeb系は点の情報は多いのですが、導線が見えなくて混乱があると感じています。

次回はRAGについて学ぶようですが、内容がどんどん発展的になってきているので、しっかり復習しながら進めていく必要がありそうです。かなり難易度上がってきてますし😧この記事がなにかの参考なればと思います。

興味ある方は以下のイベントにご参加してみてはどうでしょうか。

ibm-developer.connpass.com

【関連記事】

uepon.hatenadiary.com

uepon.hatenadiary.com

uepon.hatenadiary.com

/* -----codeの行番号----- */