Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advancing Tool Support in Spring AI #2049

Closed
ThomasVitale opened this issue Jan 6, 2025 · 5 comments
Closed

Advancing Tool Support in Spring AI #2049

ThomasVitale opened this issue Jan 6, 2025 · 5 comments
Milestone

Comments

@ThomasVitale
Copy link
Contributor

ThomasVitale commented Jan 6, 2025

This issue presents ideas and suggestions for consolidating and advancing tool support in Spring AI, before reaching the first GA version.

Tool Registration

Tools are modelled via the ToolCallback API. By default, Spring AI supports registering tools from methods and from functional objects.

Methods

In the context of Java, a tool can naturally be modelled as a method. Spring AI support registering methods as tools via the MethodToolCallback API.

Declarative tool registration is supported via the @Tool annotation on methods.

class MyTools {

    @Tool(description = "Get the list of books written by the given author available in the library")
    List<Book> booksByAuthor(String author) {
        return bookService.getBooksByAuthor(new Author(author));
    }

}
@GetMapping("/chat")
String chat(String authorName) {
    return chatClient.prompt()
            .user("What books written by %s are available in the library?".formatted(authorName))
            .tools(new MyTools())
            .call()
            .content();
}

Functions

In special cases, there might be a wish for modelling tools as functional objects (Function/BiFunction/Supplier/Consumer). Spring AI support registering functional objects as tools via the FunctionToolCallback API.

@GetMapping("/chat")
String chat(String authorName) {
    return chatClient.prompt()
            .user("What books written by %s are available in the library?".formatted(authorName))
            .tools(FunctionToolCallback.builder("booksByAuthor", author -> bookService().getBooksByAuthor(author))
                        .description("Get the list of books written by the given author available in the library")
                        .inputType(BookService.Author.class)
                        .build())
            .call()
            .content();
}

Tool Execution

By default, tool execution is performed transparently by a ChatModel object using the ToolCallingManager API. In case of errors while executing tools, a ToolCallExceptionConverter is used to process the exception.

If you need full control over the tool execution, for example by asking the user permission before each tool execution, you can disable the internal tool execution feature and manage the tool calling workflow yourself using the ToolCallingManager API directly.

ChatOptions chatOptions = ToolCallingChatOptions.builder()
			.toolCallbacks(ToolCallbacks.from(tools))
			.internalToolExecutionEnabled(false)
			.build();

Prompt prompt = new Prompt("What's the weather in Copenhagen?", chatOptions);

ChatResponse chatResponse = chatModel.call(prompt);

if (chatResponse.hasToolCalls()) {
    List<Message> messages = toolCallingManager.executeToolCalls(prompt, chatResponse);
}

Prompt secondPrompt = new Prompt(messages, chatOptions);

ChatResponse secondChatResponse = chatModel.call(secondPrompt);

Tool Resolution

Instead of providing tools as ToolCallbacks to ChatModel or ChatClient, you have the option to pass just tool names and let the framework resolve them into ToolCallbacks dynamically.

By default, Spring AI support dynamic tool resolution from the following:

  • Functional objects registered as beans with the Spring context (Function/BiFunction/Supplier/Consumer).
  • ToolCallbacks registered as beans with the Spring context.

Additional resolution strategies can be provided via the ToolCallbackResolver API.

Example:

@Configuration(proxyBeanMethods = false)
class Functions {

    @Bean
    @Description("Get the list of books written by the given author available in the library")
    public Function<Author, List<Book>> booksByAuthor(BookService bookService) {
        return author -> bookService.getBooksByAuthor(author);
    }

}

Tasks

ThomasVitale added a commit to ThomasVitale/spring-ai that referenced this issue Jan 11, 2025
* Defined new APIs consolidating the “tool” naming as opposed to the current “function”, aligning with the industry and solving the confusion between “function tool” and “Java Function”: ToolCallback and ToolCallingChatOptions. They extend the current ones to ensure backward compatibility, but FunctionCallback and FunctionCallingOptions can be considered deprecated.
* Enhanced support for methods as tools, introducing support for declarative Tool-annotated methods via MethodToolCallback and MethodToolCallbackProvider (deprecating the existing MethodInvokingFunctionCallback).
* Improved tool execution logic with granular support for returning the result directly to the client and exception handling.
* Improved JSON Schema generation and parsing logic, consolidating the usage of the victools/jsonschema-generator library and dropping the non-maintained Jackson JSON Schema Module. This makes it possible to use tools with input lists/arrays, which the latter library was not supporting.
* Extended ChatClient API with new methods tools() and toolCallbacks(). The existing functions() methods can be considered deprecated.

