在前面的文章中,我們已經學習了快取機制(Day 13)和記憶體系統(Day 14),並在上一篇文章學習了事件處理與生命週期管理。今天我們將學習一個實用技巧:如何使用規則型分流讓系統自動判斷問題的複雜度,並選擇最適合的處理方式。簡單問題快速回應,複雜問題深度支援
想像一下日常生活中的情景:當有人問你「現在幾點?」時,你會快速回答;但當有人問「我的電腦無法開機,怎麼辦?」時,你會仔細了解問題並提供詳細的解決步驟
在 AI 客服系統中,我們也需要同樣的分流機制
簡單問題 → 快速回應
複雜問題 → 深度支援
讓我們來建立一個 QueryRouter
,它能自動判斷問題的複雜度並選擇最適合的處理方式
/**
* QueryRouter - 策略路由的核心類別
* 根據問題類型自動選擇最適合的 Agent
*/
class QueryRouter {
// 快速回應 Agent - 單次執行策略
private val quickAgent = AIAgent(
executor = simpleOpenAIExecutor(openAIKey),
strategy = singleRunStrategy(), // 簡單問題用單次執行
systemPrompt = """
你是一個高效客服助手,專門處理簡單查詢
回答要直接、準確、簡潔
使用正體中文回答
""".trimIndent(),
llmModel = OpenAIModels.CostOptimized.GPT4_1Mini
)
// 深度支援 Agent - 聊天對話策略
private val deepAgent = AIAgent(
executor = simpleOpenAIExecutor(openAIKey),
strategy = chatAgentStrategy(), // 複雜問題用對話策略
systemPrompt = """
你是一個專業的技術支援專家,能處理複雜問題
可以與客戶多輪互動,深入了解問題並提供詳細解決方案
使用正體中文回答
""".trimIndent(),
llmModel = OpenAIModels.CostOptimized.GPT4_1Mini,
toolRegistry = ToolRegistry {
// 可以主動向用戶說話
tool(SayToUser)
// 可以詢問更多資訊
tool(AskUser)
}
)
/**
* 核心功能:判斷問題是否複雜
* 這是基於規則的簡單分類邏輯
*
* 您可以根據需求調整:
* - 增加或修改關鍵字清單
* - 調整長度閾值(目前是 50 字)
* - 加入其他判斷條件(如:包含特定符號、多個句子等)
*/
private fun isComplexQuery(query: String): Boolean {
// 複雜問題的關鍵字
val complexKeywords = listOf(
"分析", "比較", "問題", "故障", "無法",
"不滿意", "投訴", "退款", "協助", "解決"
)
// 檢查是否包含複雜關鍵字
val hasComplexKeywords = complexKeywords.any { query.contains(it) }
// 長問題通常更複雜
val isLongQuery = query.length > 50
return hasComplexKeywords || isLongQuery
}
/**
* 處理客戶查詢的主方法
*/
suspend fun handleQuery(query: String): QueryResult {
return try {
val startTime = System.currentTimeMillis()
// 這裡就是策略路由的關鍵!
val result = if (isComplexQuery(query)) {
println("識別為複雜問題,使用深度支援 Agent")
deepAgent.run(query)
} else {
println("識別為簡單問題,使用快速回應 Agent")
quickAgent.run(query)
}
val processingTime = System.currentTimeMillis() - startTime
QueryResult(
answer = result,
isComplex = isComplexQuery(query),
processingTimeMs = processingTime
)
} catch (e: Exception) {
println("處理問題時發生錯誤: ${e.message}")
QueryResult(
answer = "抱歉,系統暫時無法處理您的問題。請稍後再試",
isComplex = false,
processingTimeMs = 0,
error = e.message
)
}
}
}
// 結果資料類別
data class QueryResult(
val answer: String,
val isComplex: Boolean,
val processingTimeMs: Long,
val error: String? = null
)
讓我們來測試一下 QueryRouter
的策略路由效果
suspend fun main() {
val router = QueryRouter()
println("QueryRouter 策略路由測試")
println("=".repeat(50))
// 測試案例
val testQueries = listOf(
"你們的營業時間是什麼?", // 簡單問題
"我的產品無法正常運作,需要協助解決", // 複雜問題
)
testQueries.forEachIndexed { index, query ->
println("\n測試 ${index + 1}: $query")
val result = router.handleQuery(query)
val strategyName = if (result.isComplex) "深度支援" else "快速回應"
println("選擇策略: $strategyName")
println("處理時間: ${result.processingTimeMs}ms")
println("AI 回應: ${result.answer}")
if (index < testQueries.size - 1) {
println("=".repeat(50))
}
}
println("\n測試完成!策略路由成功運作")
}
QueryRouter 策略路由測試
==================================================
測試 1: 你們的營業時間是什麼?
識別為簡單問題,使用快速回應 Agent
選擇策略: 快速回應
處理時間: 1048ms
AI 回應: 我們的營業時間是週一至週五,上午9點到下午6點。
==================================================
測試 2: 我的產品無法正常運作,需要協助解決
識別為複雜問題,使用深度支援 Agent
您好,請問您的產品是什麼類型?能否描述一下具體的問題或錯誤現象?這樣我可以更精準地幫助您解決問題。
> 我的智慧手錶有問題,無法開機
了解您的智慧手錶無法開機。請問您之前是否有看到任何異常情況,例如電量過低、曾經進行過更新、或是有摔落或進水的情況?另外,您是否嘗試過充電,或長按電源鍵一段時間?
> 都沒有
謝謝您的回覆。接下來我們可以嘗試以下步驟:
1. 請確認充電器和充電線是否正常運作,可以嘗試用其他相容的充電器或線。
2. 將手錶連接充電器,至少充電15分鐘後,再長按電源鍵10秒以上,看看是否可以開機。
3. 如果還是無法開機,請問您的手錶型號和購買時間?方便我判斷是否在保固期內安排後續維修。
> 好的
請提供您的智慧手錶型號和購買日期,這樣我可以幫您確認保固狀況並提供下一步的維修建議。
> a1001,2025/03/01
Agent says: 您的智慧手錶型號為A1001,購買日期為2025年3月1日。根據資料,您的手錶仍在保固期內。建議您可以先嘗試使用我們官方指定的充電器和線進行充電,如果問題仍未解決,我們可以協助您安排維修服務。請問您需要我協助您預約維修嗎?
> 先不用了
Agent says: 好的,如果您之後需要任何協助或想要預約維修,隨時告訴我。我會隨時為您服務,祝您有美好的一天!
選擇策略: 深度支援
處理時間: 82966ms
測試完成!策略路由成功運作
QueryRouter
的核心就是 isComplexQuery
函數,它使用兩個簡單但有效的指標
重要提醒:這個判斷邏輯完全可以根據您的業務需求調整!您可以
private fun isComplexQuery(query: String): Boolean {
val complexKeywords = listOf(
"分析", "比較", "問題", "故障", "無法",
"不滿意", "投訴", "退款", "協助", "解決"
)
val hasComplexKeywords = complexKeywords.any { query.contains(it) }
val isLongQuery = query.length > 50
return hasComplexKeywords || isLongQuery
}
特性 | 快速回應 Agent | 深度支援 Agent |
---|---|---|
策略 | simpleSingleRunStrategy() |
chatAgentStrategy() |
工具 | 無 | SayToUser , AskUser |
適用場景 | 簡單查詢 | 複雜問題 |
使用 QueryRouter
帶來的具體改善
我們實作的 QueryRouter
使用簡單的規則判斷,這種方式
優點
限制
Koog 框架提供了更強大的 Custom Strategy Graphs,它能夠
在接下來的文章中,我們會探索更進階的概念
這些進階技術將展示如何建立更複雜、更靈活的處理流程
今天我們學習了策略路由的核心概念,並實作了一個簡單而有效的 QueryRouter
在下一篇文章中,我們將學習 Koog 的流式處理與即時回應功能,探討如何為用戶提供更流暢的互動體驗
圖片來源:AI 產生
同步刊登於 Blog 第一次學 Kotlin Koog AI 就上手 Day 16:策略路由:根據問題類型選擇最適合的 Agent