Gemini APIでチャット２ (返答の安全性を制御する)

# 概要

Gemini APIを使ったチャットボットの作成で，[前回](https://qiita.com/AzukiImo/items/eedef182a88d6681b958)に続く内容です．会話の履歴を保存しつつ対話が続くところまででした．ここで問題になっていたのが，入力する内容によっては，返答されず，次のようなメッセージが表示され，終了してしまうことがありました．返答文に何らか問題がある場合に表示されるようです．




~~~:「あつい」の返答でなぜかエラー
finish_reason: SAFETY
safety_ratings {
  category: HARM_CATEGORY_SEXUALLY_EXPLICIT
  probability: MEDIUM
}
safety_ratings {
  category: HARM_CATEGORY_HATE_SPEECH
  probability: NEGLIGIBLE
}
safety_ratings {
  category: HARM_CATEGORY_HARASSMENT
  probability: NEGLIGIBLE
}
safety_ratings {
  category: HARM_CATEGORY_DANGEROUS_CONTENT
  probability: NEGLIGIBLE
}
~~~
今回は，この表示をコントロールする方法になります．

### 制御方法

制御方法は，```generate_content()``` や ```send_message()``` 関数で文章を生成するオプションに，```safety_settings``` を追加すればOKです．

:::note
send_message()でメッセージを生成する時，オプションとして次を指定します．
~~~
safety_settings={
    HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT : HarmBlockThreshold.BLOCK_NONE,
    HarmCategory.HARM_CATEGORY_HATE_SPEECH : HarmBlockThreshold.BLOCK_NONE,
    HarmCategory.HARM_CATEGORY_HARASSMENT : HarmBlockThreshold.BLOCK_NONE,
    HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT : HarmBlockThreshold.BLOCK_NONE
}
~~~
:::



# 安全性フィルター

Gemini API は，フィルターカテゴリを使用して，特定の種類のコンテンツを制限または許可できるようです．メッセージを生成する際に安全性を損なう可能性があると判断されると，上記のようなエラーメッセージが表示されるようです．この安全性を担保するような仕組みは，フィルターの値を調整することができるみたいです．


詳細は[こちら](https://ai.google.dev/gemini-api/docs/safety-settings?hl=ja)に記載されています．

https://ai.google.dev/gemini-api/docs/safety-settings?hl=ja

フィルターの値，具体的には下記の表の閾値を利用することで，ブロックする内容をある程度コントロールできるようです．
一旦，すべてを **BLOCK_NONE** にして徐々にブロックするもよし，逆に，少しずつブロックを緩める方針もよし．好みに応じて，閾値を設定してください．ただ，すべてブロックなしにすると，会話は続くのですが，有用な情報が返答されない！というケースも起こり得ます．


|概要   | 	閾値（API）| 	説明 |
|--------------------------|-----------------|------|
|ブロックなし| 	BLOCK_NONE| 	安全でないコンテンツの確率に関係なく、常に表示されます
|少量をブロック| 	BLOCK_ONLY_HIGH | 	安全でないコンテンツの可能性が高いときにブロックする
|一部をブロック |	BLOCK_MEDIUM_AND_ABOVE | 	安全でないコンテンツの確率が中程度または高い場合にブロック
|ほとんどをブロック| 	BLOCK_LOW_AND_ABOVE |	安全でないコンテンツの確率が低、中、高の場合はブロック
|なし| 	HARM_BLOCK_THRESHOLD_UNSPECIFIED |	閾値が指定されていません。デフォルト閾値を使用してブロックします

安全性のフィルターカテゴリはエラーメッセージに記載されている**HARM_CATEGORY_** で始まる4種類となります．閾値の値は表に記載の5種類でコントロール可能です．デフォルトの状態は設定なしのようです．

指定の方法は，```HarmCategory.HARM_CATEGORY_xxx_xxx : HarmBlockThreshold.BLOCK_NONE ```という辞書形式で指定することになります．具体的には，次のようなコードになります．メッセージを生成する関数のオプションとして指定します．




~~~Python: 修正部分
text = input("ユーザー >>>")

# ここがメインの変更点．safety_settings オプションを追加します．
response = chat.send_message(
    text, 
    safety_settings={
        HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE,
        HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE,
        HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_NONE,
        HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT:HarmBlockThreshold.BLOCK_NONE
        })

print(response.text)
~~~

safty_settingsオプションは、履歴を用いない返答にも利用でき，
```response = model.generate_content(text, safty_settings={設定内容})``` とすることでフィルターが有効になります．必要に応じて使い分けられるようです．




# 最終的なコード

ブロックをNONEにしたサンプルを最後に紹介して終わります．


~~~Python:sample_chap.py
import google.generativeai as genai
from google.generativeai.types import HarmCategory, HarmBlockThreshold

API_KEY = '12345abcde' 
genai.configure(api_key=API_KEY)
model = genai.GenerativeModel("gemini-1.5-flash")  # モデルは 1.5-flash
chat = model.start_chat(history=[])                # ここで履歴を使う指定をする

while True:
    text = input("ユーザー >>>")
    response = chat.send_message(text, 
								 safety_settings={
								 HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT:HarmBlockThreshold.BLOCK_NONE,
								 HarmCategory.HARM_CATEGORY_HATE_SPEECH:HarmBlockThreshold.BLOCK_NONE,
								 HarmCategory.HARM_CATEGORY_HARASSMENT:HarmBlockThreshold.BLOCK_NONE,
								 HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT:HarmBlockThreshold.BLOCK_NONE
                                 })
    print(response.text)
~~~

次回は，下記のようなブラウザで文字入力できるようなものを作ってみたいと思います．AIの返答に何故か顔文字があり気になりますが，ちゃんと数式の計算もしてくれるみたい．

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3725285/5987856f-bf88-7ad9-444b-4693c4c0a099.png" width=50%>

ただ，これを作成するくらいなら，Geminiを直接利用したほうがいいですが:sweat:

## 前回の内容

https://qiita.com/AzukiImo/items/eedef182a88d6681b958