GEMINI LABEN
DESKTOP — Gemini の Windows デスクトップ版が出ました。Windows 10 以降に対応し、Alt + Space でどの画面からでも呼び出せます0.59.0 — Gemini CLI の現在の安定版はこれです。v0.60 と v0.61 は nightly と preview だけで、安定版タグはまだ出ていません9/30 — gemini-omni-flash-preview の停止まで残り16日です。後継の gemini-omni-1.1-flash は video_config に resolution が加わっており、ID を差し替えるだけでは済まない場合があります429 — fileData に外部 URL の画像や PDF を渡すと、クォータを 0.03% しか使っていなくても 429 が返る報告が続いています。テキストだけなら通りますNEW — Drive の原稿を直して聞き直したら、Gemini が直す前の文を返してきました。取り込みの癖と、再添付を決める基準を書きましたSAFETY — 小説の翻訳で PROHIBITED_CONTENT が続くとき、閾値を下げれば通る話と、下げても通らない話があります。その境目を先に見分けたいところですDESKTOP — Gemini の Windows デスクトップ版が出ました。Windows 10 以降に対応し、Alt + Space でどの画面からでも呼び出せます0.59.0 — Gemini CLI の現在の安定版はこれです。v0.60 と v0.61 は nightly と preview だけで、安定版タグはまだ出ていません9/30 — gemini-omni-flash-preview の停止まで残り16日です。後継の gemini-omni-1.1-flash は video_config に resolution が加わっており、ID を差し替えるだけでは済まない場合があります429 — fileData に外部 URL の画像や PDF を渡すと、クォータを 0.03% しか使っていなくても 429 が返る報告が続いています。テキストだけなら通りますNEW — Drive の原稿を直して聞き直したら、Gemini が直す前の文を返してきました。取り込みの癖と、再添付を決める基準を書きましたSAFETY — 小説の翻訳で PROHIBITED_CONTENT が続くとき、閾値を下げれば通る話と、下げても通らない話があります。その境目を先に見分けたいところです
記事一覧/高度な活用
高度な活用/2026-09-14中級

BLOCK_NONE を入れても結果が変わらないとき — Gemini のブロックを閾値で動かせるかどうかの見分け方

安全フィルタで止まったとき、閾値を緩めて直る場合と、何をしても直らない場合があります。返ってきたレスポンスのどこを見て、その境目を先に判定するかをまとめました。

Gemini API239safetySettingsエラー診断コンテンツフィルタ運用設計15

浮世絵の壁紙アプリで、各作品に添える短い解説文を別の言語へ広げていたときのことです。武者絵の、合戦の場面を描いた数点だけが、応答が空のまま返ってまいりました。

そのときの私は、安全フィルタが厳しすぎるのだろうと考えました。ですから safetySettings に四つのカテゴリを並べ、すべて BLOCK_NONE を指定して、同じバッチをもう一度流しました。

結果は、一文字も変わりませんでした。同じ数点が、同じように空で返ってきたのです。

そこでようやく、レスポンスの中身を開いて読みました。止まっていた場所は、私が緩めたつもりのフィルタではありませんでした。

止まったのがプロンプト側か、応答側かを最初に分ける

Gemini のレスポンスには、ブロックの情報が二か所に入ります。

ひとつは promptFeedback です。ここに blockReason が入っていた場合、入力そのものが弾かれており、候補はひとつも返りません。公式リファレンスの blockReason の説明は「If set, the prompt was blocked and no candidates are returned. Rephrase the prompt.」となっております。ドキュメントが最初に勧めているのは閾値の調整ではなく、プロンプトの書き直しなのです。

もうひとつは候補側の finishReasonsafetyRatings です。応答の生成は始まったものの途中で止められた場合は、こちらに理由が入ります。finishReasonSAFETY であれば safetyRatings を見てどのカテゴリで止まったかを確かめられる、と安全設定のガイドに書かれています。

この二つを混ぜて眺めていると、いつまでも原因にたどり着けません。私はまず、どちらで止まったかだけを返す関数を置きました。

from google import genai
from google.genai import types
 
client = genai.Client()
 
# 調整可能フィルタに由来する blockReason は SAFETY だけです。
ADJUSTABLE = {"SAFETY"}
NORMAL_FINISH = {"STOP", "MAX_TOKENS"}
 
 
def classify_block(response):
    """(動かせるか, 止まった場所, 理由) を返します。"""
    fb = getattr(response, "prompt_feedback", None)
    reason = None
    where = None
 
    if fb is not None and getattr(fb, "block_reason", None) is not None:
        reason = fb.block_reason.name          # 例: PROHIBITED_CONTENT
        where = "prompt"
    else:
        candidates = response.candidates or []
        if not candidates:
            return ("unknown", "response", "NO_CANDIDATES")
        finish = candidates[0].finish_reason
        reason = finish.name if finish is not None else "UNSPECIFIED"
        where = "response"
        if reason in NORMAL_FINISH:
            return ("not_blocked", where, reason)
 
    movable = "adjustable" if reason in ADJUSTABLE else "core"
    return (movable, where, reason)
 
 
