
在前一篇文章中,我們學習了如何調校 AIAgent 的配置參數。但是,即使配置得再完美的 AI 系統,在真實世界中也難免會遇到各種問題:API 金鑰失效、網路連線中斷、服務暫停等。今天我們將學習如何建立基礎的錯誤處理機制,讓你的 AI 應用能夠優雅地應對這些常見問題
想像一下以下場景
如果沒有適當的錯誤處理,這些情況會造成糟糕的用戶體驗。一個具備基礎錯誤處理的 AI 應用應該能夠
預期常見的錯誤情況,提供友善的錯誤訊息,避免程式直接崩潰
最常見的錯誤是 API 金鑰問題或模型不支援
suspend fun main() {
    try {
        val agent = AIAgent(
            // executor = simpleOpenAIExecutor(ApiKeyManager.openAIApiKey!!),
            // 使用假的 api key 來模擬錯誤
            executor = simpleOpenAIExecutor("fake api key"),
            systemPrompt = "你是一個友善的 AI 助手",
            llmModel = OpenAIModels.CostOptimized.GPT4_1Mini
        )
        // 測試是否能正常運作
        val result = agent.run("你好")
        println("✅ Agent 建立成功:$result")
    } catch (e: Exception) {
        when {
            // API 金鑰相關錯誤
            e.message?.contains("api", ignoreCase = true) == true ||
                    e.message?.contains("key", ignoreCase = true) == true ||
                    e.message?.contains("auth", ignoreCase = true) == true -> {
                println("❌ API 金鑰問題:請檢查您的 API 金鑰是否正確且有效")
            }
            // 配額相關錯誤
            e.message?.contains("quota", ignoreCase = true) == true ||
                    e.message?.contains("limit", ignoreCase = true) == true -> {
                println("⏱️ API 配額已滿:請稍後再試或檢查您的使用配額")
            }
            // 其他 API 錯誤
            else -> {
                println("原始錯誤訊息:${e.message}")
                println("❓ 無法連接到 AI 服務,請稍後再試")
            }
        }
    }
}
相關的錯誤判斷這裡只是大概的示意,但實際上可能還會有更多細節需要考慮,例如錯誤代碼、錯誤訊息的格式等。請根據實體的情況進行調整。
正常情況
✅ Agent 建立成功:你好!很高興見到你,有什麼我可以幫忙的嗎?
使用一個假的 API Key 來模擬錯誤的情況
❌ API 金鑰問題:請檢查您的 API 金鑰是否正確且有效
網路問題也是常見的錯誤來源
suspend fun main() {
    val agent = AIAgent(
        executor = simpleOpenAIExecutor(ApiKeyManager.openAIApiKey!!),
        systemPrompt = "你是一個友善的 AI 助手",
        llmModel = OpenAIModels.CostOptimized.GPT4_1Mini
    )
    try {
        // 設定 5 秒超時
        withTimeout(5000) {
            val result = agent.run("你好")
            // delay 6 秒來模擬錯誤的情況
            delay(6000)
            println("✅ Agent 建立成功:$result")
        }
    } catch (e: TimeoutCancellationException) {
        println("⏰ 回應時間過長,請檢查網路連線後再試")
    } catch (e: Exception) {
        when {
            // 網路連線問題
            e.message?.contains("network", ignoreCase = true) == true ||
                    e.message?.contains("connection", ignoreCase = true) == true ||
                    e.message?.contains("timeout", ignoreCase = true) == true -> {
                println("🌐 網路連線問題,請檢查網路設定後再試")
            }
            // 服務不可用
            e.message?.contains("service", ignoreCase = true) == true ||
                    e.message?.contains("unavailable", ignoreCase = true) == true -> {
                 println("🚫 AI 服務暫時不可用,請稍後再試")
            }
            else -> {
                println("網路錯誤詳情:${e.message}") // 開發時用於除錯
                println("❓ 處理請求時發生問題,請稍後再試")
            }
        }
    }
}
正常情況
✅ Agent 建立成功:你好!很高興見到你,有什麼我可以幫忙的嗎?
使用 delay 來模擬回應時間過長的情況
⏰ 回應時間過長,請檢查網路連線後再試
有時候錯誤是暫時的,我們可以實作簡單的重試機制
suspend fun <T> simpleRetry(
    maxAttempts: Int = 3,
    delayMs: Long = 1000,
    operation: suspend () -> T
): T {
    repeat(maxAttempts) { attempt ->
        try {
            return operation()
        } catch (e: Exception) {
            println("嘗試 ${attempt + 1} 失敗:${e.message}")
            delay(delayMs)
        }
    }
    // 最後一次嘗試,如果失敗就讓異常拋出
    return operation()
}
// 使用範例
suspend fun main() {
    val agent = AIAgent(
        executor = simpleOpenAIExecutor(ApiKeyManager.openAIApiKey!!),
        systemPrompt = "你是一個友善的 AI 助手",
        llmModel = OpenAIModels.CostOptimized.GPT4_1Mini
    )
    try {
        simpleRetry(maxAttempts = 3, delayMs = 2000) {
            val result= agent.run("你好")
            // 直接丟出 error 來模擬未知的錯誤
            throw Exception("unknown error")
            println("✅ Agent 建立成功:$result")
        }
    } catch (e: Exception) {
        println("❌ 經過多次嘗試後仍無法處理您的請求,請稍後再試")
    }
}
正常情況
✅ Agent 建立成功:你好!很高興見到你,有什麼我可以幫忙的嗎?
直接 throw Exception 來模擬未知錯誤的發生情況
嘗試 1 失敗:unknown error
嘗試 2 失敗:unknown error
嘗試 3 失敗:unknown error
❌ 經過多次嘗試後仍無法處理您的請求,請稍後再試
除了基本的重試機制,我們還可以建立多供應商的 Fallback 機制。當主要的 LLM 供應商服務中斷或發生錯誤時,系統可以自動切換到備用供應商,確保服務的持續性
多供應商 Fallback 機制提供了以下優勢
💡 延伸學習:這裡只是簡單介紹多供應商 Fallback 的概念。如果您想了解完整的多 LLM 供應商整合實作,可以參考 Day 04:多 LLM 供應商整合 文章,裡面有詳細的程式碼範例和實作說明
現在讓我們把前面學到的錯誤處理技術整合起來,建立一個安全的 AI 助手
/**
 * 安全的 AI 助手 - 整合錯誤處理技術
 */
