iT邦幫忙

2025 iThome 鐵人賽

DAY 22
0
生成式 AI

第一次學 Kotlin Koog AI 就上手系列 第 22

第一次學 Kotlin Koog AI 就上手 Day 22:策略圖基礎:構建多階段 AI 工作流程

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250817/20121948Poi3rAb0ic.png

在前面的文章中,我們學習了快取機制、記憶體系統、事件處理和策略路由等功能。今天我們要深入學習 Koog 框架的核心概念之一:策略圖(Strategy Graph),這是建構複雜 AI 工作流程的基礎

什麼是策略圖?

從簡單到複雜的演進

還記得我們之前使用的簡單策略嗎?

// 簡單的單次執行策略
val agent = AIAgent(
    executor = simpleOpenAIExecutor(ApiKeyManager.openAIApiKey!!),
    strategy = singleRunStrategy(), // 簡單策略
    systemPrompt = "你是一個客服助手"
)

這種策略適合處理簡單的問答,但當我們需要處理複雜的業務邏輯時,就需要更強大的工具——策略圖 (Strategy Graph)

策略圖的核心概念

策略圖就像是一張藍圖,描述 AI Agent 如何一步步處理複雜任務

  • 節點(Node):代表一個具體的處理步驟
  • 邊(Edge):連接節點,控制執行流程
  • 條件(Condition):決定何時從一個節點跳到另一個節點

想像一下,如果 AI Agent 是一個工廠,策略圖就是生產線的設計圖,每個節點是一個工作站,邊是輸送帶,條件是品質檢查點

策略圖的核心組件

Strategy:頂層容器

val strategy = strategy<String, String>("strategy_name") {
    // 在這裡定義節點和邊
}
  • 泛型參數<輸入類型, 輸出類型>
  • 名稱:策略的識別名稱
  • 區塊:定義整個工作流程的地方

Node:執行單元

節點是策略圖的基本執行單位,每個節點負責一個特定的任務

val processNode by node<String, String>("process_data") { input ->
    // 處理輸入資料
    val result = "處理後的資料:$input"
    result // 返回處理結果
}

Edge:流程控制

邊定義了節點之間的連接關係

// 基本連接
edge(nodeA forwardTo nodeB)

// 條件連接
edge(nodeA forwardTo nodeB onCondition { output ->
    output.length > 10
})

// 轉換輸出
edge(nodeA forwardTo nodeB transformed { output ->
    output.uppercase()
})

特殊節點:nodeStart 和 nodeFinish

每個策略圖都有兩個特殊節點

  • nodeStart:策略圖的起點
  • nodeFinish:策略圖的終點

多階段資料處理流程

讓我們建立一個實際的範例,展示如何使用策略圖處理電商訂單

訂單處理流程圖

flowchart TD
    A[開始] --> B[驗證訂單節點]
    B --> C{驗證結果}
    C -->|驗證通過| D[計算價格節點]
    C -->|驗證失敗| E[錯誤處理節點]
    D --> F[生成確認節點]
    F --> G[結束]
    E --> G[結束]

    style A fill:#e1f5fe
    style B fill:#f3e5f5
    style C fill:#fff3e0
    style D fill:#f3e5f5
    style E fill:#ffebee
    style F fill:#f3e5f5
    style G fill:#e8f5e8

https://ithelp.ithome.com.tw/upload/images/20250817/20121948yq4NZ7PFBK.png

這個流程圖展示了策略圖中各個節點之間的關係

  • 驗證節點:檢查訂單資料的完整性
  • 條件分支:根據驗證結果決定後續流程
  • 成功路徑:驗證通過 → 計算價格 → 生成確認
  • 失敗路徑:驗證失敗 → 錯誤處理 → 結束
class OrderProcessingAgent {

    private val agent = AIAgent(
        executor = simpleOpenAIExecutor(ApiKeyManager.openAIApiKey!!),
        systemPrompt = "你是一個專業的訂單處理助手",
        llmModel = OpenAIModels.CostOptimized.GPT4_1Mini,
        // 使用自訂策略圖
        strategy = createOrderProcessingStrategy()
    )

    private fun createOrderProcessingStrategy() = strategy<String, String>("order_processing") {

        // 節點一:驗證訂單資料
        val validateOrderNode by node<String, String>("validate_order") { orderData ->
            println("正在驗證訂單資料...")

            // 模擬訂單驗證邏輯
            val lines = orderData.split("\n")
            val hasCustomerInfo = lines.any { it.contains("客戶:") }
            val hasProductInfo = lines.any { it.contains("商品:") }
            val hasAmount = lines.any { it.contains("金額:") }

            when {
                !hasCustomerInfo -> "錯誤:缺少客戶資訊"
                !hasProductInfo -> "錯誤:缺少商品資訊"
                !hasAmount -> "錯誤:缺少金額資訊"
                else -> {
                    println("訂單驗證通過")
                    "驗證通過:$orderData"
                }
            }
        }

        // 節點二:計算價格
        val calculatePriceNode by node<String, String>("calculate_price") { validatedOrder ->
            println("正在計算訂單價格...")

            // 從訂單中提取金額
            val amountLine = validatedOrder.split("\n")
                .find { it.contains("金額:") }

            val amount = amountLine?.substringAfter("金額:")?.trim()?.toDoubleOrNull() ?: 0.0
            val tax = amount * 0.05 // 5% 稅金
            val total = amount + tax

            val result = "$validatedOrder\n稅金:$tax\n總計:$total"
            println("價格計算完成,總計:$total")
            result
        }

        // 節點三:生成訂單確認
        val generateConfirmationNode by node<String, String>("generate_confirmation") { orderWithPrice ->
            println("正在生成訂單確認...")

            val confirmation = """
                訂單確認書
                ================
                $orderWithPrice
                ================
                狀態:已確認
                確認時間:${java.time.LocalDateTime.now()}
            """.trimIndent()

            println("訂單確認書生成完成")
            confirmation
        }

        // 節點四:錯誤處理
        val handleErrorNode by node<String, String>("handle_error") { errorMessage ->
            println("處理訂單錯誤")

            """
                訂單處理失敗
                錯誤原因:$errorMessage
                請檢查訂單資料並重新提交
            """.trimIndent()
        }

        // 定義執行流程
        edge(nodeStart forwardTo validateOrderNode)

        // 驗證成功 -> 計算價格
        edge(validateOrderNode forwardTo calculatePriceNode onCondition { result ->
            result.startsWith("驗證通過")
        })

        // 驗證失敗 -> 錯誤處理
        edge(validateOrderNode forwardTo handleErrorNode onCondition { result ->
            result.startsWith("錯誤")
        })

        // 計算價格 -> 生成確認
        edge(calculatePriceNode forwardTo generateConfirmationNode)

        // 所有路徑最終都到達結束點
        edge(generateConfirmationNode forwardTo nodeFinish)
        edge(handleErrorNode forwardTo nodeFinish)
    }

