BEACHSIDE BLOG

Azure と GitHub と C# が好きなエンジニアの個人メモ ( ・ㅂ・)و ̑̑

Azure OpenAI の Asynchronous Modified Filter (非同期変更フィルター) で Streaming のレスポンスを劇的改善する

Azure OpenAI でストリーミングのレスポンスを使うと、遅すぎて思ってたのと違うんだが...と思うことありませんか? それを解消する手段の一つが Asynchronous Modified Filter (非同期変更フィルター) です。

Asynchronous Modified Filter (非同期変更フィルター) とは

(前置き) コンテンツフィルターとは

「本家の OpenAI よりレスポンス遅いのなんで」「ストリーミングのレスポンスが本家 OpenAI の API と動きが違ってカックカク」みたいな話を聞きます。その原因として考えられるひとつが、Azure OpenAI Service の機能のひとつ「コンテンツフィルタ―」の影響です。

コンテンツフィルターは Azure OpenAI にデフォルトで備わっている機能で、敵対的なプロンプト (Adversarial Prompting) から守るためのフィルターです。

もう少しかみ砕くと、有害なコンテンツを出力させないようにしたりプロンプトインジェクションやジェイルブレイクから守るためのフィルターです。色々と設定ができますが、詳細を知りたい方は公式ドキュメントが参考になります。

Asynchronous Modified Filter (非同期変更フィルター) とは

コンテンツフィルターのデフォルトの機能だとコンテンツをバッファしてある程度たまったらフィルターします。バッファされた分の文字数がドバっとレスポンスされます。そのため streaming のレスポンスを UI で見るとすごーく微妙に感じます。

Asynchronous Modified Filter は、バッファなしですぐにコンテンツを返します。コンテンツフィルターのチェックは非同期で実行して問題があればちょっと遅れてシグナルを返します。これで本家の OpenAI に近い感じにストリーミングのレスポンスを返すことが可能になります。ずっと Azure OpenAI でデフォルトのコンテンツフィルターを使っていた場合、感動するくらいには変わります (※ 感動するかについては個人差あり)

早くなる理由を書いたのがそのままのデメリットにもなるようなトレードオフもあるので、先ほども紹介したドキュメントの中の "コンテンツストリーミング" のセクション (以下リンク) を確認しましょう。

Asynchronous Modified Filter のコンテンツフィルターをモデル (デプロイ) に適用する

ここからは Asynchronous Modified Filter の適用方法です。

現時点では申請が必要

以下のリンクに「申請ページはこちら」ってところから申請が必要です。

コンテンツフィルターの作成

Azure OpenAI Studio で "コンテンツフィルター" のメニューをクリック → 新規に作成するなら "カスタマイズ済みのフィルターを作成" をクリック。

コンテンツフィルター作成時に、「ストリーミングモード (省略可能) - プレビュー」で、非同期変更フィルター を選択して進めて作成すれば OK です。

モデル (デプロイ) への適用

既存のデプロイに適用するのであれば、Azure OpenAI Studio のメニュー "デプロイ" で対象のデプロイをクリックして "デプロイの編集" をクリックします。

詳細設定オプションの中で、先ほど作成したコンテンツフィルターを選んで保存すれば、あとは普通に使えます。

動作確認

動画取るのめんどかったのでここで載せませんが、通常のコンテンツフィルターでの Streaming のレスポンスを見慣れていた場合、 Asynchronous Modified Filter に変えて初めて Streaming のレスポンスを受け取った私は普通に感動しました。

※ Streaming のレスポンスが早くなると書くと語弊がありそうですが、UI でみるとスムーズに文字が流れるだけなので、トータルのレスポンスが短くなるわけではないです。軽く検証したところ数パーセント早くなる程度でしたので誤差かもくらい) 。 それでも UX は劇的に改善します (と個人的に感じています) 。

実装で気をつけたいポイント

Asynchronous Modified Filter を使ったときに限った話でもないですが、Contents Filter に引っかかったときに正しく処理するよう実装は気を付けましょう。細かい話は以下の公式ドキュメントに書かれています。

自分用に雑に streaming 時に気にすることをざっくりまとめると:

  • HTTP レスポンスステータスコード: 400 返ってきたときにはアウト (プロンプトインジェクションとかでがっつりフィルターに引っかかった場合即400が返るはず)
  • HTTP レスポンスステータスコード: 200 で返ってきたときでも "finish_reason":"content_filter" だったらアウト
    • レスポンスが id が空文字の場合、Prompt annotation message か Annotation message (Contents Filter の結果)。この時に "finish_reason":"content_filter" がくる場合がある。これ時点で streaming は止まる。
    • Streaming のレスポンスで id があるものは Completion token message (Assistant からの回答が入ってるやつ) 。この時はセーフ。