Handles spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
ThomasVitale added a commit to ThomasVitale/spring-ai that referenced this issue Jan 12, 2025
* Defined new APIs consolidating the “tool” naming as opposed to the current “function”, aligning with the industry and solving the confusion between “function tool” and “Java Function”: ToolCallback and ToolCallingChatOptions. They extend the current ones to ensure backward compatibility, but FunctionCallback and FunctionCallingOptions can be considered deprecated.
* Enhanced support for methods as tools, introducing support for declarative Tool-annotated methods via MethodToolCallback and MethodToolCallbackProvider (deprecating the existing MethodInvokingFunctionCallback).
* Improved tool execution logic with granular support for returning the result directly to the client and exception handling.
* Improved JSON Schema generation and parsing logic, consolidating the usage of the victools/jsonschema-generator library and dropping the non-maintained Jackson JSON Schema Module. This makes it possible to use tools with input lists/arrays, which the latter library was not supporting.
* Extended ChatClient API with new methods tools() and toolCallbacks(). The existing functions() methods can be considered deprecated.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
ThomasVitale added a commit to ThomasVitale/spring-ai that referenced this issue Jan 12, 2025
* Defined new APIs consolidating the “tool” naming as opposed to the current “function”, aligning with the industry and solving the confusion between “function tool” and “Java Function”: ToolCallback and ToolCallingChatOptions. They extend the current ones to ensure backward compatibility, but FunctionCallback and FunctionCallingOptions can be considered deprecated.
* Enhanced support for methods as tools, introducing support for declarative Tool-annotated methods via MethodToolCallback and MethodToolCallbackProvider (deprecating the existing MethodInvokingFunctionCallback).
* Improved tool execution logic with granular support for returning the result directly to the client and exception handling.
* Improved JSON Schema generation and parsing logic, consolidating the usage of the victools/jsonschema-generator library and dropping the non-maintained Jackson JSON Schema Module. This makes it possible to use tools with input lists/arrays, which the latter library was not supporting.
* Extended ChatClient API with new methods tools() and toolCallbacks(). The existing functions() methods can be considered deprecated.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
@hansdesmet
Copy link

This would make tooling great !
LangChain4J also has a @Tool annotation with the same purpose:
https://docs.langchain4j.dev/tutorials/tools/#high-level-tool-api

@Yougoss
Copy link

Yougoss commented Jan 14, 2025

Is there a plan to support Function parameters properties description? to make ai better understand how to get the corresponding parameters from the context.

From openai doc, there is a description field for each function parameters property

ThomasVitale added a commit to ThomasVitale/spring-ai that referenced this issue Jan 16, 2025
* Defined new APIs consolidating the “tool” naming as opposed to the current “function”, aligning with the industry and solving the confusion between “function tool” and “Java Function”: ToolCallback and ToolCallingChatOptions. They extend the current ones to ensure backward compatibility, but FunctionCallback and FunctionCallingOptions can be considered deprecated.
* Enhanced support for methods as tools, introducing support for declarative Tool-annotated methods via MethodToolCallback and MethodToolCallbackProvider (deprecating the existing MethodInvokingFunctionCallback).
* Improved tool execution logic with granular support for returning the result directly to the client and exception handling.
* Improved JSON Schema generation and parsing logic, consolidating the usage of the victools/jsonschema-generator library and dropping the non-maintained Jackson JSON Schema Module. This makes it possible to use tools with input lists/arrays, which the latter library was not supporting.
* Extended ChatClient API with new methods tools() and toolCallbacks(). The existing functions() methods can be considered deprecated.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
tzolov pushed a commit that referenced this issue Jan 17, 2025
* Defined new APIs consolidating the “tool” naming as opposed to the current “function”, aligning with the industry and solving the confusion between “function tool” and “Java Function”: ToolCallback and ToolCallingChatOptions. They extend the current ones to ensure backward compatibility, but FunctionCallback and FunctionCallingOptions can be considered deprecated.
* Enhanced support for methods as tools, introducing support for declarative Tool-annotated methods via MethodToolCallback and MethodToolCallbackProvider (deprecating the existing MethodInvokingFunctionCallback).
* Improved tool execution logic with granular support for returning the result directly to the client and exception handling.
* Improved JSON Schema generation and parsing logic, consolidating the usage of the victools/jsonschema-generator library and dropping the non-maintained Jackson JSON Schema Module. This makes it possible to use tools with input lists/arrays, which the latter library was not supporting.
* Extended ChatClient API with new methods tools() and toolCallbacks(). The existing functions() methods can be considered deprecated.

