Skip to content

LLMセッションと手動履歴管理

このページでは、読み取りおよび書き込みセッションの使用方法、会話履歴の管理、および言語モデルへのリクエスト送信方法など、LLMセッションに関する詳細な情報を提供します。

はじめに

LLMセッションは、言語モデル(LLM)とやり取りするための構造化された手法を提供する基本的な概念です。これらは会話履歴の管理、LLMへのリクエストの処理、およびツールの実行やレスポンス処理のための統一されたインターフェースを提供します。

LLMセッションの理解

LLMセッションは、言語モデルとやり取りするためのコンテキスト(文脈)を表します。これには以下のものがカプセル化されています:

  • 会話履歴(プロンプト)
  • 利用可能なツール
  • LLMへのリクエスト送信メソッド
  • 会話履歴の更新メソッド
  • ツールの実行メソッド

セッションは AIAgentLLMContext クラスによって管理され、このクラスが読み取りおよび書き込みセッションを作成するためのメソッドを提供します。

セッションの種類

Koogフレームワークは、2種類のセッションを提供します:

  1. 書き込みセッション (AIAgentLLMWriteSession): プロンプトやツールの変更、LLMリクエストの送信、およびツールの実行が可能です。書き込みセッションで行われた変更は、LLMコンテキストに反映(永続化)されます。

  2. 読み取りセッション (AIAgentLLMReadSession): プロンプトやツールへの読み取り専用アクセスを提供します。状態を変更せずに現在の内容を確認するのに適しています。

主な違いは、書き込みセッションは会話履歴を変更できるのに対し、読み取りセッションは変更できない点です。

セッションのライフサイクル

セッションには定義されたライフサイクルがあります:

  1. 作成: llm.writeSession { ... } または llm.readSession { ... } などを使用してセッションが作成されます。
  2. アクティブフェーズ: ラムダブロックが実行されている間、セッションはアクティブです。
  3. 終了: ラムダブロックが完了すると、セッションは自動的に閉じられます。

セッションは AutoCloseable インターフェースを実装しており、例外が発生した場合でも適切にクリーンアップされることが保証されます。

LLMセッションの操作

セッションの作成

セッションは、AIAgentLLMContext クラスのメソッドを使用して作成されます: === "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
// 書き込みセッションの作成
llm.writeSession {
    // セッションのコードをここに記述
}

// 読み取りセッションの作成
llm.readSession {
    // セッションのコードをここに記述
}
```
<!--- KNIT example-sessions-01.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
class exampleSessionsJava01 {
    public static void main(String[] args) {
        var node = AIAgentNode.builder("node_name")
            .withInput(String.class)
            .withOutput(Void.class)
            .withAction((input, ctx) -> {
-->
<!--- SUFFIX
                return null;
            })
            .build();
    }
}
-->
```java
// 書き込みセッションの作成
ctx.getLlm().writeSession(session -> {
    // セッションのコードをここに記述
    return null;
});

// 読み取りセッションの作成
ctx.getLlm().readSession(session -> {
    // セッションのコードをここに記述
    return null;
});
```
<!--- KNIT exampleSessionsJava01.java -->

これらの関数は、セッションのコンテキスト内で実行されるラムダブロックを受け取ります。ブロックが完了すると、セッションは自動的に閉じられます。

セッションのスコープとスレッド安全性

セッションはスレッド安全性を確保するために読み書きロック(read-write lock)を使用します:

  • 複数の読み取りセッションを同時にアクティブにできます。
  • 書き込みセッションは一度に1つだけアクティブにできます。
  • 書き込みセッションは、他のすべてのセッション(読み取り・書き込みの両方)をブロックします。

これにより、並行した変更によって会話履歴が破損しないことが保証されます。

セッションプロパティへのアクセス

セッション内では、プロンプトやツールにアクセスできます:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.readSession {
    val messageCount = prompt.messages.size
    val availableTools = tools.map { it.name }
}
```
<!--- KNIT example-sessions-02.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
class exampleSessionsJava02 {
    public static void main(String[] args) {
        var node = AIAgentNode.builder("node_name")
            .withInput(String.class)
            .withOutput(Void.class)
            .withAction((input, ctx) -> {
-->
<!--- SUFFIX
                return null;
            })
            .build();
    }
}
-->
```java
ctx.getLlm().readSession(session -> {
    int messageCount = session.getPrompt().getMessages().size();
    var availableTools = session.getTools().stream().map(tool -> tool.getName()).toList();
    return null;
});
```
<!--- KNIT exampleSessionsJava02.java -->

