33
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

【Prompt flow入門①】Prompt flowの作成・実行・カスタマイズ方法

Posted at

まえがき

今回は入門ということで、以下の2つのことをまとめています。

  • Prompt flowの作成~実行
  • 簡易的なタスクをPrompt flowで実装

Prompt flowの便利機能には今回触れていません。次回以降まとめていきます。
以下のような便利機能を試していく予定です。

  • マネージドオンラインエンドポイントの作成
  • Variant
  • Bulktest
  • ベクトルDBやSerp APIとの連携

リソース構築

事前作成が必要なもの

  • Azure OpenAI
    • gpt-35-turbo
  • Machine Learning Studioのワークスペース

Azure OpenAIを作成し、上記モデルをデプロイします。エンドポイントとキーをコピーしておきます。
また、下記URLからワークスペースを作成しておきます。

image.png

Prompt flowとAzure OpenAIの接続

Connenctionsタブへ移動し、
image.png

Azure OpenAIをクリックします。
image.png

名前・APIキー・エンドポイントを入力し、Saveをクリックします。
image.png

Prompt flowの作成

左側のメニューからPrompt Flowをクリックし、Createをクリックし、Standard flowを作成します。

image.png
image.png
image.png

初期状態のPrompt flowを確認

image.png

リソース作成直後の状態を確認してみます。画面左側を見てみると、inputとoutputが定義されています。

  • inputの定義:textという変数名でHello World!が格納されます
  • outputの定義:output_promptという変数名でecho_my_prompt.pyの実行結果(return値)が格納されます

画面右側を見ると、「入力~出力の間でデータに対してどのような処理を実行するか 」が可視化されています。
次に、hello_promptとecho_my_prompt.pyの詳細を確認してみます。画面をスクロールすると定義が確認できます。

  • hello_prompt
    • サンプルプロンプトが定義されています
    • ${inputs.text}の値がプロンプト内の{{text}}で展開されています
    • ここには先ほど確認した「Hello World!」という文字列が展開されることになります

image.png

  • echo_my_prompt.py
    • promptflowパッケージからデコレーター:toolをインポートしています
    • デコレーターで修飾した関数をPrompt flowのツールとして利用可能になります
    • 関数の引数はhello_promptの出力となっています

image.png

初期状態のPrompt flowを実行

実行準備は2つです。

  • ランタイムを作成する
  • Azure OpenAIに接続する(上記手順で実施済み)

ランタイムの作成

まずは、コンピューティングリソースを作成します。Add runtimeをクリックします。
image.png

Compute instance runtimeを選択します。
image.png

Create Azure ML compute instanceをクリックします。
image.png

名前を付けてVMのサイズを選択し、Createをクリックします。
image.png

作成されるのを待ちます。
作成後、ランタイムの名前を付け、先ほど作成したコンピューティングリソースを選択すると「認証が必要です」と表示がでます。
Authenticateをクリックし、サインイン画面が表示されたのでAzureアカウントでサインインすると認証はOKとなりました。
image.png

CreateConfirmとクリックし、ランタイムを作成します。
image.png

実行してみる

画面右上にあるRunボタンをクリックします。
image.png

するとフローが実行され、実行が終わるとステータスが表示されます。
image.png

詳細を確認してみる

hello_promptにカーソルを持っていくと、Detailsというボタンが表示されるのでクリックします。
image.png

inputとoutputの情報が展開されますが、画面を右に移動できない(?)のでDetailsの表示が切れてしまっています、、:frowning2:
image.png

hello_promptの定義に詳細情報が表示されているのでこちらから確認してみます。今回のinputは「Hello World!」という文字列です。ちゃんとhello_promptに入力されていることが確認できます。
image.png

echo_my_promptも同じ要領で確認可能です。

Prompt flowのカスタマイズ

今回は簡易的に以下のようなタスクを例にフローを作成してみます。

  • タスク:
    • Function calling用の関数のメタデータをJSON形式で生成する
  • フロー:
    • ①ユーザの入力からJSON形式の文字列を出力
    • ②PythonでJSON形式の文字列をパースして出力

出力をFunction callingで利用するのであれば文字列でいいので②は必要ありませんが、Prompt flowのお勉強という名目なので無駄な処理を足しています。

最終的に出来上がったフロー

image.png

入出力のイメージ

# 入力
社内情報を検索したい。

# 出力
{
    "name": "search_file",
    "description": "社内情報を検索する",
    "parameters": {
        "type": "object",
        "properties": {
            "query": {
                "type": "string",
                "description": "ファイル検索のクエリ"
            },
            "source":{
                "type": "string",
                "enum": ["Fileserver, Database"]
            }
        },
        "required": ["query", "source"]
    }
}

LLMの追加

さきほどの初期状態のフローですが、Azure OpenAIが登場していません。文字列を入力して、その文字列をそのまま出力しています。
ここにAzure OpenAIを組み込むことで、入力から何らかの文字列を生成することが可能になります。

