見出し画像

【AWS】Difyっぽい?Bedrockの新機能を試してみた【Prompt flows】

■記事の対象ユーザ

1.AWSアカウントを持っている人
2.Bedrockで使えるようになったDifyみたいなツール(Prompt flows)が気になる人
3.AWSの課金に抵抗がない人
4.Pythonの環境がすぐ用意できる人(API叩く検証で使うので)

なんちゃってAWSアーキテクトアソシエイトの

■ようするに?

2024年7月11日に発表されたBedrockの新機能「Prompt flows」を使ってフローを作り、ローカルPC上からPythonでAPI使ってアクセスするところまでを試していくよ。


0.はじめに

Bedrockに新機能!Difyみたいなノーコードアプリ開発ツールが付いてきた!

早い方は発表その日のうち(!?)に記事を書かれていて私も参考にさせて貰っていたんですが、AWSビギナーすぎてちょっと試すのにも時間がかかってしまったので今回は備忘も兼ねて少し詳しめに手順を残しておこうと思います。(AWSに慣れてる人にはかなり回りくどい感じると思うけど許してほしい)

【参考記事1】Amazon Bedrockの新機能「Prompt flows」を試してみた(GEEKFEED様)

【参考記事2】Bedrockの新機能「Prompt flows for Amazon Bedrock」(@moritalous様)

注意してね

料金は普通にClaudeに払うAPI料金をAWSに徴収されるような感じです。

今回検証に使う米国リージョンでの利用料はこんな感じ

1.BedrockでAIモデルを使えるようにする

まずはAWSマネジメントコンソールに権限を持ったユーザでログインし、
トップ画面の検索窓から「Bedrock」を検索

Bedrockの概要画面に来るので「使用を開始」を選択

「サーバレスで簡単にAIアプリケーションが作れるフルマネージドサービス」くらい?

Bedrockのトップページに到着

今回は検証用にClaude3 HaikuとSonnetを使ってみる予定だから、次の記事を参考に進めていくよ。

左側メニューの下部にある「モデルアクセス」を選択

アクセス可能なモデルの一覧が表示される

東京リージョンでの一覧画面
おま国や

リージョンを確認してみてください。
2024年7月14日現在、東京リージョンにはまだClaude3が展開されていないのでこの一覧では古いClaudeしかアクセスできない状態になっています。

幸い2024年7月中には東京リージョンにもClaude3が展開されると6月20日、21日に開催されていた「AWS Summit Japan」で発表されているので今しばらくは我慢ですね。

アメリカのリージョンでは既にClaude3 HaikuやClaude3 Sonnetが利用可能になっているので今回はバージニア北部(us-east-1)リージョンに切り替えて進めていくよ。

北米リージョンには6月末頃には来ていて本来はリクエストできるはずだけど、混み合ってるのか7月14日現在では一時的に申請不可になっているみたいね。多分サポートに問い合わせて個別に有効化を依頼しないとダメなんでしょう。

対応モデル一覧ページの最新の状況が記載されているので確認してみてね。

続きいくね。
画面上部にある「Modify moel access」を選択

遷移先で「Claude 3 Haiku」「Claude 3 Sonnet」にチェックを入れて「Next」を選択

記事書く前にHaikuを有効化してみたのでこんな表示になってます。

次に「Review and submit」の画面に来ます。
このスクリーンショットでは「Step1:Edit model access」しか表示されてませんが、初めてAnthropicのモデルに対してモデルアクセスをリクエストする場合はStep1の下に「Step2:Add use case details for Anthropic」というアンケートの様な項目が表示されています。

HaikuでStep2登録しちゃったので今回は出ていない・・・

質問項目は以下5項目でいずれも必須入力

  • 「会社名」(テキストボックス)

  • 「会社のウェイブサイトのURL」(テキストボックス)

  • 「どの業界で事業を行っているか」(プルダウン)

  • 「対象ユーザは誰ですか?」(チェックボックス)

  • 「ユースケースの説明」(テキストボックス)

私は次の様に入力しましたが問題なく申請が受け付けられました。

会社名:無所属
ウェブサイトURL:https://example.com
業界:その他→個人
対象ユーザー:「社内の従業員」「外部のユーザー」どちらもチェック
ユースケース:個人での技術的検証

Step1、Step2と両方確認したら「Submit」で確定。

元の画面に戻ると上の方にしばらくすると有効化されるよって表示されています。

青い部分

