Kotlinv2.4.0

概览

智能体使用工具执行特定任务或访问外部系统。

工具工作流

Koog 框架为在 Kotlin 和 Java 中使用工具提供了以下工作流:

  1. 创建自定义工具或使用内置工具。
  2. 将工具添加到工具注册表。
  3. 将工具注册表传递给智能体。
  4. 在智能体中使用工具。

可用工具类型

Koog 框架中有三种类型的工具:

  • 内置工具:提供智能体与用户交互及会话管理的功能。详情请参阅 内置工具
  • 基于注解的自定义工具:允许您将函数作为工具暴露给 LLM。详情请参阅 基于注解的工具
  • 自定义工具:允许您控制工具参数、元数据、执行逻辑,以及其注册和调用方式。详情请参阅 基于类的工具

工具注册表

在智能体中使用工具之前,必须将其添加到工具注册表中。 工具注册表管理智能体可用的所有工具。

工具注册表的主要特性:

  • 组织工具。
  • 支持合并多个工具注册表。
  • 提供按名称或类型检索工具的方法。

要了解更多信息,请参阅 ToolRegistry

以下是如何创建工具注册表并向其中添加工具的示例:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.tools.ToolRegistry
import ai.koog.agents.core.tools.annotations.Tool
import ai.koog.agents.core.tools.reflect.ToolSet
class MyToolSet : ToolSet {
    @Tool
    fun myTool(): String {
        // 工具实现
        return "Result"
    }
}
val myTool = MyToolSet()
-->
```kotlin
val toolRegistry = ToolRegistry {
    tools(myTool)
}
```
<!--- KNIT example-tools-overview-01.kt -->

=== "Java"

<!--- INCLUDE
/**
-->
<!--- SUFFIX
**/
-->
```java
// 创建 ToolSet 实例
MyToolSet myTool = new MyToolSet();

// 构建 ToolRegistry 并从 ToolSet 注册工具
ToolRegistry toolRegistry = ToolRegistry.builder()
    .tools(myTool)
    .build();
```
<!--- KNIT example-tools-overview-java-01.java -->

要合并多个工具注册表,请执行以下操作:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.tools.ToolRegistry
import ai.koog.agents.core.tools.annotations.Tool
import ai.koog.agents.core.tools.reflect.ToolSet
class FirstToolSet : ToolSet {
    @Tool
    fun firstSampleTool(): String {
        // 工具实现
        return "First result"
    }
}
class SecondToolSet : ToolSet {
    @Tool
    fun secondSampleTool(): String {
        // 工具实现
        return "Second result"
    }
}
val firstSampleTool = FirstToolSet()
val secondSampleTool = SecondToolSet()
-->
```kotlin
val firstToolRegistry = ToolRegistry {
    tools(firstSampleTool)
}

val secondToolRegistry = ToolRegistry {
    tools(secondSampleTool)
}

val newRegistry = firstToolRegistry + secondToolRegistry
```
<!--- KNIT example-tools-overview-02.kt -->

=== "Java"

<!--- INCLUDE
/**
-->
<!--- SUFFIX
**/
-->
```java
// 创建 ToolSet 实例
FirstToolSet firstSampleTool = new FirstToolSet();
SecondToolSet secondSampleTool = new SecondToolSet();

// 构建独立的工具注册表
ToolRegistry firstToolRegistry = ToolRegistry.builder()
    .tools(firstSampleTool)
    .build();

ToolRegistry secondToolRegistry = ToolRegistry.builder()
    .tools(secondSampleTool)
    .build();

ToolRegistry newRegistry = firstToolRegistry.plus(secondToolRegistry);
```
<!--- KNIT example-tools-overview-java-02.java -->

将工具传递给智能体

要使智能体能够使用工具,您需要在创建智能体时提供一个包含该工具的工具注册表作为参数:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.example.exampleToolsOverview01.toolRegistry
import ai.koog.prompt.executor.clients.openai.OpenAIModels
import ai.koog.prompt.executor.llms.all.simpleOpenAIExecutor
-->
```kotlin
// 智能体初始化
val agent = AIAgent(
    promptExecutor = simpleOpenAIExecutor(System.getenv("OPENAI_API_KEY")),
    systemPrompt = "You are a helpful assistant with strong mathematical skills.",
    llmModel = OpenAIModels.Chat.GPT4o,
    // 将工具注册表传递给智能体
    toolRegistry = toolRegistry
)
```
<!--- KNIT example-tools-overview-03.kt -->

=== "Java"

<!--- INCLUDE
/**
-->
<!--- SUFFIX
**/
-->
```java
AIAgent<String, String> agent = AIAgent.builder()
    .promptExecutor(simpleOpenAIExecutor(System.getenv("OPENAI_API_KEY")))
    .systemPrompt("You are a helpful assistant with strong mathematical skills.")
    .llmModel(OpenAIModels.Chat.GPT4o)
    .toolRegistry(ToolRegistry.builder()
        .tools(secondSampleTool)
        .build()
    )
    .build();
```
<!--- KNIT example-tools-overview-java-03.java -->

调用工具

在智能体代码中调用工具的方法有多种。推荐的方法是使用智能体上下文中提供的方法,而不是直接调用工具,因为这可以确保在智能体环境中正确处理工具操作。

TIP

请确保在您的工具中实现了正确的 错误处理,以防止智能体失败。

工具在由 AIAgentLLMWriteSession 表示的特定会话上下文中被调用。它提供了几种调用工具的方法,以便您可以:

  • 使用给定的实参调用工具。
  • 按名称和给定的实参调用工具。
  • 按提供的工具类和实参调用工具。
  • 使用给定的实参调用指定类型的工具。
  • 调用返回原始字符串结果的工具。

