承接之前文章,護欄介紹完後,接著我們來使用Safety Settings來設置護欄。許多開發者在初期會嘗試自己維護一長串的「敏感觸發詞」黑名單,用來防止模型生成不當內容。但這種方法不僅維護成本高,也難抵擋攻擊。
更聰明、更穩定的做法,是善用官方 API 提供的安全設定(Safety Settings)。
與其自己當裁判,不如讓官方提供的安全分類來為內容把關。我們可以針對不同類別(如:騷擾、仇恨言論、色情、危險內容)設定不同的阻擋閾值。
resp = model.generate_content(
[{"role": "user", "parts": [{"text": "幫我分析體重報告"}]}],
safety_settings=[
{"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_ONLY_HIGH"},
{"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_ONLY_HIGH"},
{"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_ONLY_HIGH"},
{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_ONLY_HIGH"}
]
)
將「要不要阻擋」的判斷交給 safety_settings,並在 System Prompt 中定義好你的應用程式被拒絕時應如何回應(例如:「抱歉,我無法提供醫療建議,請諮詢專業醫師」)。這樣分工明確,系統也更為穩健。
前面還停留在直接印出模型回傳的純文字。但對於一個需要自動化運行的後端服務來說,這種格式是不可靠的。我們需要的是機器可解析、格式固定的結構化資料。
透過設定 response_mime_type
為 "application/json"
,並提供一個 response_schema
,我們可以強制模型輸出一份符合預期格式的 JSON 文件。
response = model.generate_content(
[{"role": "user", "parts": [{"text": "請分析此餐點並給 2 點改進建議"}]}],
generation_config={
"response_mime_type": "application/json",
"response_schema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"kcal": {"type": "number"},
"protein_g": {"type": "number"},
"carbs_g": {"type": "number"},
"fat_g": {"type": "number"}
},
"required": ["name", "kcal"]
}
},
"tips": {
"type": "array",
"items": {"type": "string"}
}
},
"required": ["items", "tips"]
}
}
)
# 這段回傳的 response.text 已是 JSON 字串,可直接被後端解析
print(response.text)
使用 response_mime_type: "application/json"
搭配 schema,能確保模型的輸出是可驗證、可預期的。這對於需要串接資料庫、或與前端溝通的 API 服務來說至關重要。
當任務比較複雜時,例如分析一張可能是食物也可能是 InBody 報告的圖片,直接把問題一次性丟給模型,結果往往不穩定。一個更可靠的做法是將任務拆解成多個階段。
第一階段:低溫(temperature: 0)判斷圖片類型
先用一個確定性的請求,讓模型只做一件簡單的事:分類。這樣可以大幅提高準確率。
# 第一階段:判斷圖片類型
classify = model.generate_content(
[{"role": "user", "parts": [
{"text": "判斷這張圖片是食物(food)還是InBody報告(inbody),只回答food或inbody"},
{"inline_data": {"mime_type": "image/jpeg", "data": base64_img}}
]}],
generation_config={"temperature": 0, "max_output_tokens": 10}
).text.strip()
第二階段:根據類型,套用對應的 Schema 進行分析
得知圖片類型後,我們就可以選擇對應的 JSON 結構,再讓模型進行深入分析。
# 第二階段:根據類型選擇 schema 再分析
if classify == "food":
schema = FoodSchema
else:
schema = InbodySchema
analysis = model.generate_content(
[{"role": "user", "parts": [
{"text": "請依照指定結構分析圖片內容"},
{"inline_data": {"mime_type": "image/jpeg", "data": base64_img}}
]}],
generation_config={
"temperature": 0.4,
"response_mime_type": "application/json",
"response_schema": schema
}
)
print(analysis.text)
「先分類,再分析」的模式能有效簡化模型的任務,讓每一步的輸出都更穩定、更可控。
在與模型互動時,務必遵守「最小揭露原則」。
只提供當前任務必要的資訊
例如,在分析健康數據時,只傳送用戶的年齡、目標、最新的 InBody 數據,而不是整個用戶的個人資料歷史。
避免傳送內部規則
不要把完整的內部商業邏輯、敏感關鍵字列表或詳細的 System Prompt 傳給模型。
長期記憶交給後端
如果需要模型記住歷史對話,應將對話紀錄存放在後端資料庫。在每次請求時,由後端重新整理一份摘要(Summary)再傳送給模型,而不是把冗長的歷史紀錄全部送出。
一個可上線的系統,必須能優雅地處理各種預期外的狀況。
重試策略
當遇到 API 回傳 429 (Too Many Requests) 或 5xx (Server Error) 等暫時性錯誤時,應採用「指數退避(Exponential Backoff)」策略進行重試。如果持續失敗,可以考慮減少輸入的資料長度後再試一次。
Schema 驗證
若模型回傳的內容不符合你定義的 JSON 格式,可以觸發一次重試,並在 Prompt 中額外加入提示:「請嚴格按照提供的 JSON 格式輸出」。
端對端(E2E)測試
準備一套「黃金測資(Golden Test Cases)」,包含:
持續追蹤系統的拒答率與格式成功率,確保每次改版都不會降低服務品質。
從實驗階段到正式上線,我們完成了從「把玩 Prompt」到「打造可上線服務」的第一步。核心要點整理