Relates to gh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
ThomasVitale added a commit to ThomasVitale/spring-ai that referenced this issue Jan 19, 2025
* Enhanced support for functions as tools via FunctionToolCallback (deprecating the existing FunctionInvokingFunctionCallback).
* Aligned JSON Schema generation and parsing logic between function-based and method-based tools.
* Deprecated previous client-side function calling APIs.
* Included AOT configuration for Tool-annotated methods in Spring beans.

Relates to spring-projectsgh-2049
ThomasVitale added a commit to ThomasVitale/spring-ai that referenced this issue Jan 19, 2025
* Enhanced support for functions as tools via FunctionToolCallback (deprecating the existing FunctionInvokingFunctionCallback).
* Aligned JSON Schema generation and parsing logic between function-based and method-based tools.
* Deprecated previous client-side function calling APIs.
* Included AOT configuration for Tool-annotated methods in Spring beans.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
StudiousXiaoYu pushed a commit to StudiousXiaoYu/spring-ai that referenced this issue Jan 21, 2025
* Defined new APIs consolidating the “tool” naming as opposed to the current “function”, aligning with the industry and solving the confusion between “function tool” and “Java Function”: ToolCallback and ToolCallingChatOptions. They extend the current ones to ensure backward compatibility, but FunctionCallback and FunctionCallingOptions can be considered deprecated.
* Enhanced support for methods as tools, introducing support for declarative Tool-annotated methods via MethodToolCallback and MethodToolCallbackProvider (deprecating the existing MethodInvokingFunctionCallback).
* Improved tool execution logic with granular support for returning the result directly to the client and exception handling.
* Improved JSON Schema generation and parsing logic, consolidating the usage of the victools/jsonschema-generator library and dropping the non-maintained Jackson JSON Schema Module. This makes it possible to use tools with input lists/arrays, which the latter library was not supporting.
* Extended ChatClient API with new methods tools() and toolCallbacks(). The existing functions() methods can be considered deprecated.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
Signed-off-by: StudiousXiaoYu <1316356098@qq.com>
@ilayaperumalg ilayaperumalg added this to the 1.0.0-M6 milestone Jan 23, 2025
leijendary pushed a commit to leijendary/spring-ai that referenced this issue Jan 24, 2025
* Defined new APIs consolidating the “tool” naming as opposed to the current “function”, aligning with the industry and solving the confusion between “function tool” and “Java Function”: ToolCallback and ToolCallingChatOptions. They extend the current ones to ensure backward compatibility, but FunctionCallback and FunctionCallingOptions can be considered deprecated.
* Enhanced support for methods as tools, introducing support for declarative Tool-annotated methods via MethodToolCallback and MethodToolCallbackProvider (deprecating the existing MethodInvokingFunctionCallback).
* Improved tool execution logic with granular support for returning the result directly to the client and exception handling.
* Improved JSON Schema generation and parsing logic, consolidating the usage of the victools/jsonschema-generator library and dropping the non-maintained Jackson JSON Schema Module. This makes it possible to use tools with input lists/arrays, which the latter library was not supporting.
* Extended ChatClient API with new methods tools() and toolCallbacks(). The existing functions() methods can be considered deprecated.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
Signed-off-by: leijendary <jonathanleijendekker@gmail.com>
leijendary pushed a commit to leijendary/spring-ai that referenced this issue Jan 24, 2025
* Defined new APIs consolidating the “tool” naming as opposed to the current “function”, aligning with the industry and solving the confusion between “function tool” and “Java Function”: ToolCallback and ToolCallingChatOptions. They extend the current ones to ensure backward compatibility, but FunctionCallback and FunctionCallingOptions can be considered deprecated.
* Enhanced support for methods as tools, introducing support for declarative Tool-annotated methods via MethodToolCallback and MethodToolCallbackProvider (deprecating the existing MethodInvokingFunctionCallback).
* Improved tool execution logic with granular support for returning the result directly to the client and exception handling.
* Improved JSON Schema generation and parsing logic, consolidating the usage of the victools/jsonschema-generator library and dropping the non-maintained Jackson JSON Schema Module. This makes it possible to use tools with input lists/arrays, which the latter library was not supporting.
* Extended ChatClient API with new methods tools() and toolCallbacks(). The existing functions() methods can be considered deprecated.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
Signed-off-by: leijendary <jonathanleijendekker@gmail.com>
tzolov pushed a commit to tzolov/spring-ai that referenced this issue Jan 26, 2025
* Enhanced support for functions as tools via FunctionToolCallback (deprecating the existing FunctionInvokingFunctionCallback).
* Aligned JSON Schema generation and parsing logic between function-based and method-based tools.
* Deprecated previous client-side function calling APIs.
* Included AOT configuration for Tool-annotated methods in Spring beans.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
ThomasVitale added a commit to ThomasVitale/spring-ai that referenced this issue Jan 26, 2025
* Introduced ToolCallingManager to manage the tool calling activities for resolving and executing tools. A default implementation is provided. It can be used to handle explicit tool execution on the client-side, superseding the previous FunctionCallingHelper class. It’s ready to be instrumented via Micrometer, and support exception handling when tool calls fail.
* Introduced ToolCallExceptionConverter to handle exceptions in tool calling, and provided a default implementation propagating the error message to the chat morel.
* Introduced ToolCallbackResolver to resolve ToolCallback instances. A default implementation is provided (DelegatingToolCallbackResolver), capable of delegating the resolution to a series of resolvers, including static resolution (StaticToolCallbackResolver) and dynamic resolution from the Spring context (SpringBeanToolCallbackResolver).
* Improved configuration in ToolCallingChatOptions to enable/disable the tool execution within a ChatModel (superseding the previous proxyToolCalls option).
* Added unit and integration tests to cover all the new use cases and existing functionality which was not covered by autotests (tool resolution from Spring context).
* Deprecated FunctionCallbackResolver, AbstractToolCallSupport, and FunctionCallingHelper.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
ThomasVitale added a commit to ThomasVitale/spring-ai that referenced this issue Jan 27, 2025
* Introduced ToolCallingManager to manage the tool calling activities for resolving and executing tools. A default implementation is provided. It can be used to handle explicit tool execution on the client-side, superseding the previous FunctionCallingHelper class. It’s ready to be instrumented via Micrometer, and support exception handling when tool calls fail.
* Introduced ToolCallExceptionConverter to handle exceptions in tool calling, and provided a default implementation propagating the error message to the chat morel.
* Introduced ToolCallbackResolver to resolve ToolCallback instances. A default implementation is provided (DelegatingToolCallbackResolver), capable of delegating the resolution to a series of resolvers, including static resolution (StaticToolCallbackResolver) and dynamic resolution from the Spring context (SpringBeanToolCallbackResolver).
* Improved configuration in ToolCallingChatOptions to enable/disable the tool execution within a ChatModel (superseding the previous proxyToolCalls option).
* Added unit and integration tests to cover all the new use cases and existing functionality which was not covered by autotests (tool resolution from Spring context).
* Deprecated FunctionCallbackResolver, AbstractToolCallSupport, and FunctionCallingHelper.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
tzolov pushed a commit that referenced this issue Jan 29, 2025
* Introduced ToolCallingManager to manage the tool calling activities for resolving and executing tools. A default implementation is provided. It can be used to handle explicit tool execution on the client-side, superseding the previous FunctionCallingHelper class. It’s ready to be instrumented via Micrometer, and support exception handling when tool calls fail.
* Introduced ToolCallExceptionConverter to handle exceptions in tool calling, and provided a default implementation propagating the error message to the chat morel.
* Introduced ToolCallbackResolver to resolve ToolCallback instances. A default implementation is provided (DelegatingToolCallbackResolver), capable of delegating the resolution to a series of resolvers, including static resolution (StaticToolCallbackResolver) and dynamic resolution from the Spring context (SpringBeanToolCallbackResolver).
* Improved configuration in ToolCallingChatOptions to enable/disable the tool execution within a ChatModel (superseding the previous proxyToolCalls option).
* Added unit and integration tests to cover all the new use cases and existing functionality which was not covered by autotests (tool resolution from Spring context).
* Deprecated FunctionCallbackResolver, AbstractToolCallSupport, and FunctionCallingHelper.