書き込みセッションでは、これらのプロパティを変更することもできます:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node
import ai.koog.agents.core.tools.ToolDescriptor

val newTools = listOf<ToolDescriptor>()

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.writeSession {
    // プロンプトの変更
    appendPrompt {
        user("New user message")
    }

    // ツールの変更
    tools = newTools
}
```
<!--- KNIT example-sessions-03.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
import ai.koog.agents.core.tools.ToolDescriptor;
import java.util.Collections;
class exampleSessionsJava03 {
    public static void main(String[] args) {
        var newTools = Collections.<ToolDescriptor>emptyList();

        var node = AIAgentNode.builder("node_name")
            .withInput(String.class)
            .withOutput(Void.class)
            .withAction((input, ctx) -> {
-->
<!--- SUFFIX
                return null;
            })
            .build();
    }
}
-->
```java
ctx.getLlm().writeSession(session -> {
    // プロンプトの変更
    session.appendPrompt(promptBuilder -> {
        promptBuilder.user("New user message");
        return null;
    });

    // ツールの変更
    session.setTools(newTools);
    return null;
});
```
<!--- KNIT exampleSessionsJava03.java -->

詳細については、AIAgentLLMReadSession および AIAgentLLMWriteSession の詳細なAPIリファレンスを参照してください。

LLMリクエストの送信

基本的なリクエストメソッド

LLMリクエストを送信するための最も一般的なメソッドは以下の通りです:

  1. requestLLM(): 現在のプロンプトとツールを使用してLLMにリクエストを送信し、レスポンスを返します。

  2. requestLLMWithoutTools(): 現在のプロンプトを使用し、ツールは使用せずにLLMにリクエストを送信し、単一のレスポンスを返します。

  3. requestLLMForceOneTool(): 現在のプロンプトとツールを使用してLLMにリクエストを送信し、1つのツールの使用を強制します。

  4. requestLLMOnlyCallingTools(): ツールのみを使用して処理されるべきリクエストをLLMに送信します。

例:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.writeSession {
    // ツールを有効にしてリクエストを送信
    val response = requestLLM()

    // ツールなしでリクエストを送信
    val responseWithoutTools = requestLLMWithoutTools()
}
```
<!--- KNIT example-sessions-04.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
import ai.koog.prompt.message.Message;
class exampleSessionsJava04 {
    public static void main(String[] args) {
        var node = AIAgentNode.builder("node_name")
            .withInput(String.class)
            .withOutput(Void.class)
            .withAction((input, ctx) -> {
-->
<!--- SUFFIX
                return null;
            })
            .build();
    }
}
-->
```java
ctx.getLlm().writeSession(session -> {
    // ツールを有効にしてリクエストを送信
    var response = session.requestLLM();

    // ツールなしでリクエストを送信
    var responseWithoutTools = session.requestLLMWithoutTools();

    return null;
});
```
<!--- KNIT exampleSessionsJava04.java -->

リクエストの仕組み

LLMリクエストは、いずれかのリクエストメソッドを明示的に呼び出したときに送信されます。理解しておくべき重要なポイントは以下の通りです:

  1. 明示的な呼び出し: リクエストは、requestLLM()requestLLMWithoutTools() などのメソッドを呼び出したときにのみ発生します。
  2. 即時実行: リクエストメソッドを呼び出すと、リクエストは即座に実行され、レスポンスを受信するまでメソッドはブロックされます。
  3. 履歴の自動更新: 書き込みセッションでは、レスポンスが自動的に会話履歴に追加されます。

ツールを使用したリクエストメソッド