有关更多详细信息,请参阅 AIAgentLLMWriteSession 的 API 参考。

并行工具调用

您还可以使用 toParallelToolCallsRaw 扩展并行调用工具。例如:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.dsl.builder.strategy
import ai.koog.agents.core.dsl.builder.node
import ai.koog.agents.core.tools.SimpleTool
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import ai.koog.serialization.typeToken
import kotlinx.serialization.Serializable
-->
```kotlin
@Serializable
data class Book(
    val title: String,
    val author: String,
    val description: String
)

class BookTool() : SimpleTool<Book>(
    argsType = typeToken<Book>(),
    name = NAME,
    description = "A tool to parse book information from Markdown"
) {
    companion object {
        const val NAME = "book"
    }

    override suspend fun execute(args: Book): String {
        println("${args.title} by ${args.author}:

${args.description}") return "Done" } }

val strategy = strategy<Unit, Unit>("strategy-name") {

    /*...*/

    val myNode by node<Unit, Unit> { _ ->
        llm.writeSession {
            flow {
                emit(Book("Book 1", "Author 1", "Description 1"))
            }.toParallelToolCallsRaw(BookTool::class).collect()
        }
    }
}

```
<!--- KNIT example-tools-overview-04.kt -->

=== "Java"

<!--- INCLUDE
/**
-->
<!--- SUFFIX
**/
-->
```java
```
<!--- KNIT example-tools-overview-java-04.java -->

从节点调用工具

在使用节点构建智能体工作流时,可以使用特殊节点来调用工具:

  • nodeExecuteTool:调用单个工具并返回其结果。详情请参阅 API 参考

  • nodeExecuteSingleTool:使用提供的实参调用特定工具。详情请参阅 API 参考

  • nodeExecuteMultipleTools:执行多次工具调用并返回其结果。详情请参阅 API 参考

  • nodeLLMSendToolResult:将工具结果发送给 LLM 并获取响应。详情请参阅 API 参考

  • nodeLLMSendMultipleToolResults:将多个工具结果发送给 LLM。详情请参阅 API 参考

将智能体用作工具

该框架提供了将任何 AI 智能体转换为可供其他智能体使用的工具的能力。这项强大的功能使您能够创建分层智能体架构,其中专业智能体可以作为工具被更高级别的编排智能体调用。

将智能体转换为工具

要将智能体转换为工具,请使用 AIAgentServicecreateAgentTool() 扩展函数:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.agent.AIAgentService
import ai.koog.agents.core.agent.createAgentTool
import ai.koog.agents.core.tools.ToolParameterDescriptor
import ai.koog.agents.core.tools.ToolParameterType
import ai.koog.agents.core.tools.ToolRegistry
import ai.koog.prompt.executor.clients.openai.OpenAIModels
import ai.koog.prompt.executor.llms.all.simpleOpenAIExecutor
import ai.koog.serialization.typeToken
const val apiKey = ""
val analysisToolRegistry = ToolRegistry {}
-->
```kotlin
// 创建一个专门的智能体服务,负责创建财务分析智能体。
val analysisAgentService = AIAgentService(
    promptExecutor = simpleOpenAIExecutor(apiKey),
    llmModel = OpenAIModels.Chat.GPT4o,
    systemPrompt = "You are a financial analysis specialist.",
    toolRegistry = analysisToolRegistry
)

// 创建一个在调用时运行财务分析智能体的工具。
val analysisAgentTool = analysisAgentService.createAgentTool(
    agentName = "analyzeTransactions",
    agentDescription = "Performs financial transaction analysis",
    inputDescription = "Transaction analysis request",
    inputType = typeToken<String>(),
)
```
<!--- KNIT example-tools-overview-05.kt -->

=== "Java"

<!--- INCLUDE
/**
-->
<!--- SUFFIX
**/
-->
```java
```
<!--- KNIT example-tools-overview-java-05.java -->

在其他智能体中使用智能体工具

转换为工具后,您可以将智能体工具添加到另一个智能体的工具注册表中:

=== "Kotlin"

<!--- INCLUDE
import ai.koog.agents.core.agent.AIAgent
import ai.koog.agents.core.tools.ToolRegistry
import ai.koog.agents.example.exampleToolsOverview05.analysisAgentTool
import ai.koog.prompt.executor.clients.openai.OpenAIModels
import ai.koog.prompt.executor.llms.all.simpleOpenAIExecutor
const val apiKey = ""
-->
```kotlin
// 创建一个协调智能体,它可以使用专门的智能体作为工具
val coordinatorAgent = AIAgent(
    promptExecutor = simpleOpenAIExecutor(apiKey),
    llmModel = OpenAIModels.Chat.GPT4o,
    systemPrompt = "You coordinate different specialized services.",
    toolRegistry = ToolRegistry {
        tool(analysisAgentTool)
        // 根据需要添加其他工具
    }
)
```
<!--- KNIT example-tools-overview-06.kt -->

=== "Java"

<!--- INCLUDE
/**
-->
<!--- SUFFIX
**/
-->
```java
```
<!--- KNIT example-tools-overview-java-06.java -->

智能体工具执行

当调用智能体工具时:

  1. 实参将根据输入描述符进行反序列化。
  2. 包装的智能体使用反序列化的输入执行。
  3. 智能体的输出被序列化并作为工具结果返回。

智能体用作工具的优势

  • 模块化:将复杂的工作流分解为专门的智能体。
  • 可重用性:在多个协调智能体中重复使用相同的专业智能体。
  • 关注点分离:每个智能体可以专注于其特定的领域。