Model access updates submitted
It may take several minutes to receive or remove access to models. Meanwhile, you can use other Bedrock console pages. Once your access is updated, you can use the models in Bedrock. Refresh the base models table to view the updated statuses.

(Google翻訳)
モデルアクセスの更新が送信されました モデルへのアクセスを受信または削除するには、数分かかる場合があります。 その間、他の Bedrock コンソール ページを使用することもできます。 アクセスが更新されると、Bedrock でモデルを使用できるようになります。 基本モデルのテーブルを更新して、更新されたステータスを表示します。

だそうで

申請直後の一覧の様子

Claude 3 Sonnet が進行中になっている

数分待ったらアクセスが付与されました。

「アクセスが付与されました」に変わる

2.Prompt flowsでフローを作って見る

2-1.フローの作成

①Bedrockのメニューから「Promt flows」を選択

②「Create prompt flow」を選択

記事を書く前に作ったsampleがあるけど気にしないで

③ポップアップで必要事項を入力して「Create」

  • Name:適当に名づける

  • Description:説明。オプションなので空欄でもOK

  • Service role name:このflowを動かすロールの指定。Create and use a new service roleを選びます。

  • KMSキーセレクション:AWS KMSで管理してる別の鍵で暗号化したい場合はカスタマイズを選択。今回はデフォルトのままで

flowが生成され、Difyっぽい画面が出てきます。

Flow inputは必須なので消せないよ

デフォルトで灰色の「Flow inputノード」と黄色の「Flow outputノード」が配置されてるよ。

2-2.フローの構築

編集画面でフローを作っていくよ。

①InputとOutputを直接繋いでみる

まずはデフォルトで配置されているFlow inputノードとFlow outputノードを繋いでみるよ。青い丸の部分をクリックして線を伸ばせるので接続します。

繋いだら画面上部にある「Save」ボタンで保存。
画面の右側にあるチャットウィンドウから動作確認ができるよ。
Input=Outputなので当然同じ言葉が返ってくるね。

もし右側にチャットウィンドウが無い場合は「Save」ボタンの横にある右枠っぽいボタンを押すと開きます。

ここね

②AIモデルを繋いでみる

左側の「Nodes」から「Prompts」をドラッグ&ドロップ
Promptsって名前だけど、実際は使用するLLMのモデルの指定と与える命令を書くためのノードです。

真ん中の紫のヤツね

まず「PromptsノードのOutput」と「Flow OutputノードのInput」を繋ぐ

次に「Flow input Node」と「PromptsノードのInput」を繋ぐ

初期状態ではInputがNot defined(定義されていない)になっているので

そのままでは繋ぐ先が出てきません。
これはPromptsノードで設定を入れることで表示されるようになるよ。

InputがNot defined

Promtsノードを選択すると画面左側に設定画面が表示されるので
ここから設定を行います。

BedrockにはPrompt managementという機能もあって、そこで定義したプロンプトがあればPromptのプルダウンから選ぶことができます。
今回は直接定義するので「Define in node」を選びます。

Define in nodeを選ぶと表示が変わる

「モデルを選択」でこのノードが使うAIモデルを選択します。

Claude 3 Haiku を選択

次にMessage欄でinputの情報とモデルに与える命令を書きます。
「{{test}}」の様に中括弧で要素を囲うと、それがinputとして定義されてノードに表示されます。

{{test}}を書いたらInputにtestが現れた
複数書くとInputも複数になるよ

動作確認のためにMessageに{{test}}とだけ定義してFlow inputノードと繋いだものを用意して「Save」します。

③AIモデルとテスト会話してみる

チャット欄から話しかけてみる。

準備できてないらしい

(私の環境だけの可能性もあるけど)ノード構成を変更した時にSaveだけではテストが動かないみたいで、その時はフローの一覧に表示されているStatusが「Not prepared」(準備できていない)になっているみたいです。

Prompt flowsのトップ画面

そういう時はフローを選択、詳細画面に移動し右上の「Publish version」で今の状態をバージョンに保存できます。
これにより「Not prepared」だったフローのStatusが「Prepared」に変わります。

Preparedになったことを確認したら「Edit prompt flow builder」からフロー編集画面に戻れるので、再びチャット欄からテストしてみます。

testに対してClaude 3 Haiku が返事をしてくれた

ただ入力を渡すだけでは味気ないので、Promptsノードのメッセージを次のように修正して再びセーブ&Publish

ひのもとことば しゃべれよう

さっきと同じように話しかけると

ひのもとことばだ!

