このエントリは2024/07/01現在の情報に基づいています。将来の機能追加や変更に伴い、記載内容からの乖離が発生する可能性があります。
これは以下のエントリの続き。
結論から言うと、2024/07/01現在、高レベルAPIによるLangChain4j (LC4J) との統合は実現していないので、コードを入手してから、Dynamic SessionsにREST APIで投げ込む必要がある。
手順は以下の通り。
- Dynamic Sessionsを作成する
- Azure OpenAI Service (AOAI) にコードを生成させる
- 管理用Endpointに対し、2で生成したコードをREST APIで投げ込む
- 結果を取得する
今回も例によってMicronautで実装する。QuarkusやSpring Bootでも基本的なお作法は同じ。
1. Dynamic Sessionsを作成する
これは前回のエントリと同じなので省略。
2. Azure OpenAI Service (AOAI) にコードを生成させる
これは以下のGraalVMを使った実行エンジンのエントリで使ったプロンプトと同じもので生成させることにする。
JSONで出力してほしいので、JSONモードでChatLanguageModelを作成しておく点も同じ。
AzureOpenAiChatModel.builder()
.endpoint(AZURE_OPENAI_ENDPOINT)
.apiKey(AZURE_OPENAI_KEY)
.deploymentName("gpt-4o")
.temperature(0.0)
.logRequestsAndResponses(true)
.responseFormat(new ChatCompletionsJsonResponseFormat())
.maxRetries(3)
.build();
3. 管理用Endpointに対し、2で生成したコードをREST APIで投げ込む
前回のエントリにも記載した通り、
- このAPIの認証方式はEntra ID認証のみ
- Authorization HeaderにはBearerトークンをつける必要がある
なので、Azure Container Apps (ACA) のSystem assigned Managed Identityを使うことにする。アプリケーション、AOAI、Dynamic Sessions間の構成は以下のような構成。

REST Endpointに対して、POSTで投げ込む。MicronautのHTTP Clientだろうが何でもいいが、Bearer tokenを取得できるようにしておく必要がある。
public String getAccessToken() {
DefaultAzureCredential defaultAzureCredential = new DefaultAzureCredentialBuilder().build();
TokenRequestContext tokenRequestContext = new TokenRequestContext().addScopes("https://dynamicsessions.io/.default");
return defaultAzureCredential.getToken(tokenRequestContext).map(AccessToken::getToken).block();
}
セッション識別子 (session identifier) はアプリケーションセッションごとに分けておくとよいが、テスト目的であれば、特定の識別子でかまわない。識別子の仕様は以下の通り。
The identifier must be a string that is 4 to 128 characters long and can contain only alphanumeric characters and special characters from this list: |, -, &, ^, %, $, #, (, ), {, }, [, ], ;, <, and >.
セッション識別子 / Session identifiers
識別子は、4 文字から 128 文字の文字列である必要があり、この一覧 (|、-、&、^、%、$、#、(、)、{、}、[、]、;、<、>) の英数字と特殊文字のみを含められます。
https://learn.microsoft.com/azure/container-apps/sessions?tabs=azure-cli#session-identifiers
ACAのConsumption Profileのみを使う場合、外部アクセス用のPublic IPが構成されているが、Workload ProfileでIngressをカスタムVNetに閉じる場合、明示的にNAT Gatewayを立てておくとトラブルシュートの点で便利。
REST APIで投げ込むJSONは、以下のスキーマに従う。
{
"properties" : {
" codeInputType": "Inline | InlineBase64 | InlineText",
"executionType": "Synchronous"
"code" : "実行コード (Python)"
}
}
4. 結果を取得する
結果は以下の形式で出てくる。もしPythonコードでprintで結果表示している場合には、stdoutに結果が表示される。下記は10番目のフィボナッチ数の計算結果。
{
"$id": "1",
"properties": {
"$id": "2",
"status": "Success",
"stdout": "",
"stderr": "",
"result": 55,
"executionTimeInMilliseconds": 29
}
}