文章目录
- `dev.langchain4j.agent.tool.Tool`是什么
- 官方定义的核心行为
- 在包里的位置
- 最典型的官方用法
- 它解决了什么问题
- 使用时你要注意的点
- 1)它标注的是“方法”,不是类
- 2)参数语义通常要配合 `@P`
- 3)返回值设计会直接影响模型效果
- 1. `@Tool`
- 2. `@P`
- 3. `@ToolMemoryId`
- 官方 **package summary** 里还能看到这些非注解类型:
dev.langchain4j.agent.tool.ToolTool不是普通业务类,而是一个注解(annotation)。它的作用是把某个 Java 方法声明成可被 LLM 调用的工具 / function。LangChain4j 官方包说明里对它的定义很直接:被@Tool标注的方法,会被当作 language model 可以执行/调用的工具函数。(javadoc.io)
dev.langchain4j.agent.tool.Tool是什么
LangChain4j 的官方主页明确说明,这个框架支持“Java 调用 LLM”和“LLM 反过来调用 Java 代码”两个方向;@Tool就属于后者的核心能力。(docs.langchain4j.dev)
在官方源码/Javadoc 语义里,@Tool的职责是:
- 把 Java 方法暴露给模型作为 tool/function
- 配合
AiServices自动生成底层ToolSpecification - 把方法签名、参数、注解信息发送给模型
- 当模型决定调用时,自动解析参数并执行方法 (GitHub)
官方定义的核心行为
官方源码对@Tool的执行行为描述得比较完整:
- 方法会被自动转成
ToolSpecification - 如果 LLM 选择调用该工具,框架会自动解析 arguments 并调用对应方法
- 返回值如果是
String,会原样传回给 LLM - 返回值如果是
void,会返回"Success" - 其他类型会被序列化为 JSON 再传回模型 (GitHub)
这意味着,@Tool本质上是高层工具 API 的入口注解,让你不必手写底层ToolSpecification和执行器。
在包里的位置
官方 Javadoc 的dev.langchain4j.agent.tool包里,围绕Tool一起工作的几个核心成员有:
Tool:声明工具方法P:声明工具参数ReturnBehavior:定义工具返回值如何处理ToolExecutionRequest:模型生成的工具调用请求ToolSpecification:发送给模型的工具描述ToolSpecifications:从对象/方法提取工具描述的工具类 (javadoc.io)
所以你可以把Tool理解成这一整套 tool-calling 机制的入口注解。
最典型的官方用法
官方教程说明:在高层 API 里,你可以直接给 Java 方法加@Tool,然后在创建 AI Service 时通过.tools(...)注册。AI Service 会自动把这些方法转成ToolSpecification,在每次与 LLM 交互时带上;当 LLM 决定调用时,AI Service 会自动执行相应方法,并把返回值再送回模型。(GitHub)
典型写法如下:
classWeatherTools{@Tool("查询指定城市天气")StringgetWeather(@P("城市名称")Stringcity){returnweatherService.query(city);}}注册方式通常是:
Assistantassistant=AiServices.builder(Assistant.class).chatModel(chatModel).tools(newWeatherTools()).build();这个模式来自官方 Tools 教程描述的高层 Tool API。(GitHub)
它解决了什么问题
如果不用@Tool,你通常需要自己维护:
- 工具名称
- 工具描述
- 参数 schema
- 参数解析
- 工具执行映射
而@Tool+@P的组合,把这些从“手工拼装”提升成了“注解驱动配置”。官方教程明确说,这一层属于High Level Tool API;与之对应的另一层是手动构造ToolSpecification的Low Level Tool API。(GitHub)
使用时你要注意的点
1)它标注的是“方法”,不是类
@Tool是给方法加的,不是给整个类加的。类本身通常只是一个工具容器对象。这个从官方对它的定义“Java methods annotated with@Tool…”就能看出来。(javadoc.io)
2)参数语义通常要配合@P
如果只写裸参数,模型能拿到类型,但未必拿到足够好的参数语义。官方包里把P明确描述为“Parameter of a Tool”,也就是专门给工具参数补充语义的注解。(javadoc.io)
3)返回值设计会直接影响模型效果
因为String会原样给 LLM,复杂对象会转 JSON,所以:
- 简单文本型结果,用
String很直接 - 结构化结果,用对象返回更适合下游推理/拼装
- 没有返回内容时,
void也可用,但实际送回模型的是"Success"(GitHub)
LangChain4j 用来把 Java 方法声明成 LLM 可调用工具的注解。
这个包dev.langchain4j.agent.tool里,当前和注解直接相关的主要有 3 个注解类型:
@Tool@P@ToolMemoryId(Javadoc)
如果你问的是“这些注解里各自有哪些注解元素(annotation elements)”,可以这样看:
1.@Tool
@Tool用在方法上,把 Java 方法声明成可被 LLM 调用的工具。它现在包含这些注解元素:
name():工具名,默认空字符串,没写时通常用方法名value():工具描述,类型是String[]returnBehavior():工具返回行为,默认ReturnBehavior.TO_LLMsearchBehavior():工具参与 tool search 的方式,默认SearchBehavior.SEARCHABLE,标注为@Experimental,since 1.12.0metadata():provider-specific 的 JSON 字符串元数据,默认"{}",标注为@Experimental,since 1.10.0(GitHub)
2.@P
@P用在参数上,给工具参数补充 schema 语义。它现在包含这些注解元素:
value():参数描述name():参数名;如果没写,通常回退到反射拿到的参数名required():是否必填,默认truejsonSchema():自定义参数 schema 类型,默认NoneCustomSchemaElement.class;这是后来加入的扩展能力,用于自定义参数 schema/coercion (Javadoc)
3.@ToolMemoryId
@ToolMemoryId也是这个包里的注解类型,用在工具方法参数上,表示这个参数承接当前工具执行上下文里的 memory id。Javadoc 的类层级索引里能看到它和@Tool一样,都是实现java.lang.annotation.Annotation的注解类型。(Javadoc)
官方package summary里还能看到这些非注解类型:
ReturnBehaviorToolExecutionRequest- 以及和工具规范/执行相关的其他类型;其中 package summary 明确列出了
P、Tool、ReturnBehavior、ToolExecutionRequest。(Javadoc)
给你一个最实用的记忆方式:
@Tool:标方法,声明“这是工具”@P:标普通参数,声明“这个参数叫什么、怎么描述、是否必填”@ToolMemoryId:标特殊参数,声明“这个参数接收 memoryId” (GitHub)