spring-projects / spring-projects/spring-ai
Consider caching JSON schema generation in function calling
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.5k
- Forks
- 2.9k
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 6
Description
Current Performance Issue
Function calling applications regenerate identical JSON schemas on every request, causing significant CPU overhead.
Root cause analysis:
// User code pattern
chatClient.prompt("What's the weather?")
.tools(new WeatherTools()) // New instance every time
.call();
// Execution chain:
// 1. ToolCallbacks.from(new WeatherTools())
// 2. MethodToolCallbackProvider.getToolCallbacks() - no caching
// 3. ToolDefinitions.from(toolMethod) - called for each @Tool method
// 4. JsonSchemaGenerator.generateForMethodInput(method) - CPU intensive
Evidence from source code:
MethodToolCallbackProvider.getToolCallbacks() creates new tool definitions every time:
public ToolCallback[] getToolCallbacks() {
return this.toolObjects.stream()
.map(toolMethod -> MethodToolCallback.builder()
.toolDefinition(ToolDefinitions.from(toolMethod)) // No caching here
.build())
.toArray(ToolCallback[]::new);
}
ToolDefinitions.from() calls schema generation without caching:
public static ToolDefinition from(Method method) {
return builder(method).build(); // Always creates new
}
public static DefaultToolDefinition.Builder builder(Method method) {
return DefaultToolDefinition.builder()
.inputSchema(JsonSchemaGenerator.generateForMethodInput(method)); // Expensive call
}
JsonSchemaGenerator.generateForMethodInput() performs expensive operations every time:
public static String generateForMethodInput(Method method, SchemaOption... schemaOptions) {
// Complex schema generation with reflection
for (int i = 0; i < method.getParameterCount(); i++) {
ObjectNode parameterNode = SUBTYPE_SCHEMA_GENERATOR.generateSchema(parameterType); // CPU intensive
}
return schema.toPrettyString(); // JSON serialization
}
Performance Impact
Typical scenario:
@RestController
public class ChatController {
@PostMapping("/chat")
public String chat(@RequestBody String message) {
// Same schemas regenerated on every HTTP request
return chatClient.prompt(message)
.tools(new WeatherTools()) // 2 @Tool methods = 2 schema generations
.call().content();
}
}
Current behavior creates repeated work:
- Same method signatures generate identical schemas multiple times
- No reuse of schema generation results across requests
- Optimization opportunity exists for applications with repeated tool usage
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing MethodToolCallbackProvider.getToolCallbacks(), ToolDefinitions.from(), and JsonSchemaGenerator.generateForMethodInput() to understand where repeated schema generation occurs. Define and verify reuse of identical method schemas while preserving the generated tool definitions and existing behavior; the payload does not name a test file to run.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100