Relates to gh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
ThomasVitale added a commit to ThomasVitale/spring-ai that referenced this issue Jan 29, 2025
* Adopted new tool calling logic in OllamaChatModel, while maintaining full API backward compatibility thanks to the LegacyToolCallingManager.
* Improved efficiency and robustness of merging options in prompts for Ollama.
* Update Ollama Autoconfiguration to use the new ToolCallingManager.
* Improved troubleshooting for new tool calling APIs and finalised changes for full backward compatibility.
* Updated Ollama Testcontainers dependency to 0.5.7.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
@ogbozoyan
Copy link

ogbozoyan commented Jan 30, 2025

When a chat model determines that a certain tool needs to be called

It's not quite clear how the model realizes that it's “time” to call in the tool
Is it possible to predefine the flow, when model is going to call a method, it checks with @Description from the user if he wants it and on positive answer starts to execute the method ?

tzolov pushed a commit to tzolov/spring-ai that referenced this issue Jan 30, 2025
* Adopted new tool calling logic in OllamaChatModel, while maintaining full API backward compatibility thanks to the LegacyToolCallingManager.
* Improved efficiency and robustness of merging options in prompts for Ollama.
* Update Ollama Autoconfiguration to use the new ToolCallingManager.
* Improved troubleshooting for new tool calling APIs and finalised changes for full backward compatibility.
* Updated Ollama Testcontainers dependency to 0.5.7.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
@ThomasVitale ThomasVitale changed the title [DRAFT] Advancing Tool Support in Spring AI Advancing Tool Support in Spring AI Jan 30, 2025
ThomasVitale added a commit to ThomasVitale/spring-ai that referenced this issue Feb 2, 2025
* Introduced new ToolParam annotation for defining a description for tool parameters and marking them as (non)required.
* Improved the JSON Schema generation for tools, solving inconsistencies between methods and functions, and ensuring a predictable outcome.
* Added support for returning tool results directly to the user instead of passing them back to the model. Introduced new ToolExecutionResult API to propagate this information.
* Consolidated naming of tool-related options in ToolCallingChatOptions.
* Fixed varargs issue in ChatClient when passing ToolCallback[].
* Introduced new documentation for the tool calling capabilities in Spring AI, and deprecated the old one.
* Bumped jsonschema dependency to 4.37.0.

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
@ThomasVitale
Copy link
Contributor Author

