- 开发工具
- 后端
【免费下载链接】firebase-js-sdk
Firebase Javascript 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 with
blockReasonand 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 列出的属性总表如下:
| Property | Type | Description |
|---|---|---|
blockReason | BlockReason | prompt 被拦截的原因(可选) |
blockReasonMessage | string | blockReason的人类可读描述。仅在 Agent Platform Gemini API(AgentPlatformBackend)中支持(可选) |
safetyRatings | SafetyRating[] | 各危害类别的安全评级列表(必填) |
以下逐项展开。
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 the
blockReason. 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; }从这段实现可以看出三条确定的事实:
- 默认值填充:GoogleAI 后端返回的评级若缺少
severity,会被填为HarmSeverity.HARM_SEVERITY_UNSUPPORTED;缺少的probabilityScore、severityScore一律填0。这解释了为什么参考文档写“使用GoogleAIBackend时这些属性默认值为HARM_SEVERITY_UNSUPPORTED/ 0”; - 字段透传:
blockReason与blockReasonMessage原样透传,后端不返回blockReasonMessage时,结果中它就是undefined; - 整体缺失即无字段:在 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
相关推荐
Firebase JS SDK AI 包中 GroundingMetadata 接口详解:解析 Gemini Grounding 响应元数据
Firebase JS SDK AI 包中 GroundingMetadata 接口详解:解析 Gemini Grounding 响应元数据 在 Firebas
开发工具后端Firebase JS SDK(@firebase/ai)GoogleMapsGroundingChunk 接口详解:Google Maps 接地(Grounding)响应数据解析
Firebase JS SDK(@firebase/ai)GoogleMapsGroundingChunk 接口详解:Google Maps 接地(Ground
开发工具后端Firebase JS SDK 服务端应用详解:FirebaseServerApp 接口与 initializeServerApp 全解析
Firebase JS SDK 服务端应用详解:FirebaseServerApp 接口与 initializeServerApp 全解析 导读 Firebas
开发工具后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考