class SafeAIHelper {
    fun createSafeAIAgent(): AIAgent<String, String>? {
        return try {
            AIAgent(
                executor = simpleOpenAIExecutor(ApiKeyManager.openAIApiKey!!),
                systemPrompt = "你是一個友善的 AI 助手,用正體中文回答問題",
                llmModel = OpenAIModels.CostOptimized.GPT4_1Mini
            )
        } catch (e: Exception) {
            println("建立 Agent 時發生錯誤:${e.message}")
            null
        }
    }
    suspend fun askAI(question: String): String {
        val agent = createSafeAIAgent()
        // 如果 Agent 建立失敗
        if (agent == null) {
            return "❌ AI 助手暫時無法使用,請稍後再試"
        }
        return try {
            // 使用重試機制 + 超時處理
            simpleRetry() {
                // 5秒超時
                withTimeout(5000) {
                    // delay 6 秒來模擬錯誤的情況
                    delay(6000)
                    agent.run(question)
                }
            }
        } catch (e: TimeoutCancellationException) {
            "⏰ 回應時間過長,請稍後再試"
        } catch (e: Exception) {
            "❓ 處理問題時發生錯誤,請稍後再試"
        }
    }
    suspend fun <T> simpleRetry(
        maxAttempts: Int = 3,
        delayMs: Long = 1000,
        operation: suspend () -> T
    ): T {
        repeat(maxAttempts) { attempt ->
            try {
                return operation()
            } catch (e: Exception) {
                println("嘗試 ${attempt + 1} 失敗:${e.message}")
                delay(delayMs)
            }
        }
        // 最後一次嘗試,如果失敗就讓異常拋出
        return operation()
    }
}
這個範例整合了我們這次學到的幾種錯誤處理技術
為了版面的程式碼不要過長,這裡並沒有把所有的錯誤的情況都放到這個範例中判斷,有興趣的可以寫一個更加完整的錯誤處理元件
讓我們測試一下這個安全的 AI 助手
suspend fun main() {
    val aiHelper = SafeAIHelper()
    println("🤖 測試安全 AI 助手")
    println("=".repeat(30))
    val questions = listOf(
        "你好",
        "什麼是 Kotlin 協程? 請簡單回答"
    )
    questions.forEach { question ->
        println("\n💬 問題:$question")
        val answer = aiHelper.askAI(question)
        println("🤖 回答:$answer")
        println("-".repeat(30))
    }
}
正常情況
🤖 測試安全 AI 助手
==============================
💬 問題:你好
🤖 回答:你好!有什麼我可以幫忙的嗎?
------------------------------
💬 問題:什麼是 Kotlin 協程? 請簡單回答
🤖 回答:Kotlin 協程是一種輕量級的非同步程式設計工具,讓你可以用類似同步的方式撰寫非同步代碼,簡化異步操作和多線程管理。
使用 delay 來模擬回應時間過長的情況
🤖 測試安全 AI 助手
==============================
💬 問題:你好
嘗試 1 失敗:Timed out waiting for 5000 ms
嘗試 2 失敗:Timed out waiting for 5000 ms
嘗試 3 失敗:Timed out waiting for 5000 ms
🤖 回答:⏰ 回應時間過長,請稍後再試
------------------------------
💬 問題:什麼是 Kotlin 協程? 請簡單回答
嘗試 1 失敗:Timed out waiting for 5000 ms
嘗試 2 失敗:Timed out waiting for 5000 ms
嘗試 3 失敗:Timed out waiting for 5000 ms
🤖 回答:⏰ 回應時間過長,請稍後再試
------------------------------
Exception: OpenAI API key is invalid
API 金鑰問題:請檢查您的 API 金鑰是否正確且有效
fun createHelpfulErrorMessage(error: Exception): String {
    return when {
        error.message?.contains("key") == true ->
            "🔑 API 金鑰問題:請到 OpenAI 官網檢查您的金鑰是否有效"
        error.message?.contains("network") == true ->
            "🌐 網路問題:請檢查網路連線,或稍後再試"
        else -> "❓ 遇到問題了,請稍後再試或聯繫客服"
    }
}
fun logErrorForDebugging(error: Exception, context: String) {
    // 開發環境:詳細記錄
    if (System.getProperty("environment") == "development") {
        println("錯誤詳情 [$context]: ${error.message}")
        error.printStackTrace()
    }
    // 生產環境:簡化記錄
    println("錯誤 [$context]: ${error.javaClass.simpleName}")
}
今天我們學習了 Koog 應用的基礎錯誤處理技巧
下一篇文章中,我們將探討實戰專案的開發,建立一個完整的 AI 聊天機器人
圖片來源:AI 產生