iT邦幫忙

2026 iThome 鐵人賽

DAY 19
0
AI Security

30 天打造 AI 輔助 SOC 資安事件分析平台系列 第 19 篇

Day 19|AI Event Summary:誰該負責判斷 Severity?

  • 分享至 

  • xImage
  •  

從讀者建議開始重新思考 AI 與後端的分工

Day 18 完成 Structured Output 後,有讀者提出了一個很重要的問題:目前 severity 雖然已經被放進固定的資料結構,但 1、2、3 對應 High、Medium、Low 本身其實是一項確定性的系統規則,真的有必要再交給 LLM 判斷一次嗎?
這個建議讓我重新思考目前的設計。
LLM 擅長的是理解事件內容、產生摘要及解釋可能的風險;但像 Severity 數值轉換這類已有明確規則的工作,交給一般程式處理不但更簡單,結果也更加穩定。
因此今天不急著增加更多 AI 功能,而是先重新整理 Backend 與 LLM 之間的責任。
比較合理的架構應該是:

                 Security Event
                       │
             ┌─────────┴─────────┐
             ↓                   ↓
        確定性規則             語意分析
             ↓                   ↓
          Backend              Gemini
             ↓                   ↓
        Severity             Summary
        High/Medium/Low       Attack Type
                              Risk
             └─────────┬─────────┘
                       ↓
                 AI SOC Analysis

確認 SOC 事件資料庫內容
https://ithelp.ithome.com.tw/upload/images/20261003/20177754TSGqgD6hYU.png
目前 SQLite 資料庫 soc.db 中共有三筆測試事件,分別為 Network Scan、Login Attempt 與 Web Attack。每筆事件包含來源 IP、目的 IP、連接埠、通訊協定、事件特徵與 Severity 等欄位,接下來將以這些資料作為 AI 分析的輸入。

Severity Mapping

建立新檔 nano ai_event_summary.py

severity_map = {
    1: "High",
    2: "Medium",
    3: "Low"
}
severity = 2
severity_label = severity_map.get(severity, "Unknown")
print("原始 Severity:", severity)
print("轉換後 Severity:", severity_label)

https://ithelp.ithome.com.tw/upload/images/20261003/20177754PJWEgfYSUR.png
從 2 → Gemini → Medium 變成 2 → Python → Medium

建立 Enum

現在我們再解決第二個問題: severity: str 代表理論上它可以是任何文字:High、HIGH、high、2、Medium Risk、嚴重、ABC...
nano ai_event_summary.py

from enum import Enum
class SeverityLevel(str, Enum):
    HIGH = "High"
    MEDIUM = "Medium"
    LOW = "Low"
severity_map = {
    1: SeverityLevel.HIGH,
    2: SeverityLevel.MEDIUM,
    3: SeverityLevel.LOW
}
severity = 2
severity_level = severity_map.get(severity)
print("原始 Severity:", severity)
print("轉換後 Severity:", severity_level.value)

https://ithelp.ithome.com.tw/upload/images/20261003/20177754vUX2AlLdRy.png

接 SQLite + Gemini

nano ai_event_summary.py

import sqlite3
from enum import Enum
from google import genai
from pydantic import BaseModel, Field
client = genai.Client()
# Severity 只允許固定的三種值
class SeverityLevel(str, Enum):
    HIGH = "High"
    MEDIUM = "Medium"
    LOW = "Low"
# Gemini 負責產生的 AI 分析
class AIAnalysis(BaseModel):
    summary: str = Field(
        description="用繁體中文簡短說明這個資安事件發生了什麼"
    )
    attack_type: str = Field(
        description="根據事件內容判斷可能的攻擊或活動類型"
    )
    risk: str = Field(
        description="用繁體中文說明此事件可能造成的資安風險"
    )
    
# 確定性的 Severity Mapping
severity_map = {
    1: SeverityLevel.HIGH,
    2: SeverityLevel.MEDIUM,
    3: SeverityLevel.LOW
}
# 從 SQLite 讀取最新事件
conn = sqlite3.connect("soc.db")
conn.row_factory = sqlite3.Row
event = conn.execute(
    "SELECT * FROM events ORDER BY id DESC LIMIT 1"
).fetchone()
conn.close()
if event is None:
    print("No security events found.")
    exit()
# Severity 由 Backend 處理
severity_level = severity_map.get(event["severity"])
if severity_level is None:
    print("Unknown severity value:", event["severity"])
    exit()
# 準備給 Gemini 的事件資料
event_text = f"""
Event Type: {event["event_type"]}
Source IP: {event["src_ip"]}
Destination IP: {event["dest_ip"]}
Destination Port: {event["dest_port"]}
Protocol: {event["protocol"]}
Signature: {event["signature"]}
"""
prompt = f"""
You are a SOC Analyst Assistant.
The following content is security event data.
Analyze the event and explain:
1. What happened
2. The possible attack type
3. The possible security risk

Keep the explanation concise.
Do not make the final blocking decision.
Security Event:
{event_text}
"""
response = client.models.generate_content(
    model="gemini-flash-lite-latest",
    contents=prompt,
    config={
        "response_mime_type": "application/json",
        "response_schema": AIAnalysis,
    },
)
# SDK 直接解析成 AIAnalysis
result = response.parsed
print("===== Original Security Event =====")
print("Event ID:", event["id"])
print("Event Type:", event["event_type"])
print("Source IP:", event["src_ip"])
print("Destination IP:", event["dest_ip"])
print()
print("===== Backend Deterministic Rule =====")
print("Severity:", severity_level.value)
print()
print("===== Gemini AI Analysis =====")
print("事件摘要:", result.summary)
print("攻擊類型:", result.attack_type)
print("可能風險:", result.risk)

https://ithelp.ithome.com.tw/upload/images/20261003/201777548QMkwRkERi.png
今天我們做了三個重要調整:首先改用程式碼對應(severity_map.get)來決定事件嚴重性,不再交由 Gemini 判斷;其次在 Schema 中透過 Field(description="...") 明確定義 summary、attack_type 與 risk 欄位的作用;最後則將回應解析方式從原本的 json.loads(response.text) 改為直接取用結構化解析後的 response.parsed。


上一篇
Day 18|Structured Output:讓 AI 回答變成程式看得懂的 JSON
下一篇
Day 20|AI 處置建議:讓 SOC Analyst Assistant 告訴我下一步查什麼
系列文
30 天打造 AI 輔助 SOC 資安事件分析平台 共 22 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言