ツールを有効にしてリクエストを送信すると、LLMはテキストレスポンスの代わりにツール呼び出し(tool call)を返すことがあります。リクエストメソッドはこれを透過的に処理します:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node
import ai.koog.prompt.message.MessagePart

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.writeSession {
    val response = requestLLM()

    // レスポンスにはツール呼び出しやテキストが含まれる可能性があります
    val toolCalls = response.parts.filterIsInstance<MessagePart.Tool.Call>()
    if (toolCalls.isNotEmpty()) {
        // ツール呼び出しの処理
    } else {
        // テキストレスポンスの処理
    }
}
```
<!--- KNIT example-sessions-05.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
import ai.koog.prompt.message.Message;
import ai.koog.prompt.message.MessagePart;
class exampleSessionsJava05 {
    public static void main(String[] args) {
        var node = AIAgentNode.builder("node_name")
            .withInput(String.class)
            .withOutput(Void.class)
            .withAction((input, ctx) -> {
-->
<!--- SUFFIX
                return null;
            })
            .build();
    }
}
-->
```java
ctx.getLlm().writeSession(session -> {
    var response = session.requestLLM();

    // レスポンスパーツにはツール呼び出しまたはテキストコンテンツが含まれる可能性があります
    boolean hasToolCall = response.getParts().stream()
        .anyMatch(p -> p instanceof MessagePart.Tool.Call);
    if (hasToolCall) {
        // ツール呼び出しの処理
    } else {
        // テキストレスポンスの処理
    }
    return null;
});
```
<!--- KNIT exampleSessionsJava05.java -->

実際には、エージェントグラフがこのルーティングを自動的に処理するため、通常はレスポンスの型を手動でチェックする必要はありません。

構造化リクエストとストリーミングリクエスト

より高度なユースケースのために、構造化リクエストとストリーミングリクエストのためのメソッドが提供されています:

  1. requestLLMStructured(): LLMに対して、特定の構造化されたフォーマットでレスポンスを返すようリクエストします。

  2. requestLLMStructuredOneShot(): requestLLMStructured() と同様ですが、再試行や修正は行われません。

  3. requestLLMStreaming(): LLMに対してストリーミングリクエストを送信し、レスポンスチャンクの flow を返します。ストリーミングの詳細については、ストリーミングAPI のページを参照してください。

例:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node
import ai.koog.agents.example.exampleParallelNodeExecution07.JokeRating

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.writeSession {
    // 構造化リクエストを送信
    val structuredResponse = requestLLMStructured<JokeRating>()

    // ストリーミングリクエストを送信
    val responseStream = requestLLMStreaming()
    responseStream.collect { chunk ->
        // 各チャンクが到着するたびに処理
    }
}
```
<!--- KNIT example-sessions-06.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
class exampleSessionsJava06 {
    public static void main(String[] args) {
        var node = AIAgentNode.builder("node_name")
            .withInput(String.class)
            .withOutput(Void.class)
            .withAction((input, ctx) -> {
-->
<!--- SUFFIX
                return null;
            })
            .build();
    }
}
-->
```java
ctx.getLlm().writeSession(session -> {
    // ツールなしのリクエストを送信
    var responseWithoutTools = session.requestLLMWithoutTools();

    // ストリーミングリクエストを送信
    var responseStream = session.requestLLMStreaming();
    // Flow.Publisher<StreamFrame> からチャンクを処理
    return null;
});
```
<!--- KNIT exampleSessionsJava06.java -->

会話履歴の管理

プロンプトの更新

書き込みセッションでは、appendPrompt メソッドを使用してプロンプト(会話履歴)にメッセージを追加できます:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node
import ai.koog.prompt.message.MessagePart

val myToolResult = MessagePart.Tool.Result(
    id = "",
    tool = "",
    output = "",
)

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.writeSession {
    appendPrompt {
        // システムメッセージの追加
        system("You are a helpful assistant.")

        // ユーザーメッセージの追加
        user("Hello, can you help me with a coding question?")

        // アシスタントメッセージの追加
        assistant("Of course! What's your question?")

        // ツール結果の追加
        toolResult(myToolResult)
    }
}
```
<!--- KNIT example-sessions-07.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
class exampleSessionsJava07 {
    public static void main(String[] args) {
        var node = AIAgentNode.builder("node_name")
            .withInput(String.class)
            .withOutput(Void.class)
            .withAction((input, ctx) -> {
-->
<!--- SUFFIX
                return null;
            })
            .build();
    }
}
-->
```java
ctx.getLlm().writeSession(session -> {
    session.appendPrompt(promptBuilder -> {
        // システムメッセージの追加
        promptBuilder.system("You are a helpful assistant.");

        // ユーザーメッセージの追加
        promptBuilder.user("Hello, can you help me with a coding question?");

        // アシスタントメッセージの追加
        promptBuilder.assistant("Of course! What's your question?");

        // ツール実行後のフォローアップコンテキストの追加
        promptBuilder.assistant("Tool execution completed successfully.");
        return null;
    });
    return null;
});
```
<!--- KNIT exampleSessionsJava07.java -->

また、prompt プロパティに新しい Prompt オブジェクトを代入することで、プロンプトを完全に書き換えることも可能です:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node
import ai.koog.prompt.message.Message

val filteredMessages = emptyList<Message>()

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.writeSession {
    // 古いプロンプトを基に新しいプロンプトを作成
    prompt = prompt.copy(messages = filteredMessages)
}
```
<!--- KNIT example-sessions-08.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
import ai.koog.prompt.Prompt;
class exampleSessionsJava08 {
    public static void main(String[] args) {
        var node = AIAgentNode.builder("node_name")
            .withInput(String.class)
            .withOutput(Void.class)
            .withAction((input, ctx) -> {
-->
<!--- SUFFIX
                return null;
            })
            .build();
    }
}
-->
```java
ctx.getLlm().writeSession(session -> {
    var oldPrompt = session.getPrompt();
    // プロンプトの再構築と置換(Javaにおける手動書き換えアプローチ)
    session.setPrompt(
        Prompt.builder(oldPrompt.getId())
            .user("Retained summary of previous conversation")
            .build()
    );
    return null;
});
```
<!--- KNIT exampleSessionsJava08.java -->

