- Published on
第一次學 Kotlin Koog AI 就上手 Day 22:策略圖基礎:構建多階段 AI 工作流程
在前面的文章中,我們學習了快取機制、記憶體系統、事件處理和策略路由等功能。今天我們要深入學習 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
這個流程圖展示了策略圖中各個節點之間的關係
- 驗證節點:檢查訂單資料的完整性
- 條件分支:根據驗證結果決定後續流程
- 成功路徑:驗證通過 → 計算價格 → 生成確認
- 失敗路徑:驗證失敗 → 錯誤處理 → 結束
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 產生