Skip to content

Commit ad89753

Browse files
committed
fix: use the same schema generation dependency as in orchestration module
1 parent 9d3684d commit ad89753

File tree

4 files changed

+45
-31
lines changed

4 files changed

+45
-31
lines changed

foundation-models/openai/pom.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,12 @@
7878
<artifactId>jackson-annotations</artifactId>
7979
</dependency>
8080
<dependency>
81-
<groupId>com.fasterxml.jackson.module</groupId>
82-
<artifactId>jackson-module-jsonSchema</artifactId>
81+
<groupId>com.github.victools</groupId>
82+
<artifactId>jsonschema-generator</artifactId>
83+
</dependency>
84+
<dependency>
85+
<groupId>com.github.victools</groupId>
86+
<artifactId>jsonschema-module-jackson</artifactId>
8387
</dependency>
8488
<dependency>
8589
<groupId>io.vavr</groupId>

foundation-models/openai/src/main/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiTool.java

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
import static com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionTool.TypeEnum.FUNCTION;
44

55
import com.fasterxml.jackson.core.type.TypeReference;
6-
import com.fasterxml.jackson.databind.JsonMappingException;
7-
import com.fasterxml.jackson.databind.ObjectMapper;
8-
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
9-
import com.fasterxml.jackson.module.jsonSchema.JsonSchemaGenerator;
6+
import com.github.victools.jsonschema.generator.Option;
7+
import com.github.victools.jsonschema.generator.OptionPreset;
8+
import com.github.victools.jsonschema.generator.SchemaGenerator;
9+
import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder;
10+
import com.github.victools.jsonschema.generator.SchemaVersion;
11+
import com.github.victools.jsonschema.module.jackson.JacksonModule;
12+
import com.github.victools.jsonschema.module.jackson.JacksonOption;
1013
import com.google.common.annotations.Beta;
1114
import com.sap.ai.sdk.foundationmodels.openai.generated.model.ChatCompletionTool;
1215
import com.sap.ai.sdk.foundationmodels.openai.generated.model.FunctionObject;
@@ -21,9 +24,9 @@
2124
import lombok.experimental.Accessors;
2225

2326
/**
24-
* Represents an OpenAI function tool that can be used to define a function call in an OpenAI Chat
25-
* Completion request. This tool generates a JSON schema based on the provided class representing
26-
* the function's request structure.
27+
* Represents an OpenAI tool that can be used to define a function call in an OpenAI Chat Completion
28+
* request. This tool generates a JSON schema based on the provided class representing the
29+
* function's request structure.
2730
*
2831
* @param <I> the type of the input argument for the function
2932
* @see <a href="https://platform.openai.com/docs/guides/gpt/function-calling"/>OpenAI Function
@@ -36,20 +39,23 @@
3639
@AllArgsConstructor(access = AccessLevel.PRIVATE)
3740
public class OpenAiTool<I> {
3841

42+
/** The schema generator used to create JSON schemas. */
43+
@Nonnull private static final SchemaGenerator GENERATOR = createSchemaGenerator();
44+
3945
/** The name of the function. */
40-
private @Nonnull String name;
46+
@Nonnull private String name;
4147

4248
/** The model class for function request. */
43-
private @Nonnull Class<I> requestClass;
49+
@Nonnull private Class<I> requestClass;
4450

4551
/** An optional description of the function. */
46-
private @Nullable String description;
52+
@Nullable private String description;
4753

4854
/** An optional flag indicating whether the function parameters should be treated strictly. */
49-
private @Nullable Boolean strict;
55+
@Nullable private Boolean strict;
5056

5157
/** The function to be called. */
52-
private @Nullable Function<I, ?> function;
58+
@Nullable private Function<I, ?> function;
5359

5460
/**
5561
* Constructs an {@code OpenAiFunctionTool} with the specified name and a model class that
@@ -65,22 +71,16 @@ public OpenAiTool(@Nonnull final String name, @Nonnull final Class<I> requestCla
6571
@Nonnull
6672
Object execute(@Nonnull final I argument) {
6773
if (getFunction() == null) {
68-
throw new IllegalStateException("Function must not be set to execute the tool.");
74+
throw new IllegalStateException("No function configured to execute.");
6975
}
7076
return getFunction().apply(argument);
7177
}
7278

7379
ChatCompletionTool createChatCompletionTool() {
74-
final var objectMapper = new ObjectMapper();
75-
JsonSchema schema = null;
76-
try {
77-
schema = new JsonSchemaGenerator(objectMapper).generateSchema(getRequestClass());
78-
} catch (JsonMappingException e) {
79-
throw new IllegalArgumentException("Could not generate schema for " + getRequestClass(), e);
80-
}
81-
80+
final var schema = GENERATOR.generateSchema(getRequestClass());
8281
final var schemaMap =
83-
objectMapper.convertValue(schema, new TypeReference<Map<String, Object>>() {});
82+
OpenAiUtils.getOpenAiObjectMapper()
83+
.convertValue(schema, new TypeReference<Map<String, Object>>() {});
8484

8585
final var function =
8686
new FunctionObject()
@@ -90,4 +90,15 @@ ChatCompletionTool createChatCompletionTool() {
9090
.strict(getStrict());
9191
return new ChatCompletionTool().type(FUNCTION).function(function);
9292
}
93+
94+
private static SchemaGenerator createSchemaGenerator() {
95+
final var module =
96+
new JacksonModule(
97+
JacksonOption.RESPECT_JSONPROPERTY_REQUIRED, JacksonOption.RESPECT_JSONPROPERTY_ORDER);
98+
return new SchemaGenerator(
99+
new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12, OptionPreset.PLAIN_JSON)
100+
.without(Option.SCHEMA_VERSION_INDICATOR)
101+
.with(module)
102+
.build());
103+
}
93104
}

foundation-models/openai/src/test/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiChatCompletionRequestTest.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,12 +145,11 @@ record DummyRequest(String param1, int param2) {}
145145
assertThat(toolA.getFunction().getParameters())
146146
.isEqualTo(
147147
Map.of(
148-
"id",
149-
"urn:jsonschema:com:sap:ai:sdk:foundationmodels:openai:OpenAiChatCompletionRequestTest:1DummyRequest",
150148
"properties",
151-
Map.of(
152-
"param1", Map.of("type", "string"),
153-
"param2", Map.of("type", "integer")),
154-
"type", "object"));
149+
Map.of(
150+
"param1", Map.of("type", "string"),
151+
"param2", Map.of("type", "integer")),
152+
"type",
153+
"object"));
155154
}
156155
}

foundation-models/openai/src/test/java/com/sap/ai/sdk/foundationmodels/openai/OpenAiToolTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ void executeToolsThrowsOnNoFunction() {
7575
assertThatThrownBy(
7676
() -> OpenAiToolExecutor.executeTools(List.of(toolA), List.of(functionCallA)))
7777
.isInstanceOf(IllegalStateException.class)
78-
.hasMessageContaining("Function must not be set to execute the tool");
78+
.hasMessageContaining("No function configured to execute.");
7979
}
8080

8181
@Test

0 commit comments

Comments
 (0)