Skip to content

Commit c6db0ac

Browse files
sdeleuzeleijendary
authored andcommitted
Kotlin updates (spring-projects#2006)
* Update Kotlin documentation This commit updates the Kotlin documentation to showcase the new Kotlin reflection capabilities allowing to identify required properties. * Update Kotlin integration tests This commit updates the Kotlin integration tests to leverage the new Kotlin reflection capabilities allowing to identify required properties. It also adds a missing jackson-module-kotlin dependency and refine test implementation to be closer to the Java ones and use more idiomatic Kotlin code. Signed-off-by: leijendary <[email protected]>
1 parent 3d46e13 commit c6db0ac

File tree

5 files changed

+26
-25
lines changed

5 files changed

+26
-25
lines changed

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -376,14 +376,14 @@ Kotlin::
376376
[source,kotlin]
377377
----
378378
data class MathReasoning(
379-
@get:JsonProperty(required = true, value = "steps") val steps: Steps,
380-
@get:JsonProperty(required = true, value = "final_answer") val finalAnswer: String) {
379+
val steps: Steps,
380+
@get:JsonProperty(value = "final_answer") val finalAnswer: String) {
381381
382-
data class Steps(@get:JsonProperty(required = true, value = "items") val items: Array<Items>) {
382+
data class Steps(val items: Array<Items>) {
383383
384384
data class Items(
385-
@get:JsonProperty(required = true, value = "explanation") val explanation: String,
386-
@get:JsonProperty(required = true, value = "output") val output: String)
385+
val explanation: String,
386+
val output: String)
387387
}
388388
}
389389
@@ -405,9 +405,7 @@ val mathReasoning = outputConverter.convert(content)
405405
======
406406
--
407407

408-
NOTE: Ensure you use the `@JsonProperty(required = true,...)` annotation (`@get:JsonProperty(required = true,...)` with Kotlin in order to generate the annotation on the related getters, see link:https://kotlinlang.org/docs/annotations.html#annotation-use-site-targets[related documentation]).
409-
This is crucial for generating a schema that accurately marks fields as `required`.
410-
Although this is optional for JSON Schema, OpenAI link:https://platform.openai.com/docs/guides/structured-outputs/all-fields-must-be-required[mandates] it for the structured response to function correctly.
408+
NOTE: Although this is optional for JSON Schema, OpenAI link:https://platform.openai.com/docs/guides/structured-outputs/all-fields-must-be-required#all-fields-must-be-required[mandates] required fields for the structured response to function correctly. Kotlin reflection is used to infer which property are required or not based on the nullability of types and default values of parameters, so for most use case `@get:JsonProperty(required = true)` is not needed. `@get:JsonProperty(value = "custom_name")` can be useful to customize the property name. Make sure to generate the annotation on the related getters with this `@get:` syntax, see link:https://kotlinlang.org/docs/annotations.html#annotation-use-site-targets[related documentation].
411409

412410
==== Configuring via Application Properties
413411

spring-ai-spring-boot-autoconfigure/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,12 @@
586586
<scope>test</scope>
587587
</dependency>
588588

589+
<dependency>
590+
<groupId>com.fasterxml.jackson.module</groupId>
591+
<artifactId>jackson-module-kotlin</artifactId>
592+
<scope>test</scope>
593+
</dependency>
594+
589595
</dependencies>
590596

591597
</project>

spring-ai-spring-boot-autoconfigure/src/test/kotlin/org/springframework/ai/autoconfigure/ollama/tool/FunctionCallbackContextKotlinIT.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class FunctionCallbackResolverKotlinIT : BaseOllamaIT() {
3939

4040
companion object {
4141

42-
private val MODEL_NAME = OllamaModel.LLAMA3_2.getName();
42+
private val MODEL_NAME = "qwen2.5:3b";
4343

4444
@JvmStatic
4545
@BeforeAll
@@ -72,7 +72,7 @@ class FunctionCallbackResolverKotlinIT : BaseOllamaIT() {
7272
val response = chatModel
7373
.call(Prompt(listOf(userMessage), OllamaOptions.builder().function("weatherInfo").build()))
7474

75-
logger.info("Response: " + response)
75+
logger.info("Response: $response")
7676

7777
assertThat(response.getResult().output.text).contains("30", "10", "15")
7878
}
@@ -93,10 +93,11 @@ class FunctionCallbackResolverKotlinIT : BaseOllamaIT() {
9393
.build()
9494

9595
val response = chatModel.call(Prompt(listOf(userMessage), functionOptions));
96+
val output = response.getResult().output.text
9697

97-
logger.info("Response: " + response.getResult().getOutput().getText());
98+
logger.info("Response: $output");
9899

99-
assertThat(response.getResult().output.text).contains("30", "10", "15");
100+
assertThat(output).contains("30", "10", "15");
100101
}
101102
}
102103

spring-ai-spring-boot-autoconfigure/src/test/kotlin/org/springframework/ai/autoconfigure/ollama/tool/FunctionCallbackKotlinIT.kt

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import org.springframework.ai.chat.prompt.Prompt
2828
import org.springframework.ai.model.function.FunctionCallback
2929
import org.springframework.ai.model.function.FunctionCallingOptions
3030
import org.springframework.ai.ollama.OllamaChatModel
31-
import org.springframework.ai.ollama.api.OllamaModel
3231
import org.springframework.ai.ollama.api.OllamaOptions
3332
import org.springframework.boot.autoconfigure.AutoConfigurations
3433
import org.springframework.boot.test.context.runner.ApplicationContextRunner
@@ -39,7 +38,7 @@ class FunctionCallbackKotlinIT : BaseOllamaIT() {
3938

4039
companion object {
4140

42-
private val MODEL_NAME = OllamaModel.LLAMA3_2.getName();
41+
private val MODEL_NAME = "qwen2.5:3b";
4342

4443
@JvmStatic
4544
@BeforeAll
@@ -72,7 +71,7 @@ class FunctionCallbackKotlinIT : BaseOllamaIT() {
7271
val response = chatModel
7372
.call(Prompt(listOf(userMessage), OllamaOptions.builder().function("WeatherInfo").build()))
7473

75-
logger.info("Response: " + response)
74+
logger.info("Response: $response")
7675

7776
assertThat(response.getResult().output.text).contains("30", "10", "15")
7877
}
@@ -93,10 +92,10 @@ class FunctionCallbackKotlinIT : BaseOllamaIT() {
9392
.build()
9493

9594
val response = chatModel.call(Prompt(listOf(userMessage), functionOptions));
95+
val output = response.getResult().output.text
96+
logger.info("Response: $output");
9697

97-
logger.info("Response: " + response.getResult().getOutput().getText());
98-
99-
assertThat(response.getResult().output.text).contains("30", "10", "15");
98+
assertThat(output).contains("30", "10", "15");
10099
}
101100
}
102101

spring-ai-spring-boot-autoconfigure/src/test/kotlin/org/springframework/ai/autoconfigure/ollama/tool/MockKotlinWeatherService.kt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,16 @@ enum class Unit(val unitName: String) {
6161
@JsonInclude(Include.NON_NULL)
6262
@JsonClassDescription("Weather API request")
6363
data class KotlinRequest(
64-
@get:JsonProperty(required = true, value = "location")
64+
6565
@get:JsonPropertyDescription("The city and state e.g. San Francisco, CA")
66-
val location: String = "",
66+
val location: String,
6767

68-
@get:JsonProperty(required = true, value = "lat")
6968
@get:JsonPropertyDescription("The city latitude")
70-
val lat: Double = 0.0,
69+
val lat: Double,
7170

72-
@get:JsonProperty(required = true, value = "lon")
7371
@get:JsonPropertyDescription("The city longitude")
74-
val lon: Double = 0.0,
72+
val lon: Double,
7573

76-
@get:JsonProperty(required = true, value = "unit")
7774
@get:JsonPropertyDescription("Temperature unit")
7875
val unit: Unit = Unit.C
7976
)

0 commit comments

Comments
 (0)