☰
Firebase JS SDK AI:PromptFeedback 接口全解析——理解 Gemini 响应的安全拦截反馈机制
2026/10/16 6:20:40 网站建设 项目流程
  • 开发工具
  • 后端

【免费下载链接】firebase-js-sdk

Firebase Javascript SDK

项目地址:https://gitcode.com/gh_mirrors/fi/firebase-js-sdk
点击查看免费下载

在 Firebase JS SDK 的@firebase/ai模块中,每次调用GenerativeModel.generateContent或generateContentStream都会返回一个GenerateContentResponse对象;当请求的 prompt 被服务端安全策略拦截时,其中的promptFeedback字段就会携带一个PromptFeedback对象,说明“为什么被拦”以及触发了哪些安全类别。本文围绕 PromptFeedback 接口参考文档 展开,完整介绍它的三个属性(blockReason、blockReasonMessage、safetyRatings)、各枚举取值及其在两种后端(Gemini Developer API 与 Agent Platform Gemini API)下的差异,并结合 packages/ai 的源码与测试说明字段映射与默认值填充机制,帮助你写出健壮的安全拦截处理逻辑。

PromptFeedback 在响应结构中的位置

从 PromptFeedback 参考文档 可知,该接口的官方定义是:

If the prompt was blocked, this will be populated withblockReasonand the relevantsafetyRatings.

export interface PromptFeedback

它的宿主对象是GenerateContentResponse。在 响应类型定义 中可以看到它作为可选字段挂载在响应顶层:

export interface GenerateContentResponse { candidates?: GenerateContentCandidate[]; promptFeedback?: PromptFeedback; usageMetadata?: UsageMetadata; }

也就是说,promptFeedback与candidates、usageMetadata平级。实践中这意味着:

  • prompt 正常放行时,promptFeedback通常只带safetyRatings(甚至可能整体缺失);
  • prompt 被拦截时,promptFeedback.blockReason会被填充,同时candidates往往为空或不含有效候选,EnhancedGenerateContentResponse.text()等方法会直接抛出异常(其 JSDoc 明确写着 "Throws if the prompt or candidate was blocked",见 EnhancedGenerateContentResponse 定义)。

因此,一个健壮的调用方应该在取文本前先检查promptFeedback,而不是直接调用response.text()后被动捕获异常。

三个属性逐一解析

参考文档 docs-devsite/ai.promptfeedback.md 列出的属性总表如下:

PropertyTypeDescription
blockReasonBlockReasonprompt 被拦截的原因(可选)
blockReasonMessagestringblockReason的人类可读描述。仅在 Agent Platform Gemini API(AgentPlatformBackend)中支持(可选)
safetyRatingsSafetyRating[]各危害类别的安全评级列表(必填)

以下逐项展开。

blockReason:拦截原因枚举

参考文档中的签名为:

blockReason?: BlockReason;

BlockReason枚举定义在 packages/ai/src/types/enums.ts,共四个取值:

枚举值含义
BlockReason.SAFETY内容因安全设置(safety settings)被拦截
BlockReason.OTHER内容被拦截,但原因未分类
BlockReason.BLOCKLIST内容命中了术语屏蔽词表(terminology blocklist)
BlockReason.PROHIBITED_CONTENT内容因含有违禁内容被拦截

判断拦截的最直接写法:

