Azure OpenAI ServiceのコンテンツフィルタをTerraform管理する方法

この記事は[生成AI Advent Calendar 2024](https://qiita.com/advent-calendar/2024/kagai)の22日目の記事です。

このカレンダーでは1日目にもAzureの記事を書いています。
1日目記事：[trec_evalを用いてAzure AI Searchの検索精度を評価する](https://qiita.com/uchunanora/items/774804b5992afffdc516)

# はじめに
Azure OpenAI Service（AOAI）には、コンテンツフィルタという不適切な表現に関するフィルタリング機能がデフォルトで有効になっています。
しかしデフォルトのままでは、一般的な表現でも不適切と見なされエラーを吐くことが多々あります。
そこでTerraformでコンテンツフィルタを管理しようとしたところ、`azurerm`で対応しておらず困りました...。
なので本記事では、`azapi`を用いてAOAIのコンテンツフィルタをTerraform定義する方法を解説します。


# Azure OpenAI Service（AOAI）のコンテンツフィルタとは？

https://learn.microsoft.com/ja-jp/azure/ai-services/openai/concepts/content-filter?tabs=warning,user-prompt,python-new

AOAIのコンテンツフィルタは、不適切なコンテンツが生成されるのを防ぐための仕組みです。
以下の4つのカテゴリに関して、コンテンツを4つの重大度レベル（安全、低、中、高）に分類し、それに基づき入力されたプロンプトや出力を抑制します。
| カテゴリ |  |
|:-|:-|
|Hate   | 憎悪や偏見を含む表現  |
|Sexual   | 性的な暗示や露骨な表現  |
|Violence   | 自傷行為等に関連する表現  |
|Self-harm   | 暴力的な描写や脅迫を含む表現 |

各カテゴリのフィルタは以下のパラメータで制御されます。
| パラメータ |  |
|:-|:-|
| blocking  | コンテンツをブロックするかどうか  |
| severityThreshold  | フィルタの感度（ex. 低, 中, 高）  |
| source  | フィルタの対象（ex. 入力, 出力）  |

これらを適切に設定することで、AOAIが不適切なコンテンツを出力しないようにし、安全に運用することができます。


# コンテンツフィルタのTerraform管理
現時点では、AOAIのコンテンツフィルタはAPIのプレビュー版でしか作成できず、残念ながら`azurerm`プロバイダはAOAIのコンテンツフィルタをサポートしていません。
いまのところ`azapi`を使用するしかなさそうですね。`2023-06-01-preview`以降のバージョンなら良さそう。

重大度が`High`のコンテンツだけをフィルタリングするTerraform定義が以下です。
`High`のコンテンツだけフィルタするので、`Low`や`Medium`レベルのそこまで危険ではないコンテンツだけが表示されます。

```terraform
resource "azapi_resource" "content-filter-policy" {
  type                      = "Microsoft.CognitiveServices/accounts/raiPolicies@2024-10-01"
  name                      = "HighOnlyFilter"
  parent_id                 = azurerm_cognitive_account.example.id
  schema_validation_enabled = false
  body = {
    displayName = ""
    properties = {
      basePolicyName = "Microsoft.Default"
      type           = "UserManaged"

      contentFilters = [
        # プロンプト入力のフィルタ
        { name = "Hate", blocking = true, enabled = true, severityThreshold = "High", source = "Prompt" },
        { name = "Sexual", blocking = true, enabled = true, severityThreshold = "High", source = "Prompt" },
        { name = "Selfharm", blocking = true, enabled = true, severityThreshold = "High", source = "Prompt" },
        { name = "Violence", blocking = true, enabled = true, severityThreshold = "High", source = "Prompt" },

        # 生成された内容のフィルタ
        { name = "Hate", blocking = true, enabled = true, severityThreshold = "High", source = "Completion" },
        { name = "Sexual", blocking = true, enabled = true, severityThreshold = "High", source = "Completion" },
        { name = "Selfharm", blocking = true, enabled = true, severityThreshold = "High", source = "Completion" },
        { name = "Violence", blocking = true, enabled = true, severityThreshold = "High", source = "Completion" }
      ]
    }
  }
}
```

`severityThreshold`に設定する値で何が出力されるのか分かりにくいですが要は以下です。
|  | | |
|:-:|:-:|:-: |
| Low  | Medium  | High
| 少しでも危険なものは出力しない  | 中間  | 非常に危険なものだけをフィルタリングして、それ以外は出力する |

また注意点として、`blocking = true`はフィルタ自体をかけないという設定ですが、こちらはAzureに申請をしてからではないと、フィルタをオフにできないようです。

# おわりに
今回は、Terraformを使用してAzure OpenAI Serviceのコンテンツフィルタを設定する方法について解説しました。
AzureのTerraformの情報は意外と少ないので、こういうニッチな情報も備忘録として残していきたいです。