1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AppsSDKを使ってみた

1
Posted at

AppsSDKとは

ChatGPT内でアプリを作成するためのSDKです。
今までもMCPでアプリ作成ができていましたが、AppsSDKを使うとウィジェットを表示することができます。以下に紹介動画があります。

仕組み

AppsSDKはMCPのmetaデータを拡張することで実現しています。

widget_resource = _embedded_widget_resource(widget)
meta: Dict[str, Any] = {
    "openai.com/widget": widget_resource.model_dump(mode="json"),
    "openai/outputTemplate": widget.template_uri,
    "openai/toolInvocation/invoking": widget.invoking,
    "openai/toolInvocation/invoked": widget.invoked,
    "openai/widgetAccessible": True,
    "openai/resultCanProduceWidget": True,
}

return types.ServerResult(
    types.CallToolResult(
        content=[
            types.TextContent(
                type="text",
                text=widget.response_text,
            )
        ],
        structuredContent={"pizzaTopping": topping},
        _meta=meta,
    )
)

各metaデータについては https://developers.openai.com/apps-sdk/reference/ を参照してください。 "openai.com/widget"にウィジェットのHTMLが含まれています。

動作イメージ

以下がAppsSDKの動作イメージとなります。まずMCPサーバと通信(1)を行いmetaデータ内にあるwidgetをみてWebリソースを取得(2)する流れです。

apps_sdk.drawio.png

そのため、サーバは2つ(MCPサーバ・Webサーバ)必要となります。
MCPサーバはngrokで構築し、WebサーバはS3+CloudFrontで構築しました。(S3 静的ウェブサイトホスティングではうまくいきませんでした)

動かしてみた

公式サンプルは難しかったので改変しながら動かしました。最終的なコードは以下にあります。

正常に動くと以下のような動作になります。

apps_sdk0.png

ウィジェットでできること

呼び出しパラメータを取得する

ウィジェットが呼び出された時のパラメータを取得することができます。
toolInputにはChatGPTから入力されたデータが入り、toolOutputはMCPサーバで処理した結果が入ります。

const inputParam = useOpenAiGlobal("toolInput") || "default value";
const outputParam = useOpenAiGlobal("toolOutput") || "default value";
return (
  <div>
    <p>Sample View1</p>
    <p>
      toolInput parameter: <strong>{JSON.stringify(inputParam)}</strong>
    </p>
    <p>
      toolOutput parameter: <strong>{JSON.stringify(outputParam)}</strong>
    </p>

apps_sdk1.png

他のツールを呼び出す

ウィジェットから他のツールを呼び出すことも可能です。以下はsample-view2ツールを呼び出すコードです。

function callToolSampleView(name, message){
  console.log("callToolSampleView name:", name, "message:", message);
  window.openai?.callTool(name, { message }).then((response) => {
    console.log("response:", response);
    setSampleViewResponse(response["structuredContent"]["message"]);
  }).catch((error) => {
    console.error("error:", error);
  });
}

 省略 
<Button
  variant="contained"
  onClick={() => callToolSampleView("sample-view2", "Sample View1から呼び出し")}
  >
  CallTool
</Button>
<p>
  Sample View Response: <strong>{JSON.stringify(sampleViewResponse)}</strong>
</p>
      

sample-view2ツールのコードです。

async def _call_tool_request(req: types.CallToolRequest) -> types.ServerResult:

 省略 

    text = f"identifier : {widget.identifier}, message : {payload.message}"

 省略 

    return types.ServerResult(
        types.CallToolResult(
            content=[
                types.TextContent(
                    type="text",
                    text=widget.response_text,
                )
            ],
            structuredContent={
                "message": text,
            },
            _meta=meta,
        )
    )

動作させた結果

apps_sdk2.png

ChatGPTへメッセージを入力する

ウィジェットからChatGPTへメッセージを入力することも可能です。

function sendFollowUpMessage(message){
  console.log("sendFollowUpMessage message:", message);
  window.openai?.sendFollowUpMessage({ prompt: message }).then((response) => {
    console.log("response:", response);
  }).catch((error) => {
    console.error("error:", error);
  });
}

 省略 

<Button
  variant="contained"
  onClick={() => sendFollowUpMessage("日本の有名な観光地を教えてください。")}
  >
  Send Follow-Up
</Button>

Send Follow-Upボタンを押すと以下のようになります。

apps_sdk3.png

最後に

今後作成したアプリは申請が行えるようになるみたいです。申請が通ったアプリはどのように一般公開されるのか?MCPサーバやHTMLリソースの格納場所はどうなるのか?など気になります。アプリ申請が始まったら調べてみようと思います。
いずれにせよアプリが多くなることでChatGPTが視覚的に使いやすくなるため楽しみです。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?