次は、入力を2つに増やしてみましょう。
1つめのinput「test」はそのままで、2つめのinputに「language」を追加して指定したlanguageでtestを翻訳してもらいます。

Messageに{{language}}を足すとPromtsノードにも追加されるのでFlow inputノードから接続します。

しかし、このままだとインプットがString型なので1つの文字列しかPromptsノードに渡せません。そこでまずFlow inputノードのTypeをStringからObjectに変更します。

次にPromptsノードのinput要素もObject型を受け付けられるように修正します。

Expressionの部分を「$.data」から「$.data.language」と「$.data.test」に直しました。Expressionにはデフォルトだと「$.data」になってますが、こう書くことで入力Objectの中の何の要素を参照すればいいか分かるようになります。

ここまで変更したら再びセーブ&Publish。再びビルダーに戻ってテストしてみます。

チャット欄に普通にテキストだけを入力すると、InputがObject型に変わっているのでObjectで入力しろとエラーが出ます。

Object型でテストする時は次の様な形で入力します。
{ "test" : "hello", "language" : "Japanese" }

ここで左辺の"test"と”language”は先ほど設定したExpressionの $data.testと $data.languageの部分にあたります。

ちゃんと翻訳されたね

2-3.フローで使えるパーツについて

①Logic系
IteratorとCollectorは反復処理関係、ConditionはIF文+Switch文みたいな分岐を処理できるみたいです。

②Orchestration系
Promptsは上記で使ったようにAIモデルと与える命令文の指定。
AgentsはBedrockで別途作ることのできるAgentを選択出来ます。

③Code
Difyならそのままコードノードで書けるヤツですが、AWSだとLambdaで書く必要あり。また、DifyにあるHTTPリクエストに相当するノードも無いのでそれもLambdaで実装する必要がありそうです。

④Data
Knowledge baseはBedrockの機能にS3においたファイルでRAGを作れるようなもので、RAGを参照させるような機能。
S3 RetrievalとStoregeはそれぞれS3からの取得と保存です。

⑤AI Services & Other
AI Servicesは今現在はLex(AWSで作れるアレクサみたいな会話型インターフェース)のみサポートしていますが、Amazon Qも後々サポートするとか。Otherにあるのは初期配置されてるアウトプットノードです。

3.Prompt flowsをAPIで呼び出してみる

つくったフローはエイリアスを作ることで、外部からAPIとして呼び出すことが出来る様になります。

3-1.エイリアスの作成

「Publish version」の左に「Create alias」というボタンがあるので選択。

ポップアップで適当な名前を入力し、エイリアスとして使うバージョンを選択します。

今の状態で新しくバージョンを作ってエイリアスにするなら
「Prepare and create a new version and associate it to this alias.」
これまでに作ったバージョンから選ぶなら
「Use an existing version to associate this alias.」
を選択しましょう。

エイリアスを作成すると一覧の下の方に追加されています。

3-2.フローとエイリアスのID確認

外部プログラムからAPIでフローを利用するにはフローとエイリアスのIDをそれぞれ指定する必要があるので、先にIDを確認して控えておきます。

一覧から先ほど作成したエイリアスを選択し、詳細画面に行きアドレスバーを確認します。

https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/prompt-flows/「10桁の英数字①」/alias/「10桁の英数字②」/version/13

URLは次の様になっています。

prompt-flowsの後ろの「10桁の英数字①」がフローのID
aliasの後ろの「10桁の英数字②」がエイリアスのIDとなっています。

ちなみにフローのIDはフローの詳細画面のUIからも確認できます。

3-3.アクセスキー&シークレットアクセスキーを取得

ここはBedrockに限った話ではないのですが、外部からAPIを叩くときにはAWSのアクセスキーとシークレットアクセスキーが必要になります。

画面右上のアカウントのところから「セキュリティ認証情報」を選択

画面下部に「アクセスキーを作成」ボタンがあるので選択

今回はローカルからAPIを使いたいので
「AWSの外部で実行されるアプリケーション」を選択

説明タグには何かわかりやすい説明を記載しておきましょう。

アクセスキーとシークレットアクセスキーが生成されたのでCSVをダウンロードするかどこか安全なところに控えておきます。

安全のためこのキーはスクリーンショットを取ったらすぐ消したよ!!
不正利用されるとあぶないからね

3-4.boto3の準備

今回の検証ではpythonを使ってAPIを叩いてみようと思うので、AWSをAPIで操作するためのライブラリであるboto3をインストールしておきます。

pip install -y boto3

3-5.APIから叩くコードを記載

