- Published on
Koog Kotlin AI 框架實戰 Day 35:Koog 0.0.4 版本重大更新 - 可觀測、可預測、可部署
前言
從我們開始這系列教學以來,Koog 框架持續快速發展,每個版本都帶來令人驚喜的新功能。今天要介紹的 0.0.4 版本可以說是一個里程碑,JetBrains 團隊以「Observable, Predictable, Deployable Anywhere You Build」為核心理念,為企業級 AI Agent 開發帶來了革命性的改進。這個版本的五大核心更新將徹底改變我們開發和部署 AI Agent 的方式
OpenTelemetry 可觀測性支援
什麼是可觀測性
可觀測性(Observability)是現代分散式系統的核心概念,對於 AI Agent 而言更是至關重要。想像一下,當你的 AI Agent 在生產環境中處理成千上萬個請求時,你需要知道:
- 每個請求花費了多少時間
- 哪些 LLM 模型被呼叫了多少次
- Token 使用量和成本分析
- 錯誤發生在哪個環節
Koog 0.0.4 透過整合 OpenTelemetry,讓這些問題都有了答案
整合 W&B Weave 和 Langfuse
新版本支援與業界領先的 AI 可觀測性平台整合:
- W&B Weave:專為 LLM 應用設計的追蹤系統
- Langfuse:開源的 LLM 工程平台
- Jaeger:分散式追蹤系統
完整的實作範例
讓我們看看如何在實際專案中配置 OpenTelemetry:
// 檔案:src/main/kotlin/observability/ObservableAgent.kt
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.features.opentelemetry.feature.OpenTelemetry
import ai.koog.agents.utils.use
import ai.koog.prompt.executor.clients.openai.OpenAIModels
import ai.koog.prompt.executor.llms.all.simpleOpenAIExecutor
import io.opentelemetry.exporter.logging.LoggingSpanExporter
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.sdk.trace.samplers.Sampler
import kotlinx.coroutines.runBlocking
const val openAIApiKey = "your-openai-api-key"
fun main() {
runBlocking {
// 創建具備完整可觀測性的 AI Agent
val agent = AIAgent(
executor = simpleOpenAIExecutor(openAIApiKey),
llmModel = OpenAIModels.Chat.GPT4o,
systemPrompt = "你是一個智能客服助手,專門處理技術支援問題"
) {
install(OpenTelemetry) {
// 設定服務資訊
setServiceInfo("intelligent-customer-service", "1.0.0")
// 添加控制台日誌輸出(開發環境)
addSpanExporter(LoggingSpanExporter.create())
// 連接到 Jaeger(本機開發環境)
addSpanExporter(
OtlpGrpcSpanExporter.builder()
.setEndpoint("http://localhost:4317")
.build()
)
// 配置取樣策略(生產環境建議使用比例取樣)
setSampler(Sampler.traceIdRatioBased(0.8))
// 添加自訂資源屬性
addResourceAttributes(mapOf(
AttributeKey.stringKey("deployment.environment") to "production",
AttributeKey.stringKey("service.version") to "1.0.0",
AttributeKey.stringKey("team") to "ai-platform"
))
}
}
agent.use { agent ->
println("啟動具備可觀測性的 AI Agent...")
// 執行多個請求以產生追蹤資料
val requests = listOf(
"我的帳號無法登入,該怎麼辦?",
"如何重設密碼?",
"系統回應很慢,可能是什麼原因?"
)
requests.forEach { request ->
val result = agent.run(request)
println("處理請求:$request")
println("回應:$result\n")
}
println("檢查 Jaeger UI:http://localhost:16686 查看追蹤資料")
}
}
}
追蹤巢狀事件的威力
Koog 的可觀測性不僅追蹤單一操作,還能完整記錄巢狀的操作階層:
CreateAgentSpan (建立代理)
InvokeAgentSpan (呼叫代理)
NodeExecuteSpan (執行節點)
InferenceSpan (推理過程)
- Token 使用量: 150 input tokens, 75 output tokens
- 成本: $0.0034
- 延遲: 1.2秒
NodeExecuteSpan (執行工具)
ExecuteToolSpan (執行工具)
- 工具名稱: search_knowledge_base
- 執行時間: 0.3秒
NodeExecuteSpan (最終推理)
InferenceSpan (推理過程)
- 回應產生時間: 0.8秒
Ktor 框架整合
為什麼 Ktor 整合至關重要
在企業環境中,AI Agent 通常需要透過 HTTP API 提供服務。Koog 0.0.4 的 Ktor 整合讓這個過程變得非常簡單,你可以:
- 快速將 AI Agent 包裝成 RESTful API
- 透過 YAML 設定檔管理多個 LLM 供應商
- 享受 Ktor 的高效能和豐富生態系
透過 YAML 配置的靈活性
# 檔案:src/main/resources/application.yaml
koog:
openai:
apikey: 'your-openai-api-key'
baseUrl: 'https://api.openai.com'
timeout:
requestTimeoutMillis: 30000
connectTimeoutMillis: 10000
socketTimeoutMillis: 30000
anthropic:
apikey: 'your-anthropic-api-key'
baseUrl: 'https://api.anthropic.com'
timeout:
requestTimeoutMillis: 30000
google:
apikey: 'your-google-api-key'
baseUrl: 'https://generativelanguage.googleapis.com'
openrouter:
apikey: 'your-openrouter-api-key'
baseUrl: 'https://openrouter.ai'
ollama:
baseUrl: 'http://localhost:11434'
timeout:
requestTimeoutMillis: 60000
完整的 RESTful API 實作
// 檔案:src/main/kotlin/deployment/KtorIntegration.kt
import ai.koog.agents.core.agent.AIAgent
import ai.koog.ktor.singleRunAgent
import ai.koog.prompt.executor.clients.openai.OpenAIModels
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.http.*
import kotlinx.serialization.Serializable
@Serializable
data class ChatRequest(
val message: String,
val sessionId: String? = null
)
@Serializable
data class ChatResponse(
val response: String,
val sessionId: String,
val timestamp: Long = System.currentTimeMillis()
)
fun Application.configureKoog() {
// 安裝 Koog 外掛
install(Koog) {
llm {
// 從 application.yaml 自動載入配置
openAI(apiKey = "your-openai-api-key")
anthropic(apiKey = "your-anthropic-api-key")
}
// 配置 Agent 行為
agent {
// 設定預設模型
model = OpenAIModels.GPT4.Turbo
// 設定最大迭代次數
maxAgentIterations = 10
// 註冊工具
registerTools {
tool(::searchTool)
tool(::calculatorTool)
}
// 配置系統提示
prompt {
system("你是一個專業的技術支援助手,具備豐富的問題解決經驗")
}
}
}
// 定義 API 路由
routing {
route("/api/v1") {
// 單次對話端點
post("/chat") {
try {
val request = call.receive<ChatRequest>()
val response = singleRunAgent(request.message)
call.respond(HttpStatusCode.OK, ChatResponse(
response = response,
sessionId = request.sessionId ?: generateSessionId()
))
} catch (e: Exception) {
call.respond(HttpStatusCode.InternalServerError, mapOf(
"error" to "處理請求時發生錯誤",
"details" to e.message
))
}
}
// 健康檢查端點
get("/health") {
call.respond(HttpStatusCode.OK, mapOf(
"status" to "healthy",
"timestamp" to System.currentTimeMillis()
))
}
// Agent 狀態端點
get("/agent/status") {
call.respond(HttpStatusCode.OK, mapOf(
"agent" to "active",
"models" to listOf("gpt-4", "claude-3"),
"tools" to listOf("search", "calculator")
))
}
}
}
}
// 輔助函數
private fun generateSessionId(): String =
"session-${System.currentTimeMillis()}-${(1000..9999).random()}"
private fun searchTool(query: String): String =
"搜尋結果:$query"
private fun calculatorTool(expression: String): String =
"計算結果:$expression"
結構化輸出功能
為什麼結構化輸出很重要
在企業應用中,我們經常需要從 AI 回應中提取結構化資料。傳統的文字處理方法不僅不可靠,還容易出錯。Koog 0.0.4 的結構化輸出功能徹底解決了這個問題
自動錯誤修正和重試機制
新版本最令人驚艷的是內建的錯誤修正功能。當 LLM 回傳的結構化資料格式不正確時,系統會自動使用另一個模型進行修正:
// 檔案:src/main/kotlin/structured/StructuredDataExample.kt
import ai.koog.prompt.structure.*
import ai.koog.prompt.executor.clients.openai.OpenAIModels
import ai.koog.prompt.executor.llms.all.simpleOpenAIExecutor
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.Serializable
@Serializable
data class CustomerInfo(
val name: String,
val email: String,
val issue: String,
val priority: String, // "low", "medium", "high", "urgent"
val category: String, // "technical", "billing", "account", "general"
val estimatedResolutionTime: Int // 預估解決時間(小時)
)
@Serializable
data class ProductFeedback(
val productName: String,
val rating: Int, // 1-5
val positiveAspects: List<String>,
val negativeAspects: List<String>,
val recommendationScore: Int, // 0-10
val improvementSuggestions: List<String>
)
suspend fun extractCustomerInfo(userInput: String): CustomerInfo {
val executor = simpleOpenAIExecutor(System.getenv("OPENAI_KEY"))
return executor.executeStructured(
prompt = prompt("customer-service-analysis") {
system("""
你是一個專業的客服分析師。
請分析客戶訊息,提取關鍵資訊並分類問題的優先級和類別。
優先級判斷標準:
- urgent:影響業務運作的嚴重問題
- high:重要功能無法使用
- medium:一般功能問題
- low:詢問或建議
""".trimIndent())
user("客戶訊息:$userInput")
},
model = OpenAIModels.CostOptimized.GPT4oMini,
config = StructuredOutputConfig(
default = StructuredOutput.Manual(CustomerInfo.serializer()),
// 當資料格式錯誤時,使用 GPT-4 進行修正
fixingParser = StructureFixingParser(
fixingModel = OpenAIModels.Chat.GPT4o,
retries = 3
)
)
)
}
suspend fun analyzeProductFeedback(feedback: String): ProductFeedback {
val executor = simpleOpenAIExecutor(System.getenv("OPENAI_KEY"))
return executor.executeStructured(
prompt = prompt("product-feedback-analysis") {
system("""
你是一個產品反饋分析專家。
請分析用戶反饋,提取產品評價的各個維度。
評分標準:
- rating: 1-5 (1=非常不滿意, 5=非常滿意)
- recommendationScore: 0-10 (0=絕不推薦, 10=強烈推薦)
""".trimIndent())
user("用戶反饋:$feedback")
},
model = OpenAIModels.Chat.GPT4o,
config = StructuredOutputConfig(
default = StructuredOutput.Manual(ProductFeedback.serializer()),
fixingParser = StructureFixingParser(
fixingModel = OpenAIModels.Chat.GPT4o,
retries = 2
)
)
)
}
fun main() {
runBlocking {
// 測試客戶資訊提取
val customerMessage = """
你好,我是張小明,email 是 [email protected]。
我的帳號無法登入,已經嘗試重設密碼但還是不行。
這個問題影響到我無法處理重要的工作,請盡快協助解決。
""".trimIndent()
val customerInfo = extractCustomerInfo(customerMessage)
println("客戶資訊:$customerInfo")
// 測試產品反饋分析
val productFeedback = """
我使用這個軟體已經三個月了,整體來說還不錯。
UI 介面很直觀,功能也很完整,特別是自動備份功能很實用。
但是載入速度有點慢,希望能改進。另外報表功能可以更豐富一些。
我會推薦給同事使用。
""".trimIndent()
val feedback = analyzeProductFeedback(productFeedback)
println("產品反饋分析:$feedback")
}
}
在會話中使用結構化輸出
// 在 LLM 會話中使用結構化輸出
llm.writeSession {
// 發送一般訊息
requestLLM("請分析這位客戶的問題")
// 請求結構化回應
val structuredResponse = requestLLMStructured(
config = StructuredOutputConfig(
default = StructuredOutput.Manual(CustomerInfo.serializer()),
fixingParser = StructureFixingParser(
fixingModel = OpenAIModels.Chat.GPT4o,
retries = 3
)
)
)
// 繼續處理結構化資料
println("提取的客戶資訊:$structuredResponse")
}
新平台和模型支援
iOS 平台支援
Koog 0.0.4 正式支援 iOS 平台,這意味著你可以:
- 在 iOS 應用中直接整合 AI Agent
- 開發離線優先的智能應用
- 利用 Kotlin Multiplatform 的優勢跨平台開發
新的 LLM 模型支援
新版本新增了多個業界領先的模型:
// 支援 GPT-5(當可用時)
OpenAIModels.Chat.GPT5
// 支援 DeepSeek 系列模型
DeepSeekModels.Chat.V2
DeepSeekModels.Code.V2
// 支援 Qwen 系列模型
QwenModels.Chat.QwenMax
QwenModels.Code.QwenCoder
// 如何選擇適合的模型
when (task) {
is CodeGeneration -> QwenModels.Code.QwenCoder
is MathProblem -> DeepSeekModels.Chat.V2
is GeneralChat -> OpenAIModels.Chat.GPT4o
is Translation -> OpenAIModels.Chat.GPT4oMini // 成本考量
}
生產級重試機制
為什麼重試機制至關重要
在生產環境中,網路問題、API 限制、暫時性錯誤都是常見的情況。一個穩健的重試機制能夠:
- 提高系統可用性
- 減少因暫時性問題導致的失敗
- 提供更好的使用者體驗
可配置重試策略
// 檔案:src/main/kotlin/retry/RetryConfiguration.kt
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.features.retry.RetryConfig
import ai.koog.prompt.executor.clients.openai.OpenAIModels
import kotlinx.coroutines.delay
import kotlin.time.Duration.Companion.seconds
suspend fun createResilientAgent(): AIAgent {
return AIAgent(
executor = simpleOpenAIExecutor(apiKey),
llmModel = OpenAIModels.Chat.GPT4o,
systemPrompt = "你是一個高可用性的 AI 助手"
) {
// 配置重試策略
install(RetryFeature) {
// 最大重試次數
maxRetries = 3
// 指數退避策略
backoffStrategy = ExponentialBackoff(
initialDelay = 1.seconds,
maxDelay = 10.seconds,
multiplier = 2.0
)
// 可重試的錯誤類型
retryableExceptions = setOf(
NetworkException::class,
RateLimitException::class,
TemporaryServiceException::class
)
// 自訂重試條件
retryCondition = { exception, attemptNumber ->
when {
exception is RateLimitException -> {
// 對於限制錯誤,等待更長時間
delay(30.seconds)
attemptNumber < 2
}
exception is NetworkException -> {
// 網路錯誤快速重試
attemptNumber < 3
}
else -> false
}
}
}
}
}
子圖重試與程式化回饋
在複雜的工作流程中,Koog 支援對特定子圖進行重試:
// 子圖級別的重試配置
val workflow = createWorkflow {
node("data-extraction") {
retry(maxAttempts = 2) {
extractDataFromDocument(input)
}
}
node("data-validation") {
retry(
maxAttempts = 3,
backoff = LinearBackoff(2.seconds)
) {
validateExtractedData(data)
}
}
node("data-processing") {
// 程式化回饋:根據前一步結果調整重試策略
val retryCount = if (previousStepFailed) 1 else 2
retry(maxAttempts = retryCount) {
processValidatedData(data)
}
}
}
升級指南
從舊版本升級的注意事項
如果你正在使用 Koog 0.0.3 或更早版本,請注意以下變更:
- 依賴更新:
// 舊版本
implementation("ai.koog.agents:core:0.0.3")
// 新版本
implementation("ai.koog.agents:core:0.0.4")
implementation("ai.koog.agents:agents-features-opentelemetry:0.0.4")
- API 變更:
requestStructured
已更名為requestLLMStructured
- OpenTelemetry 配置需要明確安裝 feature
- 相容性檢查:
// 檢查版本相容性
if (KoogVersion.current >= KoogVersion.v0_0_4) {
// 使用新的結構化輸出功能
val structured = llm.writeSession {
requestLLMStructured<DataClass>()
}
} else {
// 使用舊的方法
val response = llm.writeSession {
requestLLM()
}
}
最佳實踐建議
- 逐步升級:建議先在開發環境測試新功能
- 可觀測性優先:立即啟用 OpenTelemetry 追蹤
- 結構化輸出:重構現有的資料提取邏輯
- 重試策略:根據實際使用情況調整重試配置
總結
Koog 0.0.4 版本帶來的五大核心更新讓 AI Agent 開發邁入了新的階段:
- OpenTelemetry 可觀測性:讓 AI 系統的運作透明化,便於監控和最佳化
- Ktor 整合:簡化 API 服務的建置和部署流程
- 結構化輸出:提供可靠的資料提取和自動錯誤修正機制
- 新平台支援:iOS 支援和新 LLM 模型擴展了應用場景
- 生產級重試:增強系統的穩定性和可用性
這些更新不僅提升了開發效率,更重要的是為企業級 AI Agent 應用奠定了堅實的基礎。隨著 AI 技術的快速發展,Koog 框架展現出了跟上時代步伐的能力和決心
下一步,建議你開始實驗這些新功能,特別是可觀測性和結構化輸出,它們將大幅改善你的 AI Agent 開發體驗
支持創作
如果這篇文章對您有幫助,歡迎透過 贊助連結 支持我持續創作優質內容。您的支持是我前進的動力!
圖片來源:AI 產生