在写Tool层实现的时候,其实没觉得这是一个问题,写一个AbstractClass,让所有的tool 都extends AbstractClass,然后扫描bean一次性加载进去,常规套路。
但是很意外的这个套路失灵了。
代码是这样的(省略部分):
public class AgentChatService {
private final List<AbstractTool> tools;
public Flux<String> chatWithTool(String prompt) {
return Flux.defer(() -> chatClient.prompt(prompt).tools(tools).stream().content());
}
}
报错信息一直是这样的(隐去了部分的className):
1 |
|
也就是切换成这种方式,@Tool
的注解框架突然扫不到了。
我下意识的怀疑toolList是空对象,但很快意识到不对,因为报错信息已经明确提示了具体的类。
Debug跟进去看一下,对象注入一切正常,现在有两个怀疑:
- AbstractToolList泛化有影响
- CGLIB代理有影响
断点进入框架代码:
public ChatClient.ChatClientRequestSpec tools(Object... toolObjects) {
Assert.notNull(toolObjects, "toolObjects cannot be null");
Assert.noNullElements(toolObjects, "toolObjects cannot contain null elements");
this.toolCallbacks.addAll(Arrays.asList(ToolCallbacks.from(toolObjects)));
return this;
}
我传入了一个什么来着?一个List。
改一下:
public class AgentChatService {
private final List<AbstractTool> tools;
public Flux<String> chatWithTool(String prompt) {
return Flux.defer(() -> chatClient.prompt(prompt).tools(tools.toArray()).stream().content());
}
}
重新测试一下,一切正常了。
细节是魔鬼。