resp = client.models.generate_content(
    model="gemini-3.8-flash",
    contents="(ここに実際の入力)",
)
print(classify_block(resp))

私の場合、返ってきたのは ("core", "prompt", "PROHIBITED_CONTENT") でした。閾値をいくら動かしても届かない側です。

blockReason の値は、二つの層に分かれています

blockReason の取りうる値は、API リファレンスに六つ挙がっております。そのうち調整可能なフィルタに由来するものは、ひとつだけです。

公式の説明(要旨)safetySettings で動くか
SAFETY安全上の理由でブロック。どのカテゴリかは safetyRatings で確認動きます
PROHIBITED_CONTENT禁止コンテンツによるブロック動きません
BLOCKLIST用語ブロックリストに含まれる語によるブロック動きません
IMAGE_SAFETY安全でない画像生成内容によるブロック動きません
OTHER理由不明のブロック動きません
BLOCK_REASON_UNSPECIFIED既定値。この値は使われない該当しません

根拠は仕様の本文にあります。安全設定のガイドには「調整可能な安全フィルタに加えて、Gemini API には児童の安全を脅かす内容などの中核的な危害に対する保護が組み込まれており、この種の危害は常にブロックされ、調整できません」という趣旨の一文が置かれております。

つまり safetySettings は、フィルタ全体を操作する道具ではありません。四つの調整可能なカテゴリの外側には、設定の届かない層がもう一枚あるのです。

ここを知らないまま閾値だけを上下させていると、効いていない操作を効いていると思い込んだまま、何時間も溶かすことになります。私が溶かしたのは、ちょうど一晩でした。

Gemini 2.5・3 系の既定は Off — だから「緩める」は最初から効いていません

もうひとつ、私が見落としていた記述があります。安全設定のガイドの閾値の表のすぐ下に、こう書かれています。

If the threshold is not set, the default block threshold is Off for Gemini 2.5 and 3 models.

閾値を指定しなければ、Gemini 2.5 系と 3 系では既定のブロック閾値が Off である、ということです。同じページには「モデル自体が備える安全性のため、追加のフィルタは既定でオフになっています」という説明も添えられております。

ここから導かれる結論は、思っていたよりも厳しいものでした。safetySettings を一行も書いていない状態で止まったのであれば、調整可能フィルタはそもそも働いていなかったのです。そこへ BLOCK_NONEOFF を足したところで、状態は何も変わりません。

私が四つのカテゴリを並べて再実行したあの夜は、すでにオフのスイッチをもう一度オフにしていただけでした。

閾値は締めるための道具であって、緩めるための道具ではありません。 この一行を手元に置いてから、切り分けの順序が変わりました。いまは「止まった」と聞いたら、閾値ではなく blockReason を先に見るようにしております。

指定できるカテゴリについても、ひとつ補足を書き残します。ガイドの表には調整可能なフィルタが四つ(ハラスメント、ヘイトスピーチ、性的に露骨な内容、危険な内容)と載っておりますが、generateContent のリファレンスで safetySettings の説明を読むと、受け付けるカテゴリとして次の六つが挙げられています。

カテゴリガイドの表に記載
HARM_CATEGORY_HARASSMENTあり
HARM_CATEGORY_HATE_SPEECHあり
HARM_CATEGORY_SEXUALLY_EXPLICITあり
HARM_CATEGORY_DANGEROUS_CONTENTあり
HARM_CATEGORY_CIVIC_INTEGRITYなし
HARM_CATEGORY_JAILBREAKなし

同じリファレンスには「ひとつのカテゴリにつき設定は一件まで」「一覧に含めなかったカテゴリには既定の設定が使われる」とも書かれています。下の二つはガイド側の表に載っておりませんので、挙動を前提にする前にご自身の環境で一度確かめていただくほうが安全です。

あわせて押さえておきたいのが、ブロックの判定軸です。Gemini API は深刻度ではなく、安全でない確率でブロックします。ガイドは「ロボットに殴られた」と「ロボットに切り裂かれた」を並べ、前者のほうが確率は高く出るかもしれない一方、後者のほうが深刻度は高いと感じられるだろう、と説明しております。深刻な内容ほど強く止まるはずだ、という直感は当てになりません。

動かせない側に当たったら、入力のほうへ手を入れます

PROHIBITED_CONTENTBLOCKLIST が返ってきた場合、こちら側に残っている手は設定ではなく入力です。私が順に試している四つを書いておきます。

ひとつめは、まとめて渡すのをやめることです。私の失敗はここでした。三十件の解説文を一度の呼び出しに入れていたため、どの一件が原因なのか最後まで分からなかったのです。二分探索で割っていけば、数回の呼び出しで原因の一件にたどり着けます。

