Skip to content

Commit cc12f82

Browse files
Added Orchestration LLM Config Convenience
1 parent 81e7996 commit cc12f82

File tree

6 files changed

+176
-26
lines changed

6 files changed

+176
-26
lines changed

docs/guides/ORCHESTRATION_CHAT_COMPLETION.md

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ To use the Orchestration service, create a client and a configuration object:
7777
var client = new OrchestrationClient();
7878

7979
var config = new OrchestrationModuleConfig()
80-
.withLlmConfig(LLMModuleConfig.create().modelName("gpt-35-turbo").modelParams(Map.of()));
80+
.withLlmConfig(OrchestrationAiModel.GPT_4O);
8181
```
8282

8383
Please also refer to [our sample code](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java) for this and all following code examples.
@@ -218,13 +218,11 @@ In this example, the input will be masked before the call to the LLM. Note that
218218
Change your LLM module configuration to add model parameters:
219219

220220
```java
221-
var llmConfig =
222-
LLMModuleConfig.create()
223-
.modelName("gpt-35-turbo")
224-
.modelParams(
225-
Map.of(
226-
"max_tokens", 50,
227-
"temperature", 0.1,
228-
"frequency_penalty", 0,
229-
"presence_penalty", 0));
221+
LLMModuleConfig llmConfig =
222+
OrchestrationAiModel.GPT_4O.modelParams(
223+
Map.of(
224+
"max_tokens", 50,
225+
"temperature", 0.1,
226+
"frequency_penalty", 0,
227+
"presence_penalty", 0));
230228
```
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package com.sap.ai.sdk.orchestration;
2+
3+
import com.sap.ai.sdk.orchestration.client.model.LLMModuleConfig;
4+
import java.util.Map;
5+
import javax.annotation.Nonnull;
6+
7+
/** Large language models available in Orchestration. */
8+
// https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/models-and-scenarios-in-generative-ai-hub
9+
@SuppressWarnings("unused") // tested in OrchestrationTest.orchestrationModelAvailability()
10+
public class OrchestrationAiModel extends LLMModuleConfig {
11+
12+
/** IBM Granite 13B chat completions model */
13+
public static final OrchestrationAiModel IBM_GRANITE_13B_CHAT =
14+
new OrchestrationAiModel("ibm--granite-13b-chat");
15+
16+
/** MistralAI Mistral Large Instruct model */
17+
public static final OrchestrationAiModel MISTRAL_LARGE_INSTRUCT =
18+
new OrchestrationAiModel("mistralai--mistral-large-instruct");
19+
20+
/** MistralAI Mixtral 8x7B Instruct v01 model */
21+
public static final OrchestrationAiModel MIXTRAL_8X7B_INSTRUCT_V01 =
22+
new OrchestrationAiModel("mistralai--mixtral-8x7b-instruct-v01");
23+
24+
/** Meta Llama3 70B Instruct model */
25+
public static final OrchestrationAiModel LLAMA3_70B_INSTRUCT =
26+
new OrchestrationAiModel("meta--llama3-70b-instruct");
27+
28+
/** Meta Llama3.1 70B Instruct model */
29+
public static final OrchestrationAiModel LLAMA3_1_70B_INSTRUCT =
30+
new OrchestrationAiModel("meta--llama3.1-70b-instruct");
31+
32+
/** Anthropic Claude 3 Sonnet model */
33+
public static final OrchestrationAiModel CLAUDE_3_SONNET =
34+
new OrchestrationAiModel("anthropic--claude-3-sonnet");
35+
36+
/** Anthropic Claude 3 Haiku model */
37+
public static final OrchestrationAiModel CLAUDE_3_HAIKU =
38+
new OrchestrationAiModel("anthropic--claude-3-haiku");
39+
40+
/** Anthropic Claude 3 Opus model */
41+
public static final OrchestrationAiModel CLAUDE_3_OPUS =
42+
new OrchestrationAiModel("anthropic--claude-3-opus");
43+
44+
/** Anthropic Claude 3.5 Sonnet model */
45+
public static final OrchestrationAiModel CLAUDE_3_5_SONNET =
46+
new OrchestrationAiModel("anthropic--claude-3.5-sonnet");
47+
48+
/** Amazon Titan Embed Text model */
49+
public static final OrchestrationAiModel TITAN_EMBED_TEXT =
50+
new OrchestrationAiModel("amazon--titan-embed-text");
51+
52+
/** Amazon Titan Text Lite model */
53+
public static final OrchestrationAiModel TITAN_TEXT_LITE =
54+
new OrchestrationAiModel("amazon--titan-text-lite");
55+
56+
/** Amazon Titan Text Express model */
57+
public static final OrchestrationAiModel TITAN_TEXT_EXPRESS =
58+
new OrchestrationAiModel("amazon--titan-text-express");
59+
60+
/** Azure OpenAI GPT-3.5 Turbo chat completions model */
61+
public static final OrchestrationAiModel GPT_35_TURBO = new OrchestrationAiModel("gpt-35-turbo");
62+
63+
/** Azure OpenAI GPT-3.5 Turbo chat completions model */
64+
public static final OrchestrationAiModel GPT_35_TURBO_16K =
65+
new OrchestrationAiModel("gpt-35-turbo-16k");
66+
67+
/** Azure OpenAI GPT-4 chat completions model */
68+
public static final OrchestrationAiModel GPT_4 = new OrchestrationAiModel("gpt-4");
69+
70+
/** Azure OpenAI GPT-4-32k chat completions model */
71+
public static final OrchestrationAiModel GPT_4_32K = new OrchestrationAiModel("gpt-4-32k");
72+
73+
/** Azure OpenAI Text Embedding Ada 002 model */
74+
public static final OrchestrationAiModel TEXT_EMBEDDING_ADA_002 =
75+
new OrchestrationAiModel("text-embedding-ada-002");
76+
77+
/** Azure OpenAI Text Embedding 3 Small model */
78+
public static final OrchestrationAiModel TEXT_EMBEDDING_3_SMALL =
79+
new OrchestrationAiModel("text-embedding-3-small");
80+
81+
/** Azure OpenAI Text Embedding 3 Large model */
82+
public static final OrchestrationAiModel TEXT_EMBEDDING_3_LARGE =
83+
new OrchestrationAiModel("text-embedding-3-large");
84+
85+
/** Azure OpenAI GPT-4o chat completions model */
86+
public static final OrchestrationAiModel GPT_4O = new OrchestrationAiModel("gpt-4o");
87+
88+
/** Azure OpenAI GPT-4o-mini chat completions model */
89+
public static final OrchestrationAiModel GPT_4O_MINI = new OrchestrationAiModel("gpt-4o-mini");
90+
91+
/** Google Cloud Platform Text Bison model */
92+
public static final OrchestrationAiModel TEXT_BISON = new OrchestrationAiModel("text-bison");
93+
94+
/** Google Cloud Platform Chat Bison model */
95+
public static final OrchestrationAiModel CHAT_BISON = new OrchestrationAiModel("chat-bison");
96+
97+
/** Google Cloud Platform Text Embedding Gecko model */
98+
public static final OrchestrationAiModel TEXT_EMBEDDING_GECKO =
99+
new OrchestrationAiModel("textembedding-gecko");
100+
101+
/** Google Cloud Platform Text Embedding Gecko Multilingual model */
102+
public static final OrchestrationAiModel TEXT_EMBEDDING_GECKO_MULTILINGUAL =
103+
new OrchestrationAiModel("textembedding-gecko-multilingual");
104+
105+
/** Google Cloud Platform Gemini 1.0 Pro model */
106+
public static final OrchestrationAiModel GEMINI_1_0_PRO =
107+
new OrchestrationAiModel("gemini-1.0-pro");
108+
109+
/** Google Cloud Platform Gemini 1.5 Pro model */
110+
public static final OrchestrationAiModel GEMINI_1_5_PRO =
111+
new OrchestrationAiModel("gemini-1.5-pro");
112+
113+
/** Google Cloud Platform Gemini 1.5 Flash model */
114+
public static final OrchestrationAiModel GEMINI_1_5_FLASH =
115+
new OrchestrationAiModel("gemini-1.5-flash");
116+
117+
OrchestrationAiModel(@Nonnull final String modelName) {
118+
setModelName(modelName);
119+
setModelParams(Map.of());
120+
}
121+
}

orchestration/src/test/java/com/sap/ai/sdk/orchestration/OrchestrationUnitTest.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,12 @@
5757
@WireMockTest
5858
class OrchestrationUnitTest {
5959
static final LLMModuleConfig LLM_CONFIG =
60-
LLMModuleConfig.create()
61-
.modelName("gpt-35-turbo-16k")
62-
.modelParams(
63-
Map.of(
64-
"max_tokens", 50,
65-
"temperature", 0.1,
66-
"frequency_penalty", 0,
67-
"presence_penalty", 0));
60+
OrchestrationAiModel.GPT_35_TURBO_16K.modelParams(
61+
Map.of(
62+
"max_tokens", 50,
63+
"temperature", 0.1,
64+
"frequency_penalty", 0,
65+
"presence_penalty", 0));
6866
private final Function<String, InputStream> fileLoader =
6967
filename -> Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream(filename));
7068

sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.sap.ai.sdk.app.controllers;
22

3+
import static com.sap.ai.sdk.orchestration.OrchestrationAiModel.GPT_35_TURBO;
4+
35
import com.sap.ai.sdk.orchestration.OrchestrationClient;
46
import com.sap.ai.sdk.orchestration.OrchestrationModuleConfig;
57
import com.sap.ai.sdk.orchestration.OrchestrationPrompt;
@@ -30,12 +32,11 @@
3032
@RestController
3133
@RequestMapping("/orchestration")
3234
class OrchestrationController {
33-
static final LLMModuleConfig LLM_CONFIG =
34-
LLMModuleConfig.create().modelName("gpt-35-turbo").modelParams(Map.of());
35+
LLMModuleConfig llmConfig = GPT_35_TURBO;
3536

3637
private final OrchestrationClient client = new OrchestrationClient();
3738
private final OrchestrationModuleConfig config =
38-
new OrchestrationModuleConfig().withLlmConfig(LLM_CONFIG);
39+
new OrchestrationModuleConfig().withLlmConfig(llmConfig);
3940

4041
/**
4142
* Chat request to OpenAI through the Orchestration service with a simple prompt.
@@ -171,7 +172,7 @@ public CompletionPostResponse maskingAnonymization() {
171172

172173
/**
173174
* Let the orchestration service a response to a hypothetical user who provided feedback on the AI
174-
* SDK. Pseydonymize the user's name and location to protect their privacy.
175+
* SDK. Pseudonymize the user's name and location to protect their privacy.
175176
*
176177
* @return the result object
177178
*/

sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/OrchestrationTest.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,22 @@
33
import static org.assertj.core.api.Assertions.assertThat;
44
import static org.assertj.core.api.Assertions.assertThatThrownBy;
55

6+
import com.sap.ai.sdk.orchestration.OrchestrationAiModel;
67
import com.sap.ai.sdk.orchestration.OrchestrationClientException;
78
import com.sap.ai.sdk.orchestration.client.model.AzureThreshold;
89
import com.sap.ai.sdk.orchestration.client.model.CompletionPostResponse;
10+
import java.lang.reflect.Field;
11+
import java.util.ArrayList;
912
import java.util.List;
1013
import java.util.Map;
14+
import lombok.SneakyThrows;
15+
import lombok.extern.slf4j.Slf4j;
1116
import org.assertj.core.api.InstanceOfAssertFactories;
1217
import org.junit.jupiter.api.BeforeEach;
18+
import org.junit.jupiter.api.DisplayName;
1319
import org.junit.jupiter.api.Test;
1420

21+
@Slf4j
1522
class OrchestrationTest {
1623
OrchestrationController controller;
1724

@@ -41,7 +48,7 @@ void testTemplate() {
4148
assertThat(llm.getId()).isNotEmpty();
4249
assertThat(llm.getObject()).isEqualTo("chat.completion");
4350
assertThat(llm.getCreated()).isGreaterThan(1);
44-
assertThat(llm.getModel()).isEqualTo(OrchestrationController.LLM_CONFIG.getModelName());
51+
assertThat(llm.getModel()).isEqualTo(controller.llmConfig.getModelName());
4552
var choices = llm.getChoices();
4653
assertThat(choices.get(0).getIndex()).isZero();
4754
assertThat(choices.get(0).getMessage().getContent()).isNotEmpty();
@@ -54,7 +61,7 @@ void testTemplate() {
5461
assertThat(result.getOrchestrationResult().getObject()).isEqualTo("chat.completion");
5562
assertThat(result.getOrchestrationResult().getCreated()).isGreaterThan(1);
5663
assertThat(result.getOrchestrationResult().getModel())
57-
.isEqualTo(OrchestrationController.LLM_CONFIG.getModelName());
64+
.isEqualTo(controller.llmConfig.getModelName());
5865
choices = result.getOrchestrationResult().getChoices();
5966
assertThat(choices.get(0).getIndex()).isZero();
6067
assertThat(choices.get(0).getMessage().getContent()).isNotEmpty();
@@ -137,4 +144,29 @@ void testMaskingPseudonymization() {
137144
.doesNotContain("MASKED_PERSON")
138145
.contains("Mallory");
139146
}
147+
148+
@Test
149+
@DisplayName("Declared OrchestrationAiModels must match Orchestration's list of available models")
150+
@SneakyThrows
151+
void orchestrationModelAvailability() {
152+
// TODO: Change this test to be like ScenarioTest.openAiModelAvailability() once the
153+
// Orchestration service has made the "available models endpoint".
154+
// Right now this test cannot tell if we are lacking models.
155+
156+
// Gather our declared Orchestration models
157+
List<OrchestrationAiModel> declaredOrchestrationModelList = new ArrayList<>();
158+
for (Field field : OrchestrationAiModel.class.getFields()) {
159+
if (field.getType().equals(OrchestrationAiModel.class)) {
160+
declaredOrchestrationModelList.add(((OrchestrationAiModel) field.get(null)));
161+
}
162+
}
163+
164+
declaredOrchestrationModelList.parallelStream()
165+
.forEach(
166+
model -> {
167+
controller.llmConfig = model;
168+
log.info("Testing completion for model: {}", model.getModelName());
169+
assertThat(controller.completion()).isNotNull();
170+
});
171+
}
140172
}

sample-code/spring-app/src/test/java/com/sap/ai/sdk/app/controllers/ScenarioTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
import org.junit.jupiter.api.DisplayName;
1212
import org.junit.jupiter.api.Test;
1313

14-
public class ScenarioTest {
14+
class ScenarioTest {
1515

1616
@Test
1717
@DisplayName("Declared OpenAI models must match AI Core's available OpenAI models")
1818
@SneakyThrows
19-
public void openAiModelAvailability() {
19+
void openAiModelAvailability() {
2020

2121
// Gather AI Core's list of available OpenAI models
2222
final var aiModelList = new ScenarioController().getModels().getResources();

0 commit comments

Comments
 (0)