We are coming to the end of our Spring AI source code analysis topic today. I've taken a thorough look at the basics of what I'm interested in and shared those analyses with you. If you are interested in this topic, you can read the following articles. Each article is layered with a deeper look at the content in question. Considering that long articles can be exhausting, I have adopted a step-by-step approach to ensure that each one is concise and easy to understand. I hope this will provide you with a valuable reference!
Basic usage of Spring AI:/guoxiaoyu/p/18284842
Evolution and practice of the Spring.3 version of the auto-assembly mechanism:/guoxiaoyu/p/18384642
What exactly is the use of the in SpringBoot.3:/guoxiaoyu/p/18434660
The core logic of Spring AI's blocking request and response mechanism:/guoxiaoyu/p/18440488
Streaming Answers Source Code Analysis for Spring AI:/guoxiaoyu/p/18440684
Today our topic will focus on the last step: how to effectively use AI technology in Java programs. As we all know, Java is an object-oriented programming language, so no matter what AI interface we call, from a business perspective, it is essentially just an interface, while the AI acts as a third-party docking platform. However, it's worth noting that the AI's chat replies often don't apply to objects because they can't directly return formatted JSON data. This issue prevents Spring from transforming them into entity classes, and thus from truly integrating them into business processes.
Today, we will explore how the Spring AI framework effectively addresses this challenge. By deeply analyzing the design and implementation of the framework, we hope to show you how to smoothly integrate AI capabilities into Java applications to drive further business growth.
In addition to this, function call function callback is also an important feature of AI technology. So, how does Spring AI deal with this challenge? Today, we will explore this issue in depth, analyze how the Spring AI framework can effectively deal with function callbacks, so as to enhance the interaction between AI and Java programs.
materialized class
Entity classes play an integral role in Java programs, whether they are performing internal operations or returning data to a front-end RESTful interface, entity classes are at the heart of messaging in the business. In the Spring AI framework, we can effectively control the AI answers to ensure that they map correctly to entity classes. Next, we will explore how Spring AI accomplishes this, with the following basic usage:
@GetMapping("/ai-Entity")
ActorFilms generationByEntity() {
ActorFilms actorFilms = ()
.user("Generate the filmography for a random actor.")
.call()
.entity();
return actorFilms;
}
source code analysis
Here, we no longer call thecontent
method, choosing instead to use theentity
method as a return type. This change means that we need to focus onentity
implementation and its role in the overall process. Next, let's analyze this key part in depth with code samples:
public <T> T entity(Class<T> type) {
(type, "the class must be non-null");
var boc = new BeanOutputConverter<T>(type);
return doSingleWithBeanOutputConverter(boc);
}
Here, a file namedBeanOutputConverter
of the converter. Next, let's take a closer look at thedoSingleWithBeanOutputConverter
The specific implementation of the method.
private <T> T doSingleWithBeanOutputConverter(StructuredOutputConverter<T> boc) {
var chatResponse = doGetObservableChatResponse(, ());
var stringResponse = ().getOutput().getContent();
return (stringResponse);
}
Here, we are going to discuss thedoGetObservableChatResponse
methods are mainly responsible for the interaction process with third-party APIs. Since we have already analyzed the implementation of the Chat Call API method in detail in our previous explanation, we will not delve into its specifics this time, but focus on the core functionality and application scenarios of the method.
Entity class cue word restrictions
Here, let's check out the()
method. This method returns a prompt, which varies depending on the type. To understand this better, we can analyze the prompt format for a single Bean entity class.
The details are as follows:
public String getFormat() {
String template = """
Your response should be in JSON format.
Do not include any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.
Do not include markdown code blocks in your response.
Remove the ```json markdown from the output.
Here is the JSON Schema instance your output must adhere to:
```%s```
""";
return (template, );
}
This is actually very simple. By explicitly restricting the format of the AI's return with a hint word, we can make sure that the output meets our requirements to the greatest extent possible. This approach allows Spring to parse efficiently, while the jsonSchema is simply the various pieces of information we pass in about the entity class.
Encapsulated entity class
method is responsible for the process of encapsulating data into an entity class. Specifically, it will receive the raw data and transform it through internal logic to generate an entity class structure that conforms to our definition.
On the surface, it's clear that the process involves JSON serialization, which encapsulates the data into the object format we expect. However, it is important to note that while the AI's prompts are intended to try to limit the content of its responses to match our requirements as closely as possible, there is no guarantee that the format it returns will be exactly as preset due to a variety of factors.
Therefore, in order to ensure the robustness and reliability of the program, an exception catching mechanism is introduced into the process. This mechanism effectively handles potential formatting inconsistencies or errors, thus ensuring that the application runs smoothly without crashing when confronted with data that does not meet expectations.
function callback
AI is currently able to play a role, mainly thanks to the function calling capabilities of the models. The practical value of relying solely on training models for chat answering is relatively limited, as this approach is very costly and unaffordable for many organizations. However, with the introduction of the function callback feature, AI can access and utilize a variety of data, both real-time and business data, in real time, enabling it to provide more accurate and effective answers based on the information provided, thus providing substantial business capabilities.
Next, let's look at how Spring AI accomplishes this.
basic usage
After understanding the previous Spring AI Usage article, you probably have a good grasp of how to create a Function function. Next, we'll dive right into how to add this function to our project.
@PostMapping("/ai-function")
ChatDataPO functionGenerationByText(@RequestParam("userInput") String userInput) {
String content = ()
.user(userInput)
.functions("CurrentWeather")
.call()
.content();
("content: {}", content);
ChatDataPO chatDataPO = ().code("text").data(().text(content).build()).build();;
return chatDataPO;
}
In our project, the functions function allows to add multiple functionalities that are not limited to a single tool call. For example, in applications that visualize intelligences, such as the Thousand Sails AppBuilder, we can observe the use of thinking rounds, which involves multiple tool calls. This approach provides richer functionality and flexibility to our intelligibles.
Next, we'll make a function call to actually demonstrate the effect.
Here we have used a fixed 30 degrees as an example value, but you can call other third-party services via interfaces inside function methods to get real-time data. Thus, by integrating external data sources, you can achieve smarter and more adaptable functionality.
source code analysis
Remember what we discussed earlier? At the end of the answer, we make a judgment call to determine if the current output is a function call. This process is an important part of ensuring that the system can accurately recognize and execute functions. Next, we will show the relevant source code to gain a deeper understanding of the exact implementation of this mechanism:
if (isToolCall(chatResponse,
(ChatCompletionFinishReason.TOOL_CALLS.name(), ()))) {
var toolCallConversation = handleToolCalls(prompt, chatResponse);
// Recursively call the call method with the tool call message
// conversation that contains the call responses.
return (new Prompt(toolCallConversation, ()));
}
I have also set a breakpoint here so that you can clearly see the process. This breakpoint helps us to confirm that the results returned are generated entirely by the AI. Based on this, we make further judgments to decide whether we need to call the function tool or not.
Next, we will move on to the function call. This step is crucial because the return value of the function will be provided to the AI again as a reference for subsequent answers. Let's take a look at exactly how the function call is made. Although I have found the source code for this, I will provide a visualization to make the process easier to understand. This image will clearly show the flow of the function call and how the return value is incorporated into the AI's answer.
The reason for sending these parameters is that the restrictions have been set at the time of initiating the request. Below are the request parameters that I have intercepted:
tools=[FunctionTool[type=FUNCTION, function=Function[description=Get weather conditions for a specified location, name=CurrentWeather, parameters={$schema=/draft/2020-12/schema, type=object, properties={location={type=string}, unit={type=string, enum=[C, F]}}}]]]
Almost all third-party AI interfaces currently offer a program calledtools
parameter for passing the parameters we need. Take OpenAI as an example:
Call Function Interface
Since our function implements the@FunctionalInterface
interface, so thecall
This line will actually call our definedapply
interface. Given that our parameter is an entity record, the system will transform and encapsulate it in JSON and call it later. The process is shown below:
public String call(String functionArguments) {
// Convert the tool calls JSON arguments into a Java function request object.
I request = fromJson(functionArguments, inputType);
// extend conversation with function response.
return ().apply(request);
}
Therefore, even after all operations have been completed, if the tool still needs to be invoked in the next AI judgment, the system will continue to loop until all questions have been answered in full. This design ensures the consistency and integrity of the entire process.
summarize
In this discussion, we dig deeper into how Spring AI framework can be perfectly integrated with Java programs to enhance business capabilities. As AI technology continues to evolve, its integration in Java applications has become key to improving development efficiency and user experience. We not only analyzed the mapping and control of entity classes, but also explored the power of function callbacks, showing how these complex interactions can be handled effectively with Spring AI.
Hopefully, these analytics have inspired you to think about AI applications and motivated you to be bold in your own projects and incorporate AI technology into your business processes. We look forward to seeing your ideas realized and applied in the future!
Finish Spreading Flowers! This concludes a series of source code analyses on Spring AI, and I'll continue to bring you analyses in the future if there are still starting points of interest!
I'm Rain, a Java server-side coder, studying the mysteries of AI technology. I love technical communication and sharing, and I am passionate about open source community. I am also a Tencent Cloud Creative Star, Ali Cloud Expert Blogger, Huawei Cloud Enjoyment Expert, and Nuggets Excellent Author.
💡 I won't be shy about sharing my personal explorations and experiences on the path of technology, in the hope that I can bring some inspiration and help to your learning and growth.
🌟 Welcome to the effortless drizzle! 🌟