在前面的學習中,我們已經建立了基本的 Koog AI Agent 並了解了提示系統的 DSL 語法。今天我們將探索 Koog 框架的重要特色:多 LLM 供應商整合
在實際應用中,依賴單一 LLM 供應商往往會面臨成本、效能和可靠性的挑戰。Koog 的多供應商支援讓我們能夠建立更穩健和更靈活的 AI 應用
在深入技術實作之前,讓我們先了解多 LLM 整合的重要性
每個 LLM 供應商都有其擅長領域,根據實際使用經驗,不同供應商適合不同的使用場景
實際使用場景分配
這裡的使用場景是根據我平常的使用習慣來區分的
多 LLM 策略可以顯著提升應用穩定性
實際效益
Koog 目前支援以下 LLM 供應商
模型選擇說明:每個 LLM 供應商都有眾多模型可選擇,不可能在文章中一一列出和介紹。這裡我只列舉比較常用或 CP 值比較高的模型作為範例,實際使用時請根據個人需求、預算和應用場景來選擇最適合的模型
重要說明:雖然 GPT-5 是 OpenAI 最新的模型,但因為 Koog 框架還沒有更新相關的 model 程式碼支援,所以統一使用 GPT-4.1 (mini),包含先前的文章也是一樣
Anthropic
Google AI
OpenRouter
這裡只有列出部份支援的 LLM 供應商而已, 沒有全部
注意:基於 API 測試費用考量,本教學僅使用兩個雲端 API(OpenAI、Google)和本地模型(Ollama)進行測試
在 IntelliJ IDEA 中設定環境變數(參考 Day 02 的設定方式)
Environment variables
欄位中加入OPENAI_API_KEY=你的OpenAI API金鑰
GOOGLE_API_KEY=你的Google API金鑰
OLLAMA_BASE_URL=http://localhost:11434
object ApiKeyManager {
val openAIApiKey: String = System.getenv("OPENAI_API_KEY")
val googleApiKey: String = System.getenv("GOOGLE_API_KEY")
val ollamaBaseUrl: String = System.getenv("OLLAMA_BASE_URL")
// 檢查可用的供應商
fun getAvailableProviders(): List<String> {
val available = mutableListOf<String>()
if (openAIApiKey.isNotBlank()) {
available.add("OpenAI")
}
if (googleApiKey.isNotBlank()) {
available.add("Google")
}
if (ollamaBaseUrl.isNotBlank()) {
available.add("Ollama")
}
return available
}
}
Koog 提供了 MultiLLMPromptExecutor
來統一管理多個 LLM 客戶端
class BasicMultiLLMSetup {
fun createBasicMultiExecutor(): MultiLLMPromptExecutor {
val executors = mutableMapOf<LLMProvider, LLMClient>()
ApiKeyManager.openAIApiKey?.let { apiKey ->
executors[LLMProvider.OpenAI] = OpenAILLMClient(apiKey)
println("✅ OpenAI GPT 執行器已加入(大 Context 處理)")
}
ApiKeyManager.googleApiKey?.let { apiKey ->
executors[LLMProvider.Google] = GoogleLLMClient(apiKey)
println("✅ Google Gemini 執行器已加入(大 Context 處理)")
}
ApiKeyManager.ollamaBaseUrl?.let { baseUrl ->
executors[LLMProvider.Ollama] = OllamaClient(baseUrl)
println("✅ Ollama 執行器已加入(本地隱私保護)")
}
return MultiLLMPromptExecutor(executors)
}
}
讓我們建立一個簡單的多 LLM 應用,展示基本的整合使用
suspend fun main() {
println("🤖 多 LLM 助手系統啟動中...")
// 顯示可用的供應商
println("📋 可用的 LLM 供應商:")
ApiKeyManager.getAvailableProviders().forEach { provider ->
println(" ✅ $provider")
}
try {
val setup = BasicMultiLLMSetup()
val multiExecutor = setup.createBasicMultiExecutor()
// 建立多 LLM Agent
val agent = AIAgent(
executor = multiExecutor,
systemPrompt = "你是一個智能助手,使用多個 LLM 供應商為使用者提供最佳服務。請用正體中文回答問題。",
llmModel = OpenAIModels.CostOptimized.GPT4_1Mini
)
println("\n✅ 多 LLM 助手系統已就緒!")
// 測試不同類型的問題
val testQuestions = listOf(
"你好,你現在正在使用哪個模型回答問題? 請具體回答出那一個模型"
)
println("\n👤 使用者:$question")
println("🤖 AI 回答:")
val response = agent.run(question)
println(response)
} catch (e: Exception) {
println("❌ 系統啟動失敗:${e.message}")
e.printStackTrace()
}
}
基本上,這裡會根據你給它的 Model
來決定使用哪個 Executor
(供應商)
先使用 OpenAIModels.CostOptimized.GPT4_1Mini
來執行測試
🤖 多 LLM 助手系統啟動中...
📋 可用的 LLM 供應商:
✅ OpenAI (GPT-4.1 mini)
✅ Google (Gemini 2.5 Flash)
✅ Ollama (gpt-oss:20b)
✅ OpenAI GPT 執行器已加入(大 Context 處理)
✅ Google Gemini 執行器已加入(大 Context 處理)
✅ Ollama 執行器已加入(本地隱私保護)
✅ 多 LLM 助手系統已就緒!
👤 使用者:你好,你現在正在使用哪個模型回答問題? 請具體回答出那一個模型
🤖 AI 回答:
你好!我目前使用的是OpenAI的GPT-4模型來回答你的問題。如果你有任何需要,隨時告訴我!
如果我們把 Model
換成 GoogleModels.Gemini2_5Flash
🤖 多 LLM 助手系統啟動中...
📋 可用的 LLM 供應商:
✅ OpenAI
✅ Google
✅ Ollama
✅ OpenAI GPT 執行器已加入(大 Context 處理)
✅ Google Gemini 執行器已加入(大 Context 處理)
✅ Ollama 執行器已加入(本地隱私保護)
✅ 多 LLM 助手系統已就緒!
👤 使用者:你好,你現在正在使用哪個模型回答問題? 請具體回答出那一個模型
🤖 AI 回答:
你好!
我是一個大型語言模型,由 Google 訓練。
在前面的範例,雖然 AIAgent
會自動根據模型來選擇 Executor
,不過還是需要寫死模型在程式碼裡面,我們是不是可以改成,自動根據任務類型來選擇合適的模型,這樣子就不用人工介入了
在 BasicMultiLLMSetup
裡增加一個依 task 來選擇模型的 fun
注意,這裡沒有考慮到 AI 供應商是否可用的問題,只是單純的選擇模型
// 簡單的供應商模型選擇
fun selectModelForTask(taskType: String): LLModel {
return when (taskType.lowercase()) {
// 日常對話的最佳選擇
"chat", "conversation" -> OpenAIModels.CostOptimized.GPT4_1Mini
// 大 Context 資料處理(
"data", "analysis" -> GoogleModels.Gemini2_5Flash
// Ollama
"privacy", "local" -> OllamaModels.Meta.LLAMA_3_2_3B
// 通用任務的平衡選擇
else -> OpenAIModels.CostOptimized.GPT4_1Mini
}
}
可以把相關對應 task 的 prompt 都先寫好,只要使用者輸入對應的 task,就會自動給它對應的 AI Agent
class BasicMultiLLMAssistant {
private val multiLLMSetup = BasicMultiLLMSetup()
fun createAgent(taskType: String): AIAgent<String, String> {
val multiExecutor = multiLLMSetup.createBasicMultiExecutor()
val modelSuggestion = multiLLMSetup.selectModelForTask(taskType)
println("Task: $taskType, 🎯 模型:${model.provider} - ${model.id}")
return AIAgent(
executor = multiExecutor,
systemPrompt = buildTaskPrompt(taskType),
llmModel = modelSuggestion,
maxIterations = 5
)
}
private fun buildTaskPrompt(taskType: String): String {
return when (taskType.lowercase()) {
"chat", "conversation" -> """
你是一個友善的 AI 助手,用正體中文回答問題
- 以自然、溫暖的方式回應
- 提供有用的資訊和建議
- 保持禮貌和專業的態度
""".trimIndent()
"data", "analysis" -> """
你是一個資料分析助手,用正體中文回答問題
- 仔細分析提供的大量資訊
- 提供結構化的分析結果
- 善於處理複雜的資料和長文本
""".trimIndent()
"privacy", "local" -> """
你是一個注重隱私的本地助手,用正體中文回答問題
- 優先保護使用者隱私
- 提供安全可靠的建議
- 不會將資料傳送到外部服務
""".trimIndent()
else -> """
你是一個通用 AI 助手,用正體中文回答問題
- 根據使用者需求提供協助
- 保持專業和有用的回應
- 適時詢問更多細節以提供更好的服務
""".trimIndent()
}
}
}
建立一個簡單的測試程式來驗證多 LLM 設定
suspend fun main() {
println("🤖 多 LLM 助手系統啟動中...")
// 顯示可用的供應商
println("📋 可用的 LLM 供應商:")
ApiKeyManager.getAvailableProviders().forEach { provider ->
println(" ✅ $provider")
}
try {
val setup = BasicMultiLLMAssistant()
println("\n✅ 多 LLM 助手系統已就緒!")
// 顯示可用的任務類型
println("\n📋 可用的任務類型:")
println(" 1. chat - 日常對話")
println(" 2. data - 資料分析")
println(" 3. privacy - 隱私保護(本地處理)")
// 使用者輸入任務類型
print("\n請輸入任務類型(chat/data/privacy):")
val taskType = readlnOrNull()?.trim() ?: "chat"
// 建立對應的 Agent
val agent = setup.createAgent(taskType)
// 使用者輸入問題
print("請輸入您的問題:")
val question = "你好,你現在正在使用哪個模型回答問題? 請具體回答出那一個模型"
println("\n👤 使用者:$question")
println("🤖 AI 回答:")
val response = agent.run(question)
println(response)
} catch (e: Exception) {
println("❌ 系統啟動失敗:${e.message}")
e.printStackTrace()
}
}
🤖 多 LLM 助手系統啟動中...
📋 可用的 LLM 供應商:
✅ OpenAI
✅ Google
✅ Ollama
✅ 多 LLM 助手系統已就緒!
📋 可用的任務類型:
1. chat - 日常對話
2. data - 資料分析
3. privacy - 隱私保護(本地處理)
請輸入任務類型(chat/data/privacy):chat
✅ OpenAI GPT 執行器已加入(大 Context 處理)
✅ Google Gemini 執行器已加入(大 Context 處理)
✅ Ollama 執行器已加入(本地隱私保護)
Task: chat, 🎯 模型:OpenAI - gpt-4.1-mini
請輸入您的問題:
👤 使用者:你好,你現在正在使用哪個模型回答問題? 請具體回答出那一個模型
🤖 AI 回答:
你好!我現在是基於 OpenAI 的 GPT-4 模型來回答你的問題。如果你有任何疑問或需要幫助,隨時告訴我哦!很高興為你服務。
在實際應用中,LLM 供應商可能會遇到服務中斷、API 限制或網路問題。讓我們繼承 BasicMultiLLMSetup
,實作一個簡單實用的 Fallback 機制,當主要供應商失敗時自動切換到備用供應商
這邊接續第一個範例來實作 Fallback 機制,暫不考慮 auto fallback 選擇供應商
class FallbackMultiLLMSetup : BasicMultiLLMSetup() {
// 建立主要和備用執行器
private val primaryExecutor = simpleOpenAIExecutor(ApiKeyManager.openAIApiKey!!)
private val fallbackExecutor = simpleGoogleAIExecutor(ApiKeyManager.googleApiKey!!)
// 定義主要和備用模型
private val primaryModel = OpenAIModels.CostOptimized.GPT4_1Mini
private val fallbackModel = GoogleModels.Gemini2_5Flash
// 簡單的備用機制 - 主要邏輯
suspend fun executeWithFallback(prompt: Prompt): String {
return try {
println("🔄 嘗試使用 OpenAI 供應商...")
val result = primaryExecutor.execute(prompt, primaryModel)
println("✅ OpenAI 供應商回應成功")
// 假設回應格式,實際需要根據框架調整
result.firstOrNull()?.content ?: "無回應內容"
} catch (e: Exception) {
println("❌ OpenAI 供應商失敗:${e.message}")
println("🔄 切換到 Google 備用供應商...")
try {
val fallbackResult = fallbackExecutor.execute(prompt, fallbackModel)
println("✅ Google 供應商回應成功")
fallbackResult.firstOrNull()?.content ?: "無回應內容"
} catch (fallbackError: Exception) {
println("❌ Google 備用供應商也失敗:${fallbackError.message}")
throw Exception("所有 LLM 供應商都無法使用。主要錯誤:${e.message},備用錯誤:${fallbackError.message}")
}
}
}
// 建立簡化的對話介面
fun createSimpleFallbackChat(): SimpleFallbackChat {
return SimpleFallbackChat(this)
}
}
// 簡單的對話包裝器
class SimpleFallbackChat(private val setup: FallbackMultiLLMSetup) {
suspend fun chat(question: String): String {
// 建立簡單的文字提示
val prompt = prompt("fallback-chat") {
system("你是一個通用 AI 助手,用正體中文回答問題")
user(question)
}
return setup.executeWithFallback(prompt)
}
}
suspend fun main() {
println("🤖 帶有 Fallback 機制的多 LLM 助手系統啟動中...")
// 顯示可用的供應商
println("📋 可用的 LLM 供應商:")
ApiKeyManager.getAvailableProviders().forEach { provider ->
println(" ✅ $provider")
}
try {
val setup = FallbackMultiLLMSetup()
println("\n✅ Fallback 多 LLM 助手系統已就緒!")
println("🛡️ 當主要供應商失敗時,系統會自動切換到備用供應商")
// 建立簡化的 Fallback 對話
val chat = setup.createSimpleFallbackChat()
val question = "你好,請介紹你自己,並告訴我你是使用哪個模型回答的?"
println("\n👤 使用者:$question")
println("🤖 AI 回答:")
val response = chat.chat(question)
println(response)
} catch (e: Exception) {
println("❌ 系統完全失敗:${e.message}")
e.printStackTrace()
}
}
主要供應商正常運作
🤖 帶有 Fallback 機制的多 LLM 助手系統啟動中...
📋 可用的 LLM 供應商:
✅ OpenAI
✅ Google
✅ Ollama
✅ Fallback 多 LLM 助手系統已就緒!
🛡️ 當主要供應商失敗時,系統會自動切換到備用供應商
👤 使用者:你好,你現在正在使用哪個模型回答問題? 請具體回答出那一個模型
🤖 AI 回答:
🔄 嘗試使用 OpenAI 供應商...
✅ OpenAI 供應商回應成功
你好!我現在使用的是基於 OpenAI 的 GPT-4 架構的語言模型來回答你的問題。
主要供應商失敗,自動 Fallback
透過一個有問題的 OpenAI API Key,來模擬切換供應商
🤖 帶有 Fallback 機制的多 LLM 助手系統啟動中...
📋 可用的 LLM 供應商:
✅ OpenAI (模擬失敗)
✅ Google
✅ Ollama
✅ Fallback 多 LLM 助手系統已就緒!
🛡️ 當主要供應商失敗時,系統會自動切換到備用供應商
👤 使用者:你好,你現在正在使用哪個模型回答問題? 請具體回答出那一個模型
🤖 AI 回答:
🔄 嘗試使用 OpenAI 供應商...
❌ OpenAI 供應商失敗:Error from OpenAI API: 401 Unauthorized: {
"error": {
"message": "Incorrect API key provided: error. You can find your API key at https://platform.openai.com/account/api-keys.",
"type": "invalid_request_error",
"param": null,
"code": "invalid_api_key"
}
}
🔄 切換到 Google 備用供應商...
✅ Google 供應商回應成功
我是一個大型語言模型,由 Google 訓練。
這個 Fallback 實作提供了以下優勢
自動容錯
優先級管理
透明的錯誤處理
成本優化
今天我們學習了 Koog 框架的多 LLM 供應商整合基礎,掌握了以下核心概念
下一篇文章我們將探索 Koog 的工具系統入門,學習如何為 AI Agent 添加實際的操作能力,從純粹的對話系統進化為能夠執行具體任務的 AI 助手
圖片來源:AI 產生
同步刊登於 Blog 第一次學 Kotlin Koog AI 就上手 Day 04:多 LLM 供應商整合