レスポンス時の履歴の自動更新

書き込みセッションでLLMリクエストを送信すると、レスポンスは自動的に会話履歴に追加されます:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.writeSession {
    // ユーザーメッセージを追加
    appendPrompt {
        user("What's the capital of France?")
    }

    // リクエストを送信 - レスポンスは自動的に履歴に追加される
    val response = requestLLM()

    // この時点でプロンプトには、ユーザーメッセージとモデルのレスポンスの両方が含まれている
}
```
<!--- KNIT example-sessions-09.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
class exampleSessionsJava09 {
    public static void main(String[] args) {
        var node = AIAgentNode.builder("node_name")
            .withInput(String.class)
            .withOutput(Void.class)
            .withAction((input, ctx) -> {
-->
<!--- SUFFIX
                return null;
            })
            .build();
    }
}
-->
```java
ctx.getLlm().writeSession(session -> {
    // ユーザーメッセージを追加
    session.appendPrompt(promptBuilder -> {
        promptBuilder.user("What's the capital of France?");
        return null;
    });

    // リクエストを送信 - レスポンスは自動的に履歴に追加される
    var response = session.requestLLM();

    // この時点でプロンプトには、ユーザーメッセージとモデル의レスポンスの両方が含まれている
    return null;
});
```
<!--- KNIT exampleSessionsJava09.java -->

この自動的な履歴更新は書き込みセッションの主要な機能であり、会話が自然に流れるようにします。

履歴の圧縮

会話が長くなると、履歴が膨大になり、多くのトークンを消費する可能性があります。プラットフォームは履歴を圧縮するためのメソッドを提供しています:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node
import ai.koog.agents.core.dsl.extension.HistoryCompressionStrategy

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.writeSession {
    // TLDR(要約)アプローチを使用して履歴を圧縮する
    replaceHistoryWithTLDR(HistoryCompressionStrategy.WholeHistory, preserveMemory = true)
}
```
<!--- KNIT example-sessions-10.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
class exampleSessionsJava10 {
    public static void main(String[] args) {
-->
<!--- SUFFIX
    }
}
-->
```java
// 履歴圧縮には専用のJavaノードを使用します。
var compressHistory = AIAgentNode.llmCompressHistory("compressHistory");
```
<!--- KNIT exampleSessionsJava10.java -->

また、ストラテジーグラフ内で nodeLLMCompressHistory ノードを使用して、特定のポイントで履歴を圧縮することもできます。

履歴の圧縮と圧縮戦略に関する詳細は、履歴の圧縮を参照してください。

セッションでのツールの実行

ツールの呼び出し

書き込みセッションは、ツールを呼び出すためのいくつかのメソッドを提供します:

  1. callTool(tool, args): 参照によってツールを呼び出します。

  2. callTool(toolName, args): 名前によってツールを呼び出します。

  3. callTool(toolClass, args): クラスによってツールを呼び出します。

  4. callToolRaw(toolName, args): 名前によってツールを呼び出し、生の文字列の結果を返します。

例:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.agent.session.callTool
import ai.koog.agents.core.agent.session.callToolRaw
import ai.koog.agents.core.dsl.builder.node
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.ext.tool.AskUser

val myTool = AskUser
val myArgs = AskUser.Args("this is a string")