    suspend fun processOrder(orderData: String): String {
        return agent.run(orderData)
    }
}

雖然看起來程式碼很複雜,但是把每個 node 拆開來看,然後了解 edge 的流程走向,其實不會很複雜

多階段資料使用範例

suspend fun main() {
    val processor = OrderProcessingAgent()

    println("=== 訂單處理策略圖演示 ===\n")

    // 測試正常訂單
    val validOrder = """
        客戶:張小明
        商品:筆記型電腦
        金額:50000
    """.trimIndent()

    println("處理正常訂單:")
    try {
        val result = processor.processOrder(validOrder)
        println("\n處理結果:")
        println(result)
    } catch (e: Exception) {
        println("處理失敗:${e.message}")
    }

    println("\n" + "=".repeat(50) + "\n")

    // 測試異常訂單
    val invalidOrder = """
        客戶:李小華
        商品:智慧型手機
        // 缺少金額資訊
    """.trimIndent()

    println("處理異常訂單:")
    try {
        val result = processor.processOrder(invalidOrder)
        println("\n處理結果:")
        println(result)
    } catch (e: Exception) {
        println("處理失敗:${e.message}")
    }
}

執行 AI 回應內容

=== 訂單處理策略圖演示 ===

處理正常訂單:
正在驗證訂單資料...
訂單驗證通過
正在計算訂單價格...
價格計算完成,總計:52500.0
正在生成訂單確認...
訂單確認書生成完成

處理結果:
                訂單確認書
                ================
                驗證通過:客戶:張小明
商品:筆記型電腦
金額:50000
稅金:2500.0
總計:52500.0
                ================
                狀態:已確認
                確認時間:2025-08-17T17:31:42.787342

==================================================

處理異常訂單:
正在驗證訂單資料...
處理訂單錯誤

處理結果:
訂單處理失敗
錯誤原因:錯誤:缺少金額資訊
請檢查訂單資料並重新提交

策略圖的優勢

清晰的邏輯結構

每個節點職責單一,邊界清楚,整個流程一目了然

靈活的條件控制

透過條件邊,可以實現複雜的業務邏輯分流

易於測試和維護

每個節點可以獨立測試,便於除錯和修改

可重用性

節點可以在不同的策略圖中重複使用

與簡單策略的比較

特性 簡單策略 策略圖
複雜度
靈活性 有限 極高
條件控制 困難 簡單
錯誤處理 基本 完善
可維護性 一般 優秀
學習成本 中等

最佳實踐建議

節點設計原則

  • 單一職責:每個節點只做一件事
  • 明確命名:節點名稱要能表達其功能
  • 錯誤處理:考慮異常情況的處理路徑

流程設計技巧

  • 起始檢查:在流程開始時驗證輸入
  • 分流清楚:條件判斷要明確,避免模糊
  • 統一出口:盡量讓所有路徑都經過 nodeFinish

偵錯和測試

  • 添加日誌:在關鍵節點添加日誌輸出
  • 分段測試:先測試個別節點,再測試整個流程
  • 邊界測試:測試各種輸入情況

總結

今天我們學習了 Koog 框架策略圖的基礎概念

  • 策略圖架構:Strategy、Node、Edge 的組成關係
  • 節點設計:如何創建具有單一職責的處理單元
  • 流程控制:使用條件邊實現複雜的業務邏輯
  • 實際應用:透過訂單處理範例理解完整流程

策略圖是構建複雜 AI 應用的重要基礎,它讓我們能夠以結構化的方式設計和管理複雜的工作流程

下一篇文章我們將深入學習進階節點操作,包括 LLM 互動節點和工具執行節點,讓策略圖能夠與外部系統進行更豐富的互動

參考資源


圖片來源:AI 產生

同步刊登於 Blog 第一次學 Kotlin Koog AI 就上手 Day 22:策略圖基礎:構建多階段 AI 工作流程


上一篇
第一次學 Kotlin Koog AI 就上手 Day 21:標準化工具整合:MCP 協定實戰
下一篇
第一次學 Kotlin Koog AI 就上手 Day 23:進階節點操作:LLM 互動與工具執行
系列文
第一次學 Kotlin Koog AI 就上手24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言