概述
代理使用工具来执行特定任务或访问外部系统。
工具工作流
Koog 框架为在 Kotlin 和 Java 中使用工具提供了以下工作流:
- 创建自定义工具或使用内置工具之一。
- 将工具添加到工具注册表。
- 将工具注册表传递给代理。
- 与代理一起使用该工具。
可用工具类型
Koog 框架中有三种类型的工具:
- 内置工具,提供代理-用户交互和对话管理的功能。详情请参阅内置工具。
- 基于注解的自定义工具,允许您将函数作为工具暴露给 LLM。详情请参阅基于注解的工具。
- 自定义工具,允许您控制工具参数、元数据、执行逻辑以及其注册和调用方式。详情请参阅基于类的工具。
工具注册表
在代理中使用工具之前,必须将其添加到工具注册表中。 工具注册表管理代理可用的所有工具。
工具注册表的主要特性:
- 组织工具。
- 支持合并多个工具注册表。
- 提供按名称或类型检索工具的方法。
要了解更多信息,请参阅 ToolRegistry。
以下是如何创建工具注册表并向其中添加工具的示例:
要合并多个工具注册表,请执行以下操作:
// Create instances of your ToolSets
FirstToolSet firstSampleTool = new FirstToolSet();
SecondToolSet secondSampleTool = new SecondToolSet();
// Build separate tool registries
ToolRegistry firstToolRegistry = ToolRegistry.builder()
.tools(firstSampleTool)
.build();
ToolRegistry secondToolRegistry = ToolRegistry.builder()
.tools(secondSampleTool)
.build();
ToolRegistry newRegistry = firstToolRegistry.plus(secondToolRegistry);
将工具传递给代理
要使代理能够使用工具,您需要在创建代理时提供一个包含该工具的工具注册表作为参数:
=== "Kotlin"
// 智能体初始化
val agent = AIAgent(
promptExecutor = simpleOpenAIExecutor(System.getenv("OPENAI_API_KEY")),
systemPrompt = "你是一位具备强大数学能力的助手。",
llmModel = OpenAIModels.Chat.GPT4o,
// 将你的工具注册表传递给智能体
toolRegistry = toolRegistry
)
调用工具
在你的智能体代码中,有几种调用工具的方式。推荐的方法是使用智能体上下文中提供的方法,而不是直接调用工具,这能确保在智能体环境中正确处理工具操作。
Tip
请确保你已在工具中实现了适当的错误处理,以防止智能体运行失败。
工具在由 AIAgentLLMWriteSession 表示的特定会话上下文中被调用。
它提供了几种调用工具的方法,以便你可以:
- 使用给定的参数调用一个工具。
- 通过工具名称和给定的参数调用一个工具。
- 通过提供的工具类和参数调用一个工具。
- 使用给定的参数调用指定类型的工具。
- 调用一个返回原始字符串结果的工具。
更多详细信息,请参阅 AIAgentLLMWriteSession 的 API 参考。
并行工具调用
你也可以使用 toParallelToolCallsRaw 扩展来并行调用工具。例如:
@Serializable
data class Book(
val title: String,
val author: String,
val description: String
)
class BookTool() : SimpleTool<Book>(
argsType = typeToken<Book>(),
name = NAME,
description = "一个从 Markdown 解析书籍信息的工具"
) {
companion object {
const val NAME = "book"
}
override suspend fun execute(args: Book): String {
println("${args.title} 作者 ${args.author}:\n ${args.description}")
return "完成"
}
}
val strategy = strategy<Unit, Unit>("strategy-name") {
/*...*/
val myNode by node<Unit, Unit> { _ ->
llm.writeSession {
flow {
emit(Book("书籍 1", "作者 1", "描述 1"))
}.toParallelToolCallsRaw(BookTool::class).collect()
}
}
}
从节点调用工具
在使用节点构建智能体工作流时,你可以使用特殊节点来调用工具:
-
nodeExecuteTool:调用单个工具调用并返回其结果。详情请参阅 API-参考。 nodeExecuteSingleTool*:调用指定工具并传入参数。详情请参阅 API-参考文档。
-
nodeExecuteMultipleTools:执行多个工具调用并返回结果。详情请参阅 API-参考文档。
-
nodeLLMSendToolResult:向 LLM 发送工具执行结果并获取响应。详情请参阅 API-参考文档。
-
nodeLLMSendMultipleToolResults:向 LLM 发送多个工具执行结果。详情请参阅 API-参考文档。
将智能体作为工具使用
该框架支持将任意 AI 智能体转换为可供其他智能体调用的工具。这一强大功能使您能够构建分层智能体架构,让高层协调智能体可以像调用工具一样调用专用智能体。
将智能体转换为工具
要转换智能体为工具,请使用 AIAgentService 及 createAgentTool() 扩展函数:
// 创建专用智能体服务,负责生成财务分析智能体
val analysisAgentService = AIAgentService(
promptExecutor = simpleOpenAIExecutor(apiKey),
llmModel = OpenAIModels.Chat.GPT4o,
systemPrompt = "您是一名财务分析专家。",
toolRegistry = analysisToolRegistry
)
// 创建调用时会运行财务分析智能体的工具
val analysisAgentTool = analysisAgentService.createAgentTool(
agentName = "analyzeTransactions",
agentDescription = "执行财务交易分析",
inputDescription = "交易分析请求",
inputType = typeToken<String>(),
)
在其他智能体中使用智能体工具
转换为工具后,您可以将智能体工具添加到其他智能体的工具注册表中:
智能体工具执行流程
当智能体工具被调用时:
- 参数根据输入描述符进行反序列化
- 封装的智能体使用反序列化后的输入执行
- 智能体的输出被序列化并作为工具结果返回
智能体作为工具的优势
- 模块化:将复杂工作流拆分为专用智能体
- 可复用性:同一专用智能体可被多个协调智能体使用
- 关注点分离:每个智能体可专注于特定领域