先ほど作った”test”を”language”で翻訳するフローをAPIから呼び出すコードを書きます。

### prompt_flows_sample.py

import boto3

client = boto3.client(
    "bedrock-agent-runtime",
    region_name="us-east-1",
    aws_access_key_id="取得したアクセスキー",
    aws_secret_access_key="取得したシークレットアクセスキー",
    )

response = client.invoke_flow(
    flowIdentifier="取得したフローのID",
    flowAliasIdentifier="取得したエイリアスのID",
    inputs=[
        {
            "nodeName": "FlowInputNode",
            "nodeOutputName": "document",
            "content": {
                "document": {
                    "test": "test",
                    "language": "Japanese"
                }
            }
        }
    ],
)

event_stream = response["responseStream"]
for event in event_stream:
    print(event)

ターミナルから実行してみる。

PS pythonファイルのパス > py .\prompt_flows_sample.py
{'flowOutputEvent': {'content': {'document': 'テスト'}, 'nodeName': 'FlowOutputNode'}}
{'flowCompletionEvent': {'completionReason': 'SUCCESS'}}

ちゃんと入力の「test」が日本語で翻訳されて「テスト」で返ってきてますね。

ちなみにnodeNameとnodeOutputNameは、インプットのノード部分のことだけどビルダー画面では変更できない様になっているので以下で固定でOKっぽいです。

"nodeName": "FlowInputNode",
"nodeOutputName": "document",
ノード名は何故か記載がないし、documentは固定になっている。

あとはPython側でエラーハンドリングと中身を取り出す処理を書いていけばアプリケーション側からPrompt flowsで作ったアプリを呼び出すことができます。

4.おわりに

インフラの人間の癖にAWS系の記事書くの何気にはじめてなの・・・疲れた・・・

最初はAWS上にFargate+Difyを構築して遊んでみようと思ってたんだけど、
最近新しくAWSにもDifyっぽいのが出てきたぞ!と目にしてつい・・・。

今回は触れませんでしたが、同じくBedrockで簡単にRAG的なものを作れるKnowledge baseとの連携や、Lambdaを使ったロジックの作りこみなどがあるので、AIアプリでやりたいことはDifyと同じように出来るんじゃないかと思います。

ただ、Difyと比べるとUIや操作感がかなり残念なので非エンジニアの方にこれ使ってノーコードでアプリ作ってね!と奨めるのは今のところ難しいのかも・・・。

AWS系記事の続きはないかもしれませんが、またどこかでお会いしましょう。ではでは。

【追記】
記事書いてるうちに別の方が記事を上げてくれているのを発見しました。
こちらも分かりやすかったので参考にペタペタ。


【みないで】書く場所が無かった愚痴

いつのまにかExpressionが消えてたりノード切断されてる件

PromptノードのMessageを編集している時に、{{test}}とかを消してしまうと、ノード間で{{test}}と繋がっていた接続が消えてしまうばかりか、Expressionの$.date.testとしていた部分も以降も消えてしまう。
迂闊に変数を消してしまうと繋ぎ直しや書き直しが必要になり非常にめんどくさい。Message内の変更を確定させるまではそこは反映させずに残しておいてほしいなぁ・・・。

Publishバージョンは更新しないとダメなの?

Publishバージョンの更新を、編集する度に行っていたけど、このPublishバージョン、デフォルトだと11個までしか保存できなくてVersion12を超えたら、古いバージョンを消さないと保存ができなかった。完成品にバージョンつけるのはいいけど、ちょっと書き直してテストしたいだけなのにバージョン付ける必要があると不便すぎない?
本来はSaveだけで動くような気がしているのでおま環であって欲しいよね。

ノードの接続を破棄したい・・・

これも判りにくかったんですが、ノード間の接続を解除するには接続している線をクリックして明後日の方向に移動させると書いてあったのですが、
青丸付近をクリックしてもNGだし、線の中央部分をクリックしてもNGで
青丸と線の中央の中間あたりをクリックしないと解除ができません。
最初これが判らなくてノード自体を削除して何度も作り直す羽目に・・・。

Lambda開くの面倒だよぉ

割りとガッツリコードを書くなら吝かでもないんだけど、ちょっとしたコードを書くのにLambdaに移動してコードを作らなきゃならないのはDifyの手軽さに比べてかなりマイナス。権限無視しておいそれとインターネットに出すわけに行かないからWeb検索ノードが無いのも痛い・・・。


この記事が気に入ったらサポートをしてみませんか?