iT邦幫忙

2026 iThome 鐵人賽

DAY 5
2
Build on Google AI

給藥袋裝一張嘴:30 天用 Android 與 Google VLM 實作高齡語音用藥助手系列 第 5 篇

Day 05|治好 AI 的亂回答!用 Gemini Structured Output 強制輸出完美 JSON

  • 分享至 

  • xImage
  •  

✏️【本日實作紀錄:Prompt 工程優化與 JSON 結構化輸出】

今天進入 AI 輸出控制階段,完成項目包含:

  1. 設計 JSON Schema 結構規範 — 定義固定的 JSON 欄位,確保 AI 回傳格式乾淨且不脫軌。
  2. 編寫結構化辨識腳本(test_vlm_json.py) — 使用 Google GenAI SDK 的 response_schema 設定,強制 Gemini 輸出 JSON。
  3. 驗證雙重輸出機制 — 讓 AI 同時回傳可用於 App 語音播報的白話文,以及可用於程式解析的藥品陣列。

一、為什麼需要 JSON 結構化輸出?

後端系統若要自動將「一天吃兩次、每次一顆」寫入 SQLite 資料庫並透過 LINE Bot 推播關懷提醒, API 必須提供結構清晰、欄位固定的 JSON 資料。

Gemini 的 Structured Output 功能讓 AI 按照指定格式回答,不需要用複雜的正則表達式(Regex)去拆解文字。

二、編寫 JSON 結構化測試腳本(test_vlm_json.py)

在 PrescriptionVLM 專案根目錄下建立 test_vlm_json.py 檔案:

import os
import json
from dotenv import load_dotenv
from google import genai
from google.genai import types
from PIL import Image

# 1. 載入 .env 檔案中的環境變數
load_dotenv()

api_key = os.getenv("GEMINI_API_KEY")
if not api_key:
    raise ValueError("❌ 錯誤:找不到 GEMINI_API_KEY,請檢查 .env 設定!")

# 2. 初始化 Google GenAI Client
client = genai.Client(api_key=api_key)

# 3. 定義 JSON 結構規範 (JSON Schema)
prescription_schema = {
    "type": "OBJECT",
    "properties": {
        "spoken_summary": {
            "type": "STRING",
            "description": "適合唸給長輩聽的白話文總結,語氣溫柔親切。"
        },
        "medicines": {
            "type": "ARRAY",
            "items": {
                "type": "OBJECT",
                "properties": {
                    "name": {"type": "STRING", "description": "藥品中文名稱或商品名"},
                    "type": {"type": "STRING", "description": "口服或外用"},
                    "frequency": {"type": "STRING", "description": "服用頻率,如:每日二次"},
                    "dosage": {"type": "STRING", "description": "每次劑量,如:1顆、0.5顆"},
                    "timing": {"type": "STRING", "description": "吃藥時間點,如:飯後、睡前"},
                    "warning": {"type": "STRING", "description": "重要警語或注意事項,無則填空字串"}
                },
                "required": ["name", "type", "frequency", "dosage", "timing"]
            }
        }
    },
    "required": ["spoken_summary", "medicines"]
}

def analyze_prescription_json(image_path):
    print(f"🔍 正在解析藥袋並輸出 JSON 結構: {image_path} ...")
    
    # 載入藥袋照片 (使用 Pillow)
    image = Image.open(image_path)
    
    # 設計提示詞
    prompt = """
    你是一位專業且細心的藥師助手。請分析這張藥袋照片:
    1. 將藥品分類為口服或外用,並精準提取名稱、頻率、劑量與吃藥時間。
    2. 針對高齡長輩,撰寫一段溫柔白話的 spoken_summary,適合 TTS 語音播報。
    3. 若有重要注意事項(如抗生素需全部吃完、會昏睡等),請填入 warning 欄位。
    """
    
    # 設定 Structured Output 配置
    config = types.GenerateContentConfig(
        response_mime_type="application/json",
        response_schema=prescription_schema
    )
    
    # 呼叫 Gemini 多模態視覺模型 (使用 gemini-3.6-flash)
    response = client.models.generate_content(
        model='gemini-3.6-flash',
        contents=[image, prompt],
        config=config
    )
    
    print("\n✅ --- AI 結構化 JSON 解析結果 ---")
    parsed_json = json.loads(response.text)
    print(json.dumps(parsed_json, indent=2, ensure_ascii=False))

if __name__ == '__main__':
    test_image = "test_rx.jpg"
    
    if os.path.exists(test_image):
        analyze_prescription_json(test_image)
    else:
        print(f"⚠️ 請在專案根目錄放置一張名為 '{test_image}' 的測試藥袋圖片再執行測試!")

三、測試驗證與成果執行

執行測試腳本

確保終端機處於 (venv) 狀態下,輸入(Ctrl+C 可取消執行test_vlm_json.py):

python test_vlm_json.py

預期輸出成果

Gemini 回傳格式清晰的 JSON 物件,不帶 Markdown 標題或多餘文字。spoken_summary 欄位可直接交給 TTS 播報,medicines 陣列可供後端存入 SQLite 資料庫,並在 LINE 聊天室與 Web 關懷儀表板中呈現結構化表格。

四、版本控制與提交 GitHub

測試成功後,將 Day 05 的程式碼提交至 GitHub:

git add .
git commit -m "保留雙引號 改填寫自己要記錄的標記 ex.鐵人賽第五天"
git push

五、本日小結與明日預告

今天導入 Gemini 的 Structured Output 功能,透過 JSON Schema 規範讓 VLM 輸出標準格式的用藥資料。這解決了自由文字難以被程式自動化處理的問題。

明天(Day 06),我們將實作 gTTS 自動語音生成機制,將 AI 產出的 spoken_summary 白話轉譯文字自動轉化為高音質 .mp3 播報檔,為長輩提供真正「能聽、能看」的雙重關懷體驗!


上一篇
Day 04|金鑰不外洩、藥袋一眼看懂!Python 串接 Google Gemini VLM 實戰
下一篇
Day 06|讓 AI 藥師親口唸藥單!整合 gTTS 語音生成與 Flask 多模態 API
系列文
給藥袋裝一張嘴:30 天用 Android 與 Google VLM 實作高齡語音用藥助手 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言