def is_blocked(response):
    kind, _where, _reason = classify_block(response)
    return kind in ("adjustable", "core", "unknown")
 
 
def find_offending(items, call):
    """ブロックを引き起こす要素を二分探索で絞り込みます。"""
    if not items:
        return []
    if len(items) == 1:
        return list(items) if is_blocked(call(items)) else []
 
    mid = len(items) // 2
    found = []
    for half in (items[:mid], items[mid:]):
        if is_blocked(call(half)):
            found.extend(find_offending(half, call))
    return found
 
 
# call は「要素のリストを受け取って GenerateContentResponse を返す」関数です
offenders = find_offending(descriptions, call=run_batch)
print(f"原因の候補: {len(offenders)} 件")

ふたつめは、目的を system_instruction に書くことです。歴史資料の説明である、暴力を推奨する意図はない、といった文脈を添えると通る場合があります。ただし中核の層に当たっているときには効きませんので、一度試して駄目なら深追いしないほうがよいと感じております。

みっつめは、生成から変換へ寄せることです。自由に書かせるのではなく、こちらが用意した語彙から選ばせる、あるいは分類だけを任せるかたちにいたします。出力の自由度を下げると、通る範囲は広がります。

よっつめが、いちばん大事かもしれません。通らない領域だと認めて、人の手に戻すことです。私は武者絵の数点について、最終的にそう決めました。三十件のうち二十数件が自動で仕上がったのであれば、残りを自分で書くのは十分に釣り合う仕事です。

全部を自動化しようとして一晩を溶かすより、境目に印を付けて先へ進むほうが、翌朝の自分は助かります。

運用に載せるなら、記録するのは三つの値です

一度きりの調査で終わらせず、日々動かす処理に組み込むのであれば、ログに残す値は三つで足ります。blockReasonfinishReason、そしてカテゴリ別の safetyRatings です。

import json
import logging
 
 
def log_block(response, request_id):
    kind, where, reason = classify_block(response)
    if kind == "not_blocked":
        return
 
    ratings = []
    candidates = response.candidates or []
    source = candidates[0] if candidates else getattr(response, "prompt_feedback", None)
    for rating in (getattr(source, "safety_ratings", None) or []):
        ratings.append({
            "category": rating.category.name,
            "probability": rating.probability.name,
        })
 
    logging.warning(json.dumps({
        "request_id": request_id,
        "movable": kind,      # adjustable / core / unknown
        "where": where,       # prompt / response
        "reason": reason,
        "ratings": ratings,
    }, ensure_ascii=False))

大切なのは、一件ごとの当たり外れで一喜一憂せずに、率で眺めることです。core の割合が一定なら、それはその題材の性質であって、設定の問題ではありません。一方で adjustable の割合が増えているのであれば、閾値やプロンプトの側に手を入れる余地が残っております。

私は多言語へ広げるバッチにこのログを足してから、朝いちばんに見る画面がひとつ減りました。数字が横ばいであることを確かめるだけで済むようになったからです。

四つの層に分けて入力と出力の両側でモデレーションを設計する話は、Gemini API Safety Settings の本番運用設計でまとめております。閾値の外側まで含めて自分のサービスの防御を組み直したい方は、そちらもあわせてご覧いただければと思います。

もし今ブロックに悩んでいらっしゃるのでしたら、まずは blockReason を一行だけログに出すところから始めてみてください。閾値をいじるのは、その値が SAFETY だと分かってからで遅くありません。私はその順序を逆にして、一晩を無駄にいたしました。

お読みいただきありがとうございました。同じところで手が止まっている方の、切り分けの時間が少しでも短くなれば嬉しく思います。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

高度な活用2026-08-06
知識カットオフが前進した日、見直すべきなのは2つの日付に挟まれた断定でした
モデルの知識カットオフが前進すると、古くなるのはモデルではなくシステム命令に書いた断定の側でした。旧カットオフと新カットオフに挟まれた行だけが補足から矛盾へ反転する理由と、その窓を機械判定する監査ツールの実行結果をまとめています。
高度な活用2026-07-03
夜間バッチが朝の 429 を連れてくる — 1 プロジェクト内で対話機能の Gemini クォータを守る優先度つきアドミッション制御
夜間バッチが朝の対話機能に 429 を連れてくる、同一プロジェクト内の Gemini クォータ競合を解消した記録です。機能タグつき計測で原因を特定し、優先度つきトークンバケットで RPM と TPM を制御。429 率 3.2%→0.03% の実測を含みます。
高度な活用2026-09-05
長い動画を Gemini に辿らせるとき、見つける問いと「無い」を確かめる問いは別々に投げています
9月1日に来たエージェント的動画理解では、どこを観るかをモデル自身が決めます。見つける問いには効きますが、映り込みが無いことの確認には被覆の保証がありません。問いの形で処理モードを分ける判断と、被覆を自分で担保する実装を書き残します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます