Skip to content

Commit ed4e759

Browse files
committed
minor improvements
Signed-off-by: Christian Tzolov <[email protected]>
1 parent cda3371 commit ed4e759

File tree

9 files changed

+35
-29
lines changed

9 files changed

+35
-29
lines changed

models/spring-ai-anthropic/src/test/java/org/springframework/ai/anthropic/client/AnthropicChatClientIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ void listOutputConverterBean2() {
124124

125125
// @formatter:off
126126
List<ActorsFilms> actorsFilms = ChatClient.create(this.chatModel).prompt()
127-
.advisors(AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT)
127+
.advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT)
128128
.options(AnthropicChatOptions.builder()
129129
.model(AnthropicApi.ChatModel.CLAUDE_SONNET_4_5)
130130
.build())

models/spring-ai-openai/src/test/java/org/springframework/ai/openai/chat/client/OpenAiChatClientIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ void beanOutputConverterNativeStructuredOutput() {
200200

201201
// @formatter:off
202202
ActorsFilms actorsFilms = ChatClient.create(this.chatModel).prompt()
203-
.advisors(AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT)
203+
.advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT)
204204
.user("Generate the filmography for a random actor.")
205205
.call()
206206
.entity(ActorsFilms.class);
@@ -230,7 +230,7 @@ void beanOutputConverterRecordsNativeStructuredOutput() {
230230

231231
// @formatter:off
232232
ActorsFilms actorsFilms = ChatClient.create(this.chatModel).prompt()
233-
.advisors(AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT)
233+
.advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT)
234234
.user("Generate the filmography of 5 movies for Tom Hanks.")
235235
.call()
236236
.entity(ActorsFilms.class);

models/spring-ai-vertex-ai-gemini/src/test/java/org/springframework/ai/vertexai/gemini/VertexAiGeminiChatModelIT.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ void listOutputConverterBean2() {
243243

244244
// @formatter:off
245245
List<ActorsFilmsRecord> actorsFilms = ChatClient.create(this.chatModel).prompt()
246-
.advisors(AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT)
246+
.advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT)
247247
.user("Generate the filmography of 5 movies for Tom Hanks and Bill Murray.")
248248
.call()
249249
.entity(new ParameterizedTypeReference<>() {
@@ -259,7 +259,7 @@ void chatClientBeanOutputConverterRecords2() {
259259
var chatClient = ChatClient.builder(this.chatModel).build();
260260

261261
ActorsFilmsRecord actorsFilms = chatClient.prompt("Generate the filmography of 5 movies for Tom Hanks.")
262-
.advisors(AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT)
262+
.advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT)
263263
.call()
264264
.entity(ActorsFilmsRecord.class);
265265

spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/AdvisorParams.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public final class AdvisorParams {
3232
private AdvisorParams() {
3333
}
3434

35-
public static final Consumer<ChatClient.AdvisorSpec> WITH_NATIVE_STRUCTURED_OUTPUT = a -> a
35+
public static final Consumer<ChatClient.AdvisorSpec> ENABLE_NATIVE_STRUCTURED_OUTPUT = a -> a
3636
.param(ChatClientAttributes.STRUCTURED_OUTPUT_NATIVE.getKey(), true);
3737

3838
}

spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/DefaultChatClient.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -475,15 +475,20 @@ public <T> T entity(Class<T> type) {
475475

476476
@Nullable
477477
private <T> T doSingleWithBeanOutputConverter(StructuredOutputConverter<T> outputConverter) {
478-
if (outputConverter != null && StringUtils.hasText(outputConverter.getFormat())) {
478+
479+
if (StringUtils.hasText(outputConverter.getFormat())) {
480+
// Used for default struectured output format support, based on prompt
481+
// instructions.
479482
this.request.context().put(ChatClientAttributes.OUTPUT_FORMAT.getKey(), outputConverter.getFormat());
483+
}
484+
485+
if (this.request.context().containsKey(ChatClientAttributes.STRUCTURED_OUTPUT_NATIVE.getKey())
486+
&& outputConverter instanceof BeanOutputConverter beanOutputConverter) {
487+
// Used for native structured output support, e.g. AI model API shoudl
488+
// provide structured output support.
489+
this.request.context()
490+
.put(ChatClientAttributes.STRUCTURED_OUTPUT_SCHEMA.getKey(), beanOutputConverter.getJsonSchema());
480491

481-
if (this.request.context().containsKey(ChatClientAttributes.STRUCTURED_OUTPUT_NATIVE.getKey())
482-
&& outputConverter instanceof BeanOutputConverter beanOutputConverter) {
483-
this.request.context()
484-
.put(ChatClientAttributes.STRUCTURED_OUTPUT_SCHEMA.getKey(),
485-
beanOutputConverter.getJsonSchema());
486-
}
487492
}
488493

489494
var chatResponse = doGetObservableChatClientResponse(this.request).chatResponse();

spring-ai-client-chat/src/main/java/org/springframework/ai/chat/client/advisor/ChatModelCallAdvisor.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,23 @@ public ChatClientResponse adviseCall(ChatClientRequest chatClientRequest, CallAd
6262
}
6363

6464
private static ChatClientRequest augmentWithFormatInstructions(ChatClientRequest chatClientRequest) {
65+
6566
String outputFormat = (String) chatClientRequest.context().get(ChatClientAttributes.OUTPUT_FORMAT.getKey());
6667

67-
if (!StringUtils.hasText(outputFormat)) {
68+
String outputSchema = (String) chatClientRequest.context()
69+
.get(ChatClientAttributes.STRUCTURED_OUTPUT_SCHEMA.getKey());
70+
71+
if (!StringUtils.hasText(outputFormat) && !StringUtils.hasText(outputSchema)) {
6872
return chatClientRequest;
6973
}
7074

71-
if (chatClientRequest.prompt().getOptions() instanceof StructuredOutputChatOptions structuredOutputChatOptions
72-
&& chatClientRequest.context().containsKey(ChatClientAttributes.STRUCTURED_OUTPUT_NATIVE.getKey())) {
75+
if (chatClientRequest.context().containsKey(ChatClientAttributes.STRUCTURED_OUTPUT_NATIVE.getKey())
76+
&& StringUtils.hasText(outputSchema) && chatClientRequest.prompt()
77+
.getOptions() instanceof StructuredOutputChatOptions structuredOutputChatOptions) {
7378

74-
String outputSchema = (String) chatClientRequest.context()
75-
.get(ChatClientAttributes.STRUCTURED_OUTPUT_SCHEMA.getKey());
79+
structuredOutputChatOptions.setOutputSchema(outputSchema);
7680

77-
if (StringUtils.hasText(outputSchema)) {
78-
structuredOutputChatOptions.setOutputSchema(outputSchema);
79-
return chatClientRequest;
80-
}
81+
return chatClientRequest;
8182
}
8283

8384
Prompt augmentedPrompt = chatClientRequest.prompt()

spring-ai-client-chat/src/test/java/org/springframework/ai/chat/client/ChatClientNativeStructuredResponseTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public void nativeEntityTest() {
111111
.build()
112112
.prompt()
113113
.options(this.structuredOutputChatOptions)
114-
.advisors(AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT)
114+
.advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT)
115115
.advisors(textCallAdvisor)
116116
.user("Tell me about John")
117117
.call()

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/chatclient.adoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,13 +285,13 @@ List<ActorFilms> actorFilms = chatClient.prompt()
285285

286286
==== Native Structured Output
287287

288-
As more AI models support structured output natively, you can take advantage of this feature by using the `AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT` advisor parameter when calling the `ChatClient`.
288+
As more AI models support structured output natively, you can take advantage of this feature by using the `AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT` advisor parameter when calling the `ChatClient`.
289289
You can use the `defaultAdvisors()` method on the `ChatClient.Builder` to set this parameter globally for all calls or set it per call as shown below:
290290

291291
[source,java]
292292
----
293293
ActorFilms actorFilms = chatClient.prompt()
294-
.advisors(AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT)
294+
.advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT)
295295
.user("Generate the filmography for a random actor.")
296296
.call()
297297
.entity(ActorFilms.class);

spring-ai-docs/src/main/antora/modules/ROOT/pages/api/structured-output-converter.adoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Generating structured outputs from Large Language Models (LLMs) using generic co
1414

1515
Before the LLM call, the converter appends format instructions to the prompt, providing explicit guidance to the models on generating the desired output structure. These instructions act as a blueprint, shaping the model's response to conform to the specified format.
1616

17-
NOTE: As more AI models natively support structured outputs, you can leverage this capability using the xref:api/chatclient.adoc#_native_structured_output[Native Structured Output] feature with `AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT`. This approach uses the generated JSON schema directly with the model's native structured output API, eliminating the need for pre-prompt formatting instructions and providing more reliable results.
17+
NOTE: As more AI models natively support structured outputs, you can leverage this capability using the xref:api/chatclient.adoc#_native_structured_output[Native Structured Output] feature with `AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT`. This approach uses the generated JSON schema directly with the model's native structured output API, eliminating the need for pre-prompt formatting instructions and providing more reliable results.
1818

1919
After the LLM call, the converter takes the model's output text and transforms it into instances of the structured type. This conversion process involves parsing the raw text output and mapping it to the corresponding structured data representation, such as JSON, XML, or domain-specific data structures.
2020

@@ -264,12 +264,12 @@ When using native structured output, the JSON schema generated by `BeanOutputCon
264264

265265
=== Using Native Structured Output
266266

267-
To enable native structured output, use the `AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT` parameter:
267+
To enable native structured output, use the `AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT` parameter:
268268

269269
[source,java]
270270
----
271271
ActorsFilms actorsFilms = ChatClient.create(chatModel).prompt()
272-
.advisors(AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT)
272+
.advisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT)
273273
.user("Generate the filmography for a random actor.")
274274
.call()
275275
.entity(ActorsFilms.class);
@@ -282,7 +282,7 @@ You can also set this globally using `defaultAdvisors()` on the `ChatClient.Buil
282282
@Bean
283283
ChatClient chatClient(ChatClient.Builder builder) {
284284
return builder
285-
.defaultAdvisors(AdvisorParams.WITH_NATIVE_STRUCTURED_OUTPUT)
285+
.defaultAdvisors(AdvisorParams.ENABLE_NATIVE_STRUCTURED_OUTPUT)
286286
.build();
287287
}
288288
----

0 commit comments

Comments
 (0)