LLMボタンをクリックします。
image.png

すると、画面左側に詳細な定義情報、画面右側にコンポーネントが追加されます。後ほどこれを編集していきます。
image.png

inputとプロンプトの変更

inputを変更します。名前をuser_inputにし、値をSlackに任意のメッセージを送りたいとしました。
image.png

hello_promptを編集し、JSON文字列生成用にします。
ペンマークを押して名前をjson_promptに変更し、プロンプトを書き換えました。
image.png

書き換え後のプロンプト
system:
- あなたはJSONを出力するAIです。
- ユーザの入力に適切に答えられるよう、ステップバイステップで慎重に考えることができます。

user:
# ゴール
- ユーザの入力に対して、JSON形式の出力を行うこと

# 出力例
\```  (バックスラッシュは必要ありません。)
{
    "name": "search_file",
    "description": "社内情報を検索する",
    "parameters": {
        "type": "object",
        "properties": {
            "query": {
                "type": "string",
                "description": "ファイル検索のクエリ"
            },
            "source":{
                "type": "string",
                "enum": ["Fileserver, Database"]
            }
        },
        "required": ["query", "source"]
    }
}
\```  (バックスラッシュは必要ありません。)

# 条件
- JSONはマークダウン形式のコードブロックとして出力すること

入力:{{text}}

chatタイプのモデルを使用するときは、以下のような書式にする必要があります。

systems:
#システムメッセージ

assistant:
#モデルの返答

user:
#ユーザの入力

修正後の定義を確認します。inputsの変数名はtextのままで、Valueを${inputs.user_input}に変更しています。
image.png

LLMの編集

json_promptの出力をLLMに渡して出力を生成する」というフローを作成していきます。
手順はさきほどと大体同じですが、LLMの場合はモデルの情報を設定する必要があります。

  • (名前を変える)
    • json_generatorとしました。
  • モデルの情報を編集
    • どのリソースのどのモデルを使うか指定
    • その他パラメータを指定
  • Promptを定義する
    • 変数展開のみのプロンプトを記述
  • Inputsを編集する
    • inputsを追加する際は、Validate and parse inputをクリックする必要があります
    • さきほど定義したjson_promptの出力を指定

image.png

JSONをパースする関数を作成・outputを変更

モデルの出力を整形するための関数を作成します。処理の中身は単純で、必要な情報を抽出してPython内で扱える辞書型に変換するだけです。

  • 「```生成されたJSON文字列```」の形式にマッチする部分を探す
  • マッチした部分を取り出し、JSONとしてパース
from promptflow import tool
import json
import re
from typing import Any, Union, Dict, List

@tool
def parse_json(input1: str) -> Union[Dict, List, Any]:
    extracted_str = _extract_code(input1)
    return json.loads(extracted_str)


def _extract_code(text: str) -> str:
    triple_match = re.search(r'```(?:\w+\n)?(.+?)```', text, re.DOTALL)
    return triple_match.group(1).strip()

フローの定義の編集については、先ほどと大体同じ手順です。

  • 名前を変える
  • コードを修正する
  • inputsのValueを変更する

image.png

さらに、outputを編集する必要があります。関数名を変更したため、変更後の関数の出力を参照するように変更します。(自動で反映されていました。自動反映されていない場合もあった気が、、)

image.png

実行してみる

Runボタンをクリックし、実行ステータスをチェックします。
すべてCompletedとなっているのでよさそうですね。
image.png

出力(outputsの中身)を確認してみると以下のような結果となりました。
JSON形式で出力してくれています。また、「Slackにメッセージを送りたい」と入力しただけですが、チャネル名に該当する引数も必要だと判断してくれています。

# 入力
Slackに任意のメッセージを送りたい。

# 出力
{
    "description": "Slackにメッセージを送信する",
    "name": "send_slack_message",
    "parameters": {
      "properties": {
        "channel": {
          "description": "送信するチャンネル名",
          "type": "string"
        },
        "message": {
          "description": "送信するメッセージ",
          "type": "string"
        }
      },
      "required": [
        "message",
        "channel"
      ],
      "type": "object"
    }
}

まとめ

Prompt flow内でPythonの関数を簡単に使用できるのはめちゃくちゃ使える機能だと思いました。
モデルの出力整形やエラーハンドリング、その他様々な処理を簡単に組み込めますね。

主観ですが、LLMアプリケーションを開発する上で以下2つは重要な要素だと考えています。

  • ①プロンプトに埋め込むためのデータの収集・加工
  • ②プロンプトエンジニアリング

Python関数とPrompt flowの便利機能を組み合わせることで①②の実装が楽になりそうです。
また、管理・評価の面に関しても機能が充実してそうなので次回は便利機能を色々と試していきますー。

参考

上位概念から丁寧にまとめられているため非常に参考になります。

33
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
33
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?