iT邦幫忙

2025 iThome 鐵人賽

DAY 24
0
生成式 AI

AI 產品與架構設計之旅:從 0 到 1,再到 Day 2系列 第 24

Day 24: 當 AI 報告需要「格式規範」- Output Schema 的第一步

  • 分享至 

  • xImage
  •  

嗨大家,我是 Debuguy。

還記得 Day 21 我們做了 Grafana Alert 的自動化分析嗎?AI 會生成一份技術分析報告,內容確實有用,但有個問題一直讓我很困擾...

問題:AI 輸出的是一大段文字

現狀:純文字報告

目前的 Grafana 分析報告長這樣:

🚨 Grafana 警報分析

摘要:API 出現大量 5xx 錯誤,影響用戶登入功能。經過分析發現是 database 連線池耗盡導致。

優先級:高
這是一個高優先級問題,因為影響到核心的登入功能,導致用戶無法正常使用服務。

信心水準:高 (95%)
基於充足的日誌證據和清晰的錯誤模式,我對這個分析結果有很高的信心。

影響範圍:
主要影響 Auth Service 和 User Profile Service。根據日誌統計,約有 1247 個用戶在這段時間內遇到登入失敗。

立即建議:
1. 立即檢查 Auth Service 的 database 連線池配置
2. 查看最近的部署記錄
3. 增加監控告警

問題在哪?

這段文字在 Slack 裡就是一大段純文字:

問題一:可讀性差

  • 資訊密度太高,凌晨三點被叫醒要花時間慢慢讀
  • 重點不突出,「優先級:高」混在一堆文字中
  • 想快速找到「建議」要往下捲

問題二:無法程式化處理

// 我想要自動判斷優先級來決定通知方式
if (報告.優先級 === '高') {  // ❌ 報告是一大段字串啊!
  notifyOnCall();
}

問題三:Slack 有更好的呈現方式

Slack 的 Block Kit 可以做出很漂亮的視覺效果:

  • 大標題、分隔線、雙欄資訊
  • 醒目的 emoji 和顏色標示
  • 結構化的條列項目

但 AI 給我一大段文字,要怎麼轉換成這些精美的 blocks?

解決方案:讓 AI 直接輸出結構化資料

Genkit 的 Structured Output

翻了 Genkit 的文件後發現,原來可以直接要求 AI 輸出結構化的 JSON!

概念很簡單:

  • 我們定義一個 schema(資料格式)
  • 告訴 AI:「請按照這個格式輸出」
  • AI 就會老實地給你 JSON

在 dotPrompt 中定義

# prompts/grafana_analysis.prompt
---
model: litellm/gemini-2.5-flash
output:
  schema:
    title: string
    summary: string
    priority: (enum[high, medium, low])
    confidence:
      level: (enum[high, medium, low])
      percentage: number
---

你是一位 Grafana 警報診斷專家...

就這樣!在 output.schema 裡面定義好格式,AI 就會按照這個格式輸出。

實際的輸出變化

Before(純文字):

摘要:API 出現大量 5xx 錯誤...
優先級:高
信心水準:高 (95%)
...

After(結構化 JSON):

{
  "title": "API 5xx 錯誤率異常警報分析",
  "summary": "API 出現大量 5xx 錯誤,影響用戶登入功能...",
  "priority": "high",
  "confidence": {
    "level": "high",
    "percentage": 95
  }
}

差異立見:

  • ✅ 結構清晰
  • ✅ 欄位明確
  • ✅ 可以直接用程式處理
  • ✅ TypeScript 可以做類型檢查

Output Schema 帶來的好處

1. 程式化處理變簡單

// 現在可以這樣寫了!
if (report.priority === 'high') {
  await notifyOnCall(report);
}

// 自動建立 ticket
if (report.confidence.percentage >= 90) {
  await createJiraTicket(report);
}

// 存入資料庫
await db.alerts.create({
  data: report
});

2. 資料格式有保證

定義 schema 時:

priority: (enum[high, medium, low])

AI 只能輸出這三個值之一:

  • "high"
  • "medium"
  • "low"
  • "較高"(會被拒絕)
  • "critical"(會被拒絕)

不用擔心 AI 會突發奇想用其他的詞彙。

3. 為視覺化呈現做準備

有了結構化資料,就可以:

  • 根據 priority 顯示不同顏色的 emoji(🔴🟡🟢)
  • confidence 做成進度條
  • recommendations 轉成 Slack 的條列 blocks

Grafana 分析

設計思路

分析報告需要包含什麼?

  1. 標題:讓人一眼知道是什麼問題
  2. 摘要:30 秒內讀完的重點
  3. 優先級:決定要不要立刻處理
  4. 信心水準:AI 對分析結果有多確定
  5. 影響範圍:哪些服務、多少用戶受影響
  6. 建議:接下來該做什麼

Schema 定義

output:
  schema:
    title: string
    summary: string
    priority: (enum[high, medium, low])
    confidence:
      level: (enum[high, medium, low])
      percentage: number
      reason: string
    impact:
      services(array): string
      userCount?: number
      description: string
    recommendations(array):
      action: string
      priority: (enum[immediate, soon, later])

實際輸出範例

{
  "title": "API 5xx 錯誤率異常",
  "summary": "Auth Service 的 database 連線池耗盡導致大量 5xx 錯誤",
  "priority": "high",
  "confidence": {
    "level": "high",
    "percentage": 95,
    "reason": "日誌證據充足,錯誤模式清晰"
  },
  "impact": {
    "services": ["auth-service", "user-profile-service"],
    "userCount": 1247,
    "description": "所有需要登入的功能都受到影響"
  },
  "recommendations": [
    {
      "action": "檢查 database 連線池配置",
      "priority": "immediate"
    },
    {
      "action": "增加監控告警",
      "priority": "soon"
    }
  ]
}

完美!現在我們有了結構清晰的資料。

下一步:把資料變成漂亮的 Slack 訊息

有了結構化的 JSON 後,明天我們要來解決:

如何把這個 JSON 轉換成漂亮的 Slack blocks?

Slack 的 Block Kit 有很多種 blocks:

  • header(大標題)
  • section(內容區塊)
  • divider(分隔線)
  • context(次要資訊)
  • rich_text(豐富的文字格式)

每種 block 都有自己的 JSON 格式規範,而且可以組合出千變萬化的視覺效果。

Slack 還有提供線上的所見即所得可以預覽樣式
Block Kit Builder

問題是:這麼多種 blocks 的格式,要怎麼優雅地定義成 TypeScript types?

明天我們就來聊聊如何用 Zod schema 把 Slack blocks 的複雜格式「馴服」,讓程式碼既類型安全又好維護。

小結

今天我們學到了 Output Schema 的核心概念:

核心價值:

  • ✅ 讓 AI 輸出結構化資料而不是純文字
  • ✅ 資料格式有保證(enum、type checking)
  • ✅ 可以輕鬆做程式化處理
  • ✅ 為視覺化呈現打好基礎

設計原則:

  • 簡單明確的 schema
  • 使用 enum 限制值域
  • 適度的巢狀結構

下一步預告:
明天我們要把這個結構化資料轉換成精美的 Slack 訊息!


AI 的發展變化很快,目前這個想法以及專案也還在實驗中。但也許透過這個過程大家可以有一些經驗和想法互相交流,歡迎大家追蹤這個系列。

也歡迎追蹤我的 Threads @debuguy.dev


上一篇
Day 23: 當 Reasoning 暫時缺席 - 用動畫填補等待的空虛
系列文
AI 產品與架構設計之旅:從 0 到 1,再到 Day 224
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言