import { AI, GenerativeModel, BlockReason } from '@firebase/ai'; const model = new GenerativeModel('gemini-2.0-flash', ai); try { const { response } = await model.generateContent('你的 prompt'); const feedback = response.promptFeedback; if (feedback?.blockReason) { // 命中拦截分支 if (feedback.blockReason === BlockReason.SAFETY) { // 因安全设置拦截:可结合 safetyRatings 定位具体危害类别 } else if (feedback.blockReason === BlockReason.BLOCKLIST) { // 命中屏蔽词表 } else if (feedback.blockReason === BlockReason.PROHIBITED_CONTENT) { // 违禁内容 } } } catch (e) { // 其他网络/配额错误等 }

blockReasonMessage:仅在 Agent Platform 后端支持

参考文档中的签名与说明:

blockReasonMessage?: string;

A human-readable description of theblockReason. This property is only supported in the Agent Platform Gemini API (AgentPlatformBackend).

即该字段提供一段可直接展示给用户的拦截原因文本。需要注意其适用前提:

  • 使用AgentPlatformBackend(通过 Vertex AI 走 Google Cloud 的 Gemini API)时,服务端可能返回该字段,可用于 UI 提示;
  • 使用GoogleAIBackend(Gemini Developer API)时,该属性不受支持,取值会是undefined。这一点在源码 PromptFeedback 接口 的 JSDoc 中有明确标注。

因此,展示拦截原因时应采用“blockReasonMessage优先、blockReason兜底”的策略,而不能假设blockReasonMessage一定存在。

safetyRatings:逐类别的安全评级(必填字段)

参考文档中的签名:

safetyRatings: SafetyRating[];

SafetyRating接口定义在 packages/ai/src/types/responses.ts:

export interface SafetyRating { category: HarmCategory; // 危害类别 probability: HarmProbability; // 命中该类别的概率等级 severity: HarmSeverity; // 危害严重度(仅 Agent Platform 后端支持) probabilityScore: number; // 概率分数(仅 Agent Platform 后端支持,GoogleAI 后端下为 0) severityScore: number; // 严重度分数(仅 Agent Platform 后端支持,GoogleAI 后端下为 0) blocked: boolean; // 该类别是否触发了拦截 }

其中涉及的枚举同样来自 packages/ai/src/types/enums.ts:

  • HarmCategory:HARM_CATEGORY_HATE_SPEECH(仇恨言论)、HARM_CATEGORY_SEXUALLY_EXPLICIT(露骨内容)、HARM_CATEGORY_HARASSMENT(骚扰)、HARM_CATEGORY_DANGEROUS_CONTENT(危险内容);
  • HarmProbability:NEGLIGIBLE/LOW/MEDIUM/HIGH四级概率;
  • HarmSeverity:HARM_SEVERITY_NEGLIGIBLE/LOW/MEDIUM/HIGH,以及HARM_SEVERITY_UNSUPPORTED(源码注释说明:GoogleAI 后端不支持HarmSeverity,该值用作兜底)。

一个典型的safetyRatings消费方式,是找出真正触发拦截的类别:

if (response.promptFeedback) { const blockedRatings = response.promptFeedback.safetyRatings.filter(r => r.blocked); console.log('被拦截的危害类别:', blockedRatings.map(r => r.category)); }

另外,请求侧的SafetySetting(通过HarmBlockThreshold,如BLOCK_LOW_AND_ABOVE、BLOCK_MEDIUM_AND_ABOVE、BLOCK_ONLY_HIGH、BLOCK_NONE、OFF等档位)决定了服务端以什么阈值拦截 prompt;promptFeedback.safetyRatings则是拦截判定结果的回执。两者配合,可以在出现误拦截时通过调低阈值来放宽策略。

后端差异:GoogleAI 与 Agent Platform 的字段对齐

PromptFeedback的文档特意标注了blockReasonMessage(以及SafetyRating上的severity/probabilityScore/severityScore)只受 Agent Platform Gemini API 支持。SDK 在运行时如何处理这种异构?答案在 mapPromptFeedback 映射函数:

export function mapPromptFeedback( promptFeedback: PromptFeedback ): PromptFeedback { // Assign missing SafetyRating properties to their defaults if undefined. const mappedSafetyRatings: SafetyRating[] = []; promptFeedback.safetyRatings.forEach(safetyRating => { mappedSafetyRatings.push({ category: safetyRating.category, probability: safetyRating.probability, severity: safetyRating.severity ?? HarmSeverity.HARM_SEVERITY_UNSUPPORTED, probabilityScore: safetyRating.probabilityScore ?? 0, severityScore: safetyRating.severityScore ?? 0, blocked: safetyRating.blocked }); }); const mappedPromptFeedback: PromptFeedback = { blockReason: promptFeedback.blockReason, safetyRatings: mappedSafetyRatings, blockReasonMessage: promptFeedback.blockReasonMessage }; return mappedPromptFeedback; }

从这段实现可以看出三条确定的事实:

  1. 默认值填充:GoogleAI 后端返回的评级若缺少severity,会被填为HarmSeverity.HARM_SEVERITY_UNSUPPORTED;缺少的probabilityScore、severityScore一律填0。这解释了为什么参考文档写“使用GoogleAIBackend时这些属性默认值为HARM_SEVERITY_UNSUPPORTED/ 0”;
  2. 字段透传:blockReason与blockReasonMessage原样透传,后端不返回blockReasonMessage时,结果中它就是undefined;
  3. 整体缺失即无字段:在 mapGenerateContentResponse 中,googleAIResponse.promptFeedback不存在时,映射后的GenerateContentResponse上promptFeedback为undefined。

单元测试 googleai-mappers.test.ts 中的describe('mapPromptFeedback')用例对这三点都做了断言:输入缺少severity/probabilityScore/severityScore/blockReasonMessage时,映射结果依次为HARM_SEVERITY_UNSUPPORTED、0、0和undefined,同时blockReason(BlockReason.OTHER)与已有的category/probability/blocked被完整保留。

补充一点:GoogleAI 内部响应类型 GoogleAIGenerateContentResponse 中,promptFeedback同样是可选字段,直接复用公共 API 的PromptFeedback类型,再经由上述映射函数统一为公开 API 的形状。

实战:一个可直接复用的拦截处理示例

结合前文的接口定义与后端差异,下面是一个处理PromptFeedback的完整示例(适用于@firebase/ai模块):

import { AI, GenerativeModel, BlockReason } from '@firebase/ai'; async function safeGenerate(ai, model, prompt) { const { response } = await model.generateContent(prompt); const feedback = response.promptFeedback; if (!feedback) { // 无 prompt 反馈,直接读取结果 return { ok: true, text: response.text() }; } if (feedback.blockReason) { // 1) 优先使用后端返回的人类可读原因(仅 Agent Platform 后端可能有值) // 2) 否则根据 blockReason 枚举给出本地文案 const localMessages = { [BlockReason.SAFETY]: '内容因安全策略被拦截。', [BlockReason.BLOCKLIST]: '内容命中了屏蔽词表。', [BlockReason.PROHIBITED_CONTENT]: '内容包含违禁信息。', [BlockReason.OTHER]: '内容被拦截(原因未分类)。' }; const detail = feedback.blockReasonMessage ?? localMessages[feedback.blockReason]; // 3) 找出真正被拦截的危害类别,便于排查与调优 safetySettings const blockedCategories = feedback.safetyRatings .filter(r => r.blocked) .map(r => r.category); return { ok: false, blockReason: feedback.blockReason, detail, blockedCategories }; } // promptFeedback 存在但未拦截:通常只是附带 safetyRatings 信息 return { ok: true, text: response.text() }; }

该示例覆盖了参考文档中的全部三个属性:以blockReason判定拦截并分支处理,用blockReasonMessage增强提示(并明确其为 Agent Platform 后端专属能力),以safetyRatings的blocked标记定位具体危害类别。

小结与延伸阅读

PromptFeedback是@firebase/ai模块中 prompt 安全拦截的“回执单”:blockReason给出分类原因(SAFETY/OTHER/BLOCKLIST/PROHIBITED_CONTENT),safetyRatings给出逐类别的概率与拦截标记,blockReasonMessage则仅在 Agent Platform Gemini API 下提供人类可读描述。使用GoogleAIBackend时,缺失的 severity/score 字段会被 SDK 统一填为HARM_SEVERITY_UNSUPPORTED和0,因此判断“是否受支持”应以后端类型而非字段是否存在为准。

  • 接口参考文档:docs-devsite/ai.promptfeedback.md
  • 接口与宿主响应类型源码:packages/ai/src/types/responses.ts
  • BlockReason等枚举源码:packages/ai/src/types/enums.ts
  • 后端响应映射实现:packages/ai/src/googleai-mappers.ts
  • 映射行为测试:packages/ai/src/googleai-mappers.test.ts
  • 开发工具
  • 后端

【免费下载链接】firebase-js-sdk

Firebase Javascript SDK

项目地址:https://gitcode.com/gh_mirrors/fi/firebase-js-sdk
点击查看免费下载
上一篇:Dagger TypeScript SDK 的 UnknownDaggerError(D101):兜底错误类的设计与排查实战
下一篇:用 Rerun 可视化 DICOM MRI 体数据:一行代码实现 3D 张量切片与语义轴命名

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询