Agent Builderだけでは動かせない、ChatKitを使うとできること2選!

Agent Builderだけで全て完結できると分かりやすいのですが、そういう訳にもいかないみたいです。

Agent BuilderのToolsのメニューにChatKitというカテゴリがあります。そこに含まれるClient ToolはAgent BuilderだけではなくChatKitを使わないと動かせません。

Widget Builderを使うとボタン付きのウィジェットを作れますが、Agent Builderだけではボタンをクリックしても何もおきません。ボタンをクリックした際の処理を動かすにはChatKitが必要です。

今回はClient Toolの動かし方とウィジェットのアクションの動かし方を解説します。

Client Tool

Client Toolとは?

Client Toolはブラウザに処理を委譲します。エージェントの処理中にブラウザへ何かを反映したい場合に使えます。サンプルで紹介されているのはテーマの変更です。本記事でもテーマ変更を例に解説します。

AgentノードにClient Toolを登録する

AgentノードのToolsからClient Toolをクリックすると、以下のような画面が表示されます。JSONで関数の定義を記述します。記述の仕方はFunction Callingの定義と同じです。

Client Toolで動かす関数が作成済みであればAIでJSON定義を作成することもできます。サンプル(openai-chatkit-starter-app)のChatKitPanel.tsxのonClientToolに以下のコードがあります。

if (invocation.name === "switch_theme") {
  const requested = invocation.params.theme;
  if (requested === "light" || requested === "dark") {
    if (isDev) {
      console.debug("[ChatKitPanel] switch_theme", requested);
    }
    onThemeRequest(requested);
    return { success: true };
  }
  return { success: false };
}

ポップアップの Generate ボタンを押すと表示される入力欄に上記のコードを入力して Create ボタンをクリックするとJSONが作成されます。

ChatKitで動かす

ChatKitでエージェントを動かす方法は前の記事を参考にしてください。

「ダークテーマに変更してください。」と指示すると……

ダークテーマに変更されました!

ウィジェットのアクション

Widget Builderでは簡単にボタンを持つウィジェットを作成することができます。しかし、このボタンをクリックしても何もおきません。OpenAIのページにはonActionを実装すればアクションを処理できると書いてあるのですが、そのままでは動きません。

アクションが動く場所

実はアクションが動く場所には2つあります。

動く場所ChatKit実装場所
サーバー側chatkit-pythonChatKitServerのaction
クライアント側chatkit-jsWidgetOptionのonAction

Widget Builderで作ったウィジェットはサーバー側で動くようになっています。そのため、クライアント側の実装であるonActionに処理を書いても動きません。

ウィジェットのActionをクライアント側で動かす方法

ポイントは .widget のActionConfigです。Widget Builderでダウンロードした .widget を開くと以下のようなコードになっています。actionに handler: "client" を追加することでクライアント側で動くようになります。 handler: "client" を追加して保存した .widget ファイルをAgentノードにアップロードしてください。

<Card
  size="sm"
  padding={0}
  confirm={{
    label: "OK",
    action: {
      type: "agent.flight.confirm",
      payload: {
        decision: "ok",
        flightNumber,
        departureCity,
        departureTime,
        arrivalCity,
        arrivalTime,
      },
    },
  }}
  cancel={{
    label: "NG",
    action: {
      type: "agent.flight.confirm",
      payload: {
        decision: "ng",
        flightNumber,
        departureCity,
        departureTime,
        arrivalCity,
        arrivalTime,
      },
    },
  }}
>

ActionConfigについて

ActionConfigには2つのプロパティがあります。アクションを処理するにはこの2つのパラメータが重要です。

プロパティ内容
typeActionを識別する文字列
payloadウィジェットから送信される値

Actionを処理するコード

クライアント側(chatkit-js)

クライアント側の実装ではWidgetsのonActionに処理を記述します。

  const chatkit = useChatKit({
~中略~
    widgets: {
      onAction: async (action, widgetItem) => {
        if (action.type == "agent.flight.confirm") {
          if (action.payload?.decision == "ok") {
            await sendUserMessageRef.current?.({
              text: `承認しました。`,
            });
          }
        }
      },
    },
~中略~
  });

サーバー側(chatkit-python)

ChatKitServerにactionメソッドを実装します。

    async def action(
        self,
        thread: ThreadMetadata,
        action: Action[str, Any],
        sender: WidgetItem | None,
        context: RequestContext,
    ) -> AsyncIterator[ThreadStreamEvent]:
        if action.type == "agent.flight.confirm":
            if action.payload['decision'] == 'ok':

                # ユーザーメッセージ 
                result_item=UserMessageItem(
                    id = _gen_id("msg"),
                    thread_id = thread.id,
                    created_at = datetime.now(),  
                    type="user_message",
                    content=[
                        UserMessageTextContent(
                            type="input_text",
                            text="承認しました。"
                        )
                    ],
                    inference_options=InferenceOptions(
                        tool_choice=None,
                        model=None,
                    )
                )

                # スレッドにアイテムを追加
                yield ThreadItemAddedEvent(
                    type="thread.item.added",
                    item=result_item
                )

                # スレッドの完了
                yield ThreadItemDoneEvent(item=result_item)

まとめ

ChatKitを使わないと動かせない機能2つをご紹介しました。Client Toolを使えばブラウザを操作できます。アクションを使えばエージェントでユーザーの入力を受け付けることができます。

どちらもOpenAIのページに記述はあるのですが、完全ではないためそのまま真似しても動きません。動かすのに苦労している人の参考になればと思います。

この記事を書いた人
新技術基盤開発室の鈴村です。生成AIに関する技術調査を行っており、最近はAI駆動開発に興味があります。開発にAIを活用する方法を模索中。
新技術基盤開発室の鈴村です。生成AIに関する技術調査を行っており、最近はAI駆動開発に興味があります。開発にAIを活用する方法を模索中。
>お役立ち資料のダウンロード

お役立ち資料のダウンロード

ブログでは紹介しきれないシステム開発や導入におけるケーススタディを資料にまとめました。お気軽にダウンロードください。

CTR IMG