typealias MyTool = AskUser

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.writeSession {
    // 参照によるツールの呼び出し
    val result = callTool(myTool, myArgs)

    // 名前によるツールの呼び出し
    val result2 = callTool("myToolName", myArgs)

    // クラスによるツールの呼び出し
    val result3 = callTool(MyTool::class, myArgs)

    // ツールを呼び出し、生の結果を取得
    val rawResult = callToolRaw("myToolName", myArgs)
}
```
<!--- KNIT example-sessions-11.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
class exampleSessionsJava11 {
    public static void main(String[] args) {
-->
<!--- SUFFIX
    }
}
-->
```java
// Javaでは、グラフストラテジー内の専用のツール実行ノードを使用します。
var executeTool = AIAgentNode.executeTools("executeTool");
var sendToolResult = AIAgentNode.llmSendToolResults("sendToolResult");
```
<!--- KNIT exampleSessionsJava11.java -->

ツールの並列実行

複数のツールを並列に実行するために、書き込みセッションは Flow の拡張関数を提供します:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node
import ai.koog.agents.ext.tool.AskUser
import kotlinx.coroutines.flow.flow

typealias MyTool = AskUser

val data = ""
fun parseDataToArgs(data: String) = flow { emit(AskUser.Args(data)) }

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.writeSession {
    // ツールを並列に実行
    parseDataToArgs(data).toParallelToolCalls(MyTool::class).collect { result ->
        // 各結果を処理
    }

    // ツールを並列に実行し、生の結果を取得
    parseDataToArgs(data).toParallelToolCallsRaw(MyTool::class).collect { rawResult ->
        // 各生の結果を処理
    }
}
```
<!--- KNIT example-sessions-12.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
class exampleSessionsJava12 {
    public static void main(String[] args) {
-->
<!--- SUFFIX
    }
}
-->
```java
// 並列での複数ツール実行に相当するJavaの実装:executeToolsノードを使用します。
var executeMultipleTools = AIAgentNode.executeTools("executeMultipleTools");
```
<!--- KNIT exampleSessionsJava12.java -->

これは、大量のデータを効率的に処理する場合に便利です。

ベストプラクティス

LLMセッションを操作する際は、以下のベストプラクティスに従ってください:

  1. 適切なセッションタイプを使用する: 会話履歴を変更する必要がある場合は書き込みセッションを使用し、読み取るだけでよい場合は読み取りセッションを使用してください。

  2. セッションを短く保つ: セッションは特定のタスクに集中させ、リソースを解放するためにできるだけ早く閉じるようにしてください。

  3. 例外を処理する: リソースリークを防ぐため、セッション内で例外を適切に処理してください。

  4. 履歴のサイズを管理する: 長時間の会話では、トークンの使用量を減らすために履歴の圧縮を使用してください。

  5. 抽象度の高いAPIを優先する: 可能な場合は、ノードベースのAPI(例:直接セッションを操作する代わりに nodeLLMRequest を使用するなど)を利用してください。

  6. スレッド安全性に留意する: 書き込みセッションは他のセッションをブロックすることを念頭に置き、書き込み操作は可能な限り短くしてください。

  7. 複雑なデータには構造化リクエストを使用する: LLMに構造化されたデータを返させる必要がある場合は、自由形式のテキストをパースするのではなく、requestLLMStructured を使用してください。

  8. 長いレスポンスにはストリーミングを使用する: 長いレスポンスの場合は、requestLLMStreaming を使用してレスポンスが届くたびに逐次処理するようにしてください。

トラブルシューティング

セッションが既に閉じられている (Session already closed)

Cannot use session after it was closed のようなエラーが表示される場合、ラムダブロックが完了した後にセッションを使用しようとしています。すべてのセッション操作がセッションブロック内で行われていることを確認してください。

履歴が大きすぎる (History too large)

履歴が大きくなりすぎてトークンを大量に消費する場合は、履歴圧縮テクニックを使用してください:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node
import ai.koog.agents.core.dsl.extension.HistoryCompressionStrategy

val strategy = strategy<Unit, Unit>("strategy-name") {
    val node by node<Unit, Unit> {
-->
<!--- SUFFIX
   }
}
-->
```kotlin
llm.writeSession {
    // 直近10メッセージを残して圧縮する
    replaceHistoryWithTLDR(HistoryCompressionStrategy.FromLastNMessages(10), preserveMemory = true)
}
```
<!--- KNIT example-sessions-13.kt -->

=== "Java"

<!--- INCLUDE
import ai.koog.agents.core.agent.entity.AIAgentNode;
class exampleSessionsJava13 {
    public static void main(String[] args) {
-->
<!--- SUFFIX
    }
}
-->
```java
// Javaの圧縮ノードを使用して最近の履歴を圧縮します。
var compressHistory = AIAgentNode.llmCompressHistory("compressHistory");
```
<!--- KNIT exampleSessionsJava13.java -->

詳細は、履歴の圧縮を参照してください。

ツールが見つからない (Tool not found)

ツールが見つからないというエラーが表示される場合は、以下を確認してください:

  • ツールがツールレジストリに正しく登録されているか。
  • 正しいツール名またはクラスを使用しているか。

APIドキュメント

詳細については、AIAgentLLMSession および AIAgentLLMContext の全リファレンスを参照してください。