ThomasVitale commented Feb 2, 2025

@Yougoss there is already some partial support based on whether you're using methods or functions, and whether it's a nested object or not. I've been working on improving that logic to ensure consistency of behaviour across all those scenarios, and writing documentation for it. You can see the draft PR here: #2162 Feel free to share your feedback on the solution!

The idea implemented in that PR is such that descriptions and required properties can be specified using one of the following supported annotations:

  • @ToolParam(required = ..., description = ...) (from Spring AI)
  • @JsonProperty(required = ...) (from Jackson)
  • @Schema(required = ..., description = ...) (from Swagger)
  • @Nullable (from Spring Framework)

Notice that this is just a proposal. The final solution might differ.

tzolov pushed a commit that referenced this issue Feb 4, 2025
* Introduced new ToolParam annotation for defining a description for tool parameters and marking them as (non)required.
* Improved the JSON Schema generation for tools, solving inconsistencies between methods and functions, and ensuring a predictable outcome.
* Added support for returning tool results directly to the user instead of passing them back to the model. Introduced new ToolExecutionResult API to propagate this information.
* Consolidated naming of tool-related options in ToolCallingChatOptions.
* Fixed varargs issue in ChatClient when passing ToolCallback[].
* Introduced new documentation for the tool calling capabilities in Spring AI, and deprecated the old one.
* Bumped jsonschema dependency to 4.37.0.

Relates to gh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
ThomasVitale added a commit to ThomasVitale/spring-ai that referenced this issue Feb 5, 2025
* Completed new documentation for Tool Calling
* Added deprecation notes and migration guide to documentation
* Made “call” methods explicit in ToolCallback API
* Consolidated naming: ToolCallExceptionConverter -> ToolExecutionExceptionProcessor
* Consolidated naming: ToolCallResultConvert.apply() -> ToolCallResultConvert.convert()

Relates to spring-projectsgh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
tzolov pushed a commit that referenced this issue Feb 5, 2025
* Completed new documentation for Tool Calling
* Added deprecation notes and migration guide to documentation
* Made “call” methods explicit in ToolCallback API
* Consolidated naming: ToolCallExceptionConverter -> ToolExecutionExceptionProcessor
* Consolidated naming: ToolCallResultConvert.apply() -> ToolCallResultConvert.convert()
* Redraw diagrams for consistency

Relates to gh-2049

Signed-off-by: Thomas Vitale <ThomasVitale@users.noreply.github.com>
@ThomasVitale
Copy link
Contributor Author

All the work included in this issue has been delivered. It's available in 1.0.0-SNAPSHOT and will be included in the upcoming 1.0.0-M6 version.

Full documentation of the new tool calling features: https://docs.spring.io/spring-ai/reference/api/tools.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants