Skip to content

追蹤 (Tracing)

本頁面包含追蹤 (Tracing) 功能的詳細資訊,該功能為 AI agent 提供全面的追蹤能力。

功能概覽

追蹤功能是一個強大的監控與偵錯工具,可擷取有關 agent 執行的詳細資訊,包括:

  • 策略執行
  • LLM 呼叫
  • LLM 串流(開始、框架、完成、錯誤)
  • 工具呼叫
  • agent 圖中的節點執行

此功能透過攔截 agent 管線中的關鍵事件,並將其轉發給可配置的訊息處理器來運作。這些處理器可以將追蹤資訊輸出到各種目的地,例如記錄檔或檔案系統中的其他類型檔案,使開發人員能夠深入了解 agent 行為並有效地進行疑難排解。

事件流程

  1. 追蹤功能攔截 agent 管線中的事件。
  2. 根據配置的訊息篩選器對事件進行篩選。
  3. 篩選後的事件被傳遞給註冊的訊息處理器。
  4. 訊息處理器將事件格式化並輸出到其各自的目的地。

配置與初始化

基本設定

若要使用追蹤功能,您需要:

  1. 擁有一個或多個訊息處理器(您可以使用現有的處理器或建立自己的處理器)。
  2. 在您的 agent 中安裝 Tracing
  3. 配置訊息篩選器(選填)。
  4. 將訊息處理器新增到該功能中。

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.feature.model.events.LLMCallCompletedEvent
import ai.koog.agents.core.feature.model.events.ToolCallStartingEvent
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageLogWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.io.buffered
import kotlinx.io.files.Path
import kotlinx.io.files.SystemFileSystem
-->
```kotlin
// 定義將用作追蹤訊息目的地的記錄器/檔案 
val logger = KotlinLogging.logger { }
val outputPath = Path("/path/to/trace.log")

// 建立一個 agent
val agent = AIAgent(
    promptExecutor = simpleOllamaAIExecutor(),
    llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
    install(Tracing) {
        // 配置訊息處理器以處理追蹤事件
        addMessageProcessor(TraceFeatureMessageLogWriter(logger))
        addMessageProcessor(TraceFeatureMessageFileWriter.create(outputPath))
    }
}
```
<!--- KNIT example-tracing-01.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageLogWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import org.slf4j.LoggerFactory;
import java.nio.file.Path;
public class exampleTracingJava01 {
    public static void main(String[] args) {
-->
<!--- SUFFIX
    }
}
-->
```java
// 定義將用作追蹤訊息目的地的記錄器/檔案
var logger = LoggerFactory.getLogger("tracing");
var outputPath = Path.of("/path/to/trace.log");

// 建立一個 agent
var agent = AIAgent.builder()
    .promptExecutor(PromptExecutor.builder().ollama().build())
    .llmModel(OllamaModels.Meta.LLAMA_3_2)

    .install(Tracing.Feature, config -> {
        // 配置訊息處理器以處理追蹤事件
        config.addMessageProcessor(TraceFeatureMessageLogWriter.create(logger));
        config.addMessageProcessor(TraceFeatureMessageFileWriter.create(outputPath));
    })
    .build();
```
<!--- KNIT exampleTracingJava01.java -->

訊息篩選

您可以處理所有現有事件,或根據特定基準選擇其中一些事件。 訊息篩選器可讓您控制處理哪些事件。這對於專注於 agent 執行的特定面向非常有用:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.feature.model.events.*
import ai.koog.agents.example.exampleTracing01.outputPath
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import kotlinx.io.buffered
import kotlinx.io.files.Path
import kotlinx.io.files.SystemFileSystem
val agent = AIAgent(
    promptExecutor = simpleOllamaAIExecutor(),
    llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
    install(Tracing) {
-->
<!--- SUFFIX
   }
}
-->
```kotlin

val fileWriter = TraceFeatureMessageFileWriter(
    outputPath,
    { path: Path -> SystemFileSystem.sink(path).buffered() }
)

addMessageProcessor(fileWriter)

// 僅篩選與 LLM 相關的事件
fileWriter.setMessageFilter { message ->
    message is LLMCallStartingEvent || message is LLMCallCompletedEvent
}

// 僅篩選與工具相關的事件
fileWriter.setMessageFilter { message -> 
    message is ToolCallStartingEvent ||
        message is ToolCallCompletedEvent ||
        message is ToolValidationFailedEvent ||
        message is ToolCallFailedEvent
}

// 僅篩選節點執行事件
fileWriter.setMessageFilter { message -> 
    message is NodeExecutionStartingEvent || message is NodeExecutionCompletedEvent
}
```
<!--- KNIT example-tracing-02.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.core.feature.model.events.*;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class exampleTracingJava02 {
    public static void main(String[] args) {
        var outputPath = Path.of("/path/to/trace.log");
        var agent = AIAgent.builder()
            .promptExecutor(PromptExecutor.builder().ollama().build())
            .llmModel(OllamaModels.Meta.LLAMA_3_2)
            .install(Tracing.Feature, config -> {
-->
<!--- SUFFIX
            })
            .build();
    }
}
-->
```java
var fileWriter = TraceFeatureMessageFileWriter.create(
    outputPath,
    path -> { try { return Files.newOutputStream(path); } catch (IOException e) { throw new UncheckedIOException(e); }}
);

config.addMessageProcessor(fileWriter);

// 僅篩選與 LLM 相關的事件
fileWriter.setMessageFilter(message ->
    message instanceof LLMCallStartingEvent || message instanceof LLMCallCompletedEvent
);

// 僅篩選與工具相關的事件
fileWriter.setMessageFilter(message ->
    message instanceof ToolCallStartingEvent ||
        message instanceof ToolCallCompletedEvent ||
        message instanceof ToolValidationFailedEvent ||
        message instanceof ToolCallFailedEvent
);

// 僅篩選節點執行事件
fileWriter.setMessageFilter(message ->
    message instanceof NodeExecutionStartingEvent || message instanceof NodeExecutionCompletedEvent
);
```
<!--- KNIT exampleTracingJava02.java -->

大量追蹤數據

對於具有複雜策略或長時間運行的 agent,追蹤事件的量可能會非常大。考慮使用以下方法來管理事件量:

  • 使用特定的訊息篩選器來減少事件數量。
  • 實作具有緩衝或取樣功能的自訂訊息處理器。
  • 對記錄檔使用檔案輪轉,以防止其變得過大。

相依圖

追蹤功能具有以下相依性:

Tracing
├── AIAgentPipeline (用於攔截事件)
├── TraceFeatureConfig
│   └── FeatureConfig
├── Message Processors (訊息處理器)
│   ├── TraceFeatureMessageLogWriter
│   │   └── FeatureMessageLogWriter
│   ├── TraceFeatureMessageFileWriter
│   │   └── FeatureMessageFileWriter
│   └── TraceFeatureMessageRemoteWriter
│       └── FeatureMessageRemoteWriter
└── Event Types (來自 ai.koog.agents.core.feature.model)
    ├── AgentStartingEvent
    ├── AgentCompletedEvent
    ├── AgentExecutionFailedEvent
    ├── AgentClosingEvent
    ├── GraphStrategyStartingEvent
    ├── FunctionalStrategyStartingEvent
    ├── StrategyCompletedEvent
    ├── NodeExecutionStartingEvent
    ├── NodeExecutionCompletedEvent
    ├── NodeExecutionFailedEvent
    ├── SubgraphExecutionStartingEvent
    ├── SubgraphExecutionCompletedEvent
    ├── SubgraphExecutionFailedEvent
    ├── LLMCallStartingEvent
    ├── LLMCallCompletedEvent
    ├── LLMStreamingStartingEvent
    ├── LLMStreamingFrameReceivedEvent
    ├── LLMStreamingFailedEvent
    ├── LLMStreamingCompletedEvent
    ├── ToolCallStartingEvent
    ├── ToolValidationFailedEvent
    ├── ToolCallFailedEvent
    └── ToolCallCompletedEvent

範例與快速入門

基本追蹤到記錄器

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageLogWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
-->
<!--- SUFFIX
}
-->
```kotlin
// 建立一個記錄器
val logger = KotlinLogging.logger { }

// 建立一個帶有追蹤功能的 agent
val agent = AIAgent(
    promptExecutor = simpleOllamaAIExecutor(),
    llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
    install(Tracing) {
        addMessageProcessor(TraceFeatureMessageLogWriter(logger))
    }
}

// 執行 agent
agent.run("Hello, agent!")
```
<!--- KNIT example-tracing-03.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageLogWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import org.slf4j.LoggerFactory;
public class exampleTracingJava03 {
    public static void main(String[] args) {
-->
<!--- SUFFIX
    }
}
-->
```java
// 建立一個記錄器
var logger = LoggerFactory.getLogger("tracing");

// 建立一個帶有追蹤功能的 agent
var agent = AIAgent.builder()
    .promptExecutor(PromptExecutor.builder().ollama().build())
    .llmModel(OllamaModels.Meta.LLAMA_3_2)

    .install(Tracing.Feature, config -> {
        config.addMessageProcessor(TraceFeatureMessageLogWriter.create(logger));
    })
    .build();

// 執行 agent
agent.run("Hello, agent!");
```
<!--- KNIT exampleTracingJava03.java -->

錯誤處理與邊緣情況

無訊息處理器

如果沒有訊息處理器被新增到追蹤功能,系統將記錄一條警告:

Tracing Feature. No feature out stream providers are defined. Trace streaming has no target.

該功能仍會攔截事件,但不會對其進行處理或輸出到任何地方。

資源管理

訊息處理器可能會持有需要正確釋放的資源(例如檔案句柄)。使用 use 擴充函式來確保正確的清理作業:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.example.exampleTracing01.outputPath
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import kotlinx.coroutines.runBlocking
import kotlinx.io.buffered
import kotlinx.io.files.Path
import kotlinx.io.files.SystemFileSystem
const val input = "What's the weather like in New York?"
fun main() {
   runBlocking {
-->
<!--- SUFFIX
    }
}
-->
```kotlin
val writer = TraceFeatureMessageFileWriter(
    outputPath,
    { path: Path -> SystemFileSystem.sink(path).buffered() }
)

// 建立一個 agent
val agent = AIAgent(
    promptExecutor = simpleOllamaAIExecutor(),
    llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
    install(Tracing) {
        addMessageProcessor(writer)
    }
}

// 執行 agent
agent.run(input)

// 當區塊結束時,Writer 將自動關閉
```
<!--- KNIT example-tracing-04.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class exampleTracingJava04 {
    public static void main(String[] args) {
        var outputPath = Path.of("/path/to/trace.log");
        String input = "What's the weather like in New York?";
-->
<!--- SUFFIX
    }
}
-->
```java
var writer = TraceFeatureMessageFileWriter.create(
    outputPath,
    path -> { try { return Files.newOutputStream(path); } catch (IOException e) { throw new UncheckedIOException(e); }}
);

// 建立一個 agent
var agent = AIAgent.builder()
    .promptExecutor(PromptExecutor.builder().ollama().build())
    .llmModel(OllamaModels.Meta.LLAMA_3_2)

    .install(Tracing.Feature, config -> {
        config.addMessageProcessor(writer);
    })
    .build();

// 執行 agent
agent.run(input);

// 當區塊結束時,Writer 將自動關閉
```
<!--- KNIT exampleTracingJava04.java -->

追蹤特定事件到檔案

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.feature.model.events.LLMCallCompletedEvent
import ai.koog.agents.core.feature.model.events.LLMCallStartingEvent
import ai.koog.agents.example.exampleTracing01.outputPath
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import kotlinx.coroutines.runBlocking
import kotlinx.io.buffered
import kotlinx.io.files.Path
import kotlinx.io.files.SystemFileSystem
const val input = "What's the weather like in New York?"
fun main() {
    runBlocking {
-->
<!--- SUFFIX
    }
}
-->
```kotlin
val fileWriter = TraceFeatureMessageFileWriter(
    outputPath,
    { path: Path -> SystemFileSystem.sink(path).buffered() }
)

// 建立一個 agent
val agent = AIAgent(
    promptExecutor = simpleOllamaAIExecutor(),
    llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
    install(Tracing) {
        addMessageProcessor(fileWriter)

        // 僅追蹤 LLM 呼叫
        fileWriter.setMessageFilter { message ->
            message is LLMCallStartingEvent || message is LLMCallCompletedEvent
        }
    }
}
```
<!--- KNIT example-tracing-05.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.core.feature.model.events.LLMCallCompletedEvent;
import ai.koog.agents.core.feature.model.events.LLMCallStartingEvent;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageFileWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class exampleTracingJava05 {
    public static void main(String[] args) {
        var outputPath = Path.of("/path/to/trace.log");
        String input = "What's the weather like in New York?";
-->
<!--- SUFFIX
    }
}
-->
```java
var fileWriter = TraceFeatureMessageFileWriter.create(
    outputPath,
    path -> { try { return Files.newOutputStream(path); } catch (IOException e) { throw new UncheckedIOException(e); }}
);

// 建立一個 agent
var agent = AIAgent.builder()
    .promptExecutor(PromptExecutor.builder().ollama().build())
    .llmModel(OllamaModels.Meta.LLAMA_3_2)

    .install(Tracing.Feature, config -> {
        config.addMessageProcessor(fileWriter);

        // 僅追蹤 LLM 呼叫
        fileWriter.setMessageFilter(message ->
            message instanceof LLMCallStartingEvent || message instanceof LLMCallCompletedEvent
        );
    })
    .build();
```
<!--- KNIT exampleTracingJava05.java -->

追蹤特定事件到遠端端點

當您需要透過網路傳送事件資料時,可以使用追蹤到遠端端點。一旦啟動,追蹤到遠端端點會在指定的連接埠號啟動一個輕量級伺服器,並透過 Kotlin Server-Sent Events (SSE) 傳送事件。

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.feature.remote.server.config.DefaultServerConnectionConfig
import ai.koog.agents.features.tracing.feature.Tracing
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageRemoteWriter
import ai.koog.prompt.executor.llms.all.simpleOllamaAIExecutor
import ai.koog.prompt.executor.ollama.client.OllamaModels
import kotlinx.coroutines.runBlocking
const val input = "What's the weather like in New York?"
const val port = 4991
const val host = "localhost"
fun main() {
   runBlocking {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
val connectionConfig = DefaultServerConnectionConfig(host = host, port = port)
val writer = TraceFeatureMessageRemoteWriter(connectionConfig)

// 建立一個 agent
val agent = AIAgent(
    promptExecutor = simpleOllamaAIExecutor(),
    llmModel = OllamaModels.Meta.LLAMA_3_2,
) {
    install(Tracing) {
        addMessageProcessor(writer)
    }
}

// 執行 agent
agent.run(input)

// 當區塊結束時,Writer 將自動關閉
```
<!--- KNIT example-tracing-06.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent;
import ai.koog.agents.core.feature.remote.server.config.DefaultServerConnectionConfig;
import ai.koog.agents.features.tracing.feature.Tracing;
import ai.koog.agents.features.tracing.writer.TraceFeatureMessageRemoteWriter;
import ai.koog.prompt.executor.model.PromptExecutor;
import ai.koog.prompt.executor.ollama.client.OllamaModels;
import java.io.IOException;
import java.io.UncheckedIOException;
public class exampleTracingJava06 {
    public static void main(String[] args) {
        String input = "What's the weather like in New York?";
        int port = 4991;
        String host = "localhost";
-->
<!--- SUFFIX
    }
}
-->
```java
var connectionConfig = new DefaultServerConnectionConfig(host, port);
var writer = new TraceFeatureMessageRemoteWriter(connectionConfig);

// 建立一個 agent
var agent = AIAgent.builder()
    .promptExecutor(PromptExecutor.builder().ollama().build())
    .llmModel(OllamaModels.Meta.LLAMA_3_2)

    .install(Tracing.Feature, config -> {
        config.addMessageProcessor(writer);
    })
    .build();

// 執行 agent
agent.run(input);

// 當區塊結束時,Writer 將自動關閉
```
<!--- KNIT exampleTracingJava06.java -->

在用戶端,您可以使用 FeatureMessageRemoteClient 來接收事件並將其反序列化。

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.feature.model.events.AgentCompletedEvent
import ai.koog.agents.core.feature.model.events.DefinedFeatureEvent
import ai.koog.agents.core.feature.remote.client.config.DefaultClientConnectionConfig
import ai.koog.agents.core.feature.remote.client.FeatureMessageRemoteClient
import ai.koog.utils.io.use
import io.ktor.http.*
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.consumeAsFlow
const val input = "What's the weather like in New York?"
const val port = 4991
const val host = "localhost"
fun main() {
   runBlocking {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
val clientConfig = DefaultClientConnectionConfig(host = host, port = port, protocol = URLProtocol.HTTP)
val agentEvents = mutableListOf<DefinedFeatureEvent>()

val clientJob = launch {
    FeatureMessageRemoteClient(connectionConfig = clientConfig, scope = this).use { client ->
        val collectEventsJob = launch {
            client.receivedMessages.consumeAsFlow().collect { event ->
                // 從伺服器收集事件
                agentEvents.add(event as DefinedFeatureEvent)

                // 在 agent 完成時停止收集事件
                if (event is AgentCompletedEvent) {
                    cancel()
                }
            }
        }
        client.connect()
        collectEventsJob.join()
        client.healthCheck()
    }
}

listOf(clientJob).joinAll()
```
<!--- KNIT example-tracing-07.kt -->

API 文件

追蹤功能遵循模組化架構,包含以下關鍵元件:

  1. Tracing:攔截 agent 管線中事件的主要功能類別。
  2. TraceFeatureConfig:用於自訂功能行為的配置類別。
  3. 訊息處理器:處理並輸出追蹤事件的元件: