Skip to content

Commit e7cc3ae

Browse files
committed
chore: support the new genai endpoint format
1 parent d93426c commit e7cc3ae

File tree

6 files changed

+118
-6
lines changed

6 files changed

+118
-6
lines changed

java-cfenv-boot/src/main/java/io/pivotal/cfenv/spring/boot/GenAIChatCfEnvProcessor.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,18 @@
2828
*
2929
* @author Stuart Charlton
3030
* @author Ed King
31+
* @author Gareth Evans
3132
**/
3233
public class GenAIChatCfEnvProcessor implements CfEnvProcessor {
3334

3435
@Override
3536
public boolean accept(CfService service) {
3637
boolean isGenAIService = service.existsByTagIgnoreCase("genai") || service.existsByLabelStartsWith("genai");
3738
if (isGenAIService) {
39+
boolean endpointFormat = service.getCredentials().getMap().containsKey("endpoint");
40+
if (endpointFormat) {
41+
return true;
42+
}
3843
ArrayList<String> modelCapabilities = (ArrayList<String>) service.getCredentials().getMap().get("model_capabilities");
3944
return modelCapabilities.contains("chat");
4045
}
@@ -46,9 +51,17 @@ public boolean accept(CfService service) {
4651
public void process(CfCredentials cfCredentials, Map<String, Object> properties) {
4752
properties.put("spring.ai.openai.api-key", "redundant");
4853

49-
properties.put("spring.ai.openai.chat.base-url", cfCredentials.getString("api_base"));
50-
properties.put("spring.ai.openai.chat.api-key", cfCredentials.getString("api_key"));
51-
properties.put("spring.ai.openai.chat.options.model", cfCredentials.getString("model_name"));
54+
boolean endpointFormat = cfCredentials.getMap().containsKey("endpoint");
55+
if (endpointFormat) {
56+
Map<String, String> endpoint = (Map<String, String>)cfCredentials.getMap().get("endpoint");
57+
properties.put("spring.ai.openai.chat.base-url", endpoint.get("api_base") + "/openai");
58+
properties.put("spring.ai.openai.chat.api-key", endpoint.get("api_key"));
59+
properties.put("spring.ai.openai.chat.options.model", "tanzu://chat");
60+
} else {
61+
properties.put("spring.ai.openai.chat.base-url", cfCredentials.getString("api_base"));
62+
properties.put("spring.ai.openai.chat.api-key", cfCredentials.getString("api_key"));
63+
properties.put("spring.ai.openai.chat.options.model", cfCredentials.getString("model_name"));
64+
}
5265
}
5366

5467
@Override

java-cfenv-boot/src/main/java/io/pivotal/cfenv/spring/boot/GenAIEmbeddingCfEnvProcessor.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,18 @@
2828
*
2929
* @author Stuart Charlton
3030
* @author Ed King
31+
* @author Gareth Evans
3132
**/
3233
public class GenAIEmbeddingCfEnvProcessor implements CfEnvProcessor {
3334

3435
@Override
3536
public boolean accept(CfService service) {
3637
boolean isGenAIService = service.existsByTagIgnoreCase("genai") || service.existsByLabelStartsWith("genai");
3738
if (isGenAIService) {
39+
boolean endpointFormat = service.getCredentials().getMap().containsKey("endpoint");
40+
if (endpointFormat) {
41+
return true;
42+
}
3843
ArrayList<String> modelCapabilities = (ArrayList<String>) service.getCredentials().getMap().get("model_capabilities");
3944
return modelCapabilities.contains("embedding");
4045
}
@@ -46,9 +51,17 @@ public boolean accept(CfService service) {
4651
public void process(CfCredentials cfCredentials, Map<String, Object> properties) {
4752
properties.put("spring.ai.openai.api-key", "redundant");
4853

49-
properties.put("spring.ai.openai.embedding.base-url", cfCredentials.getString("api_base"));
50-
properties.put("spring.ai.openai.embedding.api-key", cfCredentials.getString("api_key"));
51-
properties.put("spring.ai.openai.embedding.options.model", cfCredentials.getString("model_name"));
54+
boolean endpointFormat = cfCredentials.getMap().containsKey("endpoint");
55+
if (endpointFormat) {
56+
Map<String, String> endpoint = (Map<String, String>)cfCredentials.getMap().get("endpoint");
57+
properties.put("spring.ai.openai.embedding.base-url", endpoint.get("api_base") + "/openai");
58+
properties.put("spring.ai.openai.embedding.api-key", endpoint.get("api_key"));
59+
properties.put("spring.ai.openai.embedding.options.model", "tanzu://embedding");
60+
} else {
61+
properties.put("spring.ai.openai.embedding.base-url", cfCredentials.getString("api_base"));
62+
properties.put("spring.ai.openai.embedding.api-key", cfCredentials.getString("api_key"));
63+
properties.put("spring.ai.openai.embedding.options.model", cfCredentials.getString("model_name"));
64+
}
5265
}
5366

5467
@Override

java-cfenv-boot/src/test/java/io/pivotal/cfenv/spring/boot/GenAIChatCfEnvProcessorTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
/**
2525
* @author Stuart Charlton
2626
* @author Ed King
27+
* @author Gareth Evans
2728
*/
2829
public class GenAIChatCfEnvProcessorTests extends AbstractCfEnvTests {
2930

@@ -48,4 +49,26 @@ public void testGenAIBootPropertiesWithChatModelCapability() {
4849
assertThat(getEnvironment().getProperty("spring.ai.openai.audio.transcription.options.model")).isNull();
4950
assertThat(getEnvironment().getProperty("spring.ai.openai.audio.speech.options.model")).isNull();
5051
}
52+
53+
@Test
54+
public void testGenAIBootPropertiesWithChatModelCapabilityEndpointFormat() {
55+
String TEST_GENAI_JSON_FILE = "test-genai-endpoint-chat-model.json";
56+
57+
String EXPECTED_URI_FROM_JSON_FILE = "https://genai-proxy.tpcf.io/test/openai";
58+
String EXPECTED_TOKEN_FROM_JSON_FILE = "sk-KW5kiNOKDd_1dFxsAjpVa";
59+
String EXPECTED_MODEL_FROM_JSON_FILE = "tanzu://chat";
60+
61+
mockVcapServices(getServicesPayload(readTestDataFile(TEST_GENAI_JSON_FILE)));
62+
63+
assertThat(getEnvironment().getProperty("spring.ai.openai.api-key")).isEqualTo("redundant");
64+
65+
assertThat(getEnvironment().getProperty("spring.ai.openai.chat.base-url")).isEqualTo(EXPECTED_URI_FROM_JSON_FILE);
66+
assertThat(getEnvironment().getProperty("spring.ai.openai.chat.api-key")).isEqualTo(EXPECTED_TOKEN_FROM_JSON_FILE);
67+
assertThat(getEnvironment().getProperty("spring.ai.openai.chat.options.model")).isEqualTo(EXPECTED_MODEL_FROM_JSON_FILE);
68+
69+
assertThat(getEnvironment().getProperty("spring.ai.openai.embedding.options.model")).isNotNull();
70+
assertThat(getEnvironment().getProperty("spring.ai.openai.image.options.model")).isNull();
71+
assertThat(getEnvironment().getProperty("spring.ai.openai.audio.transcription.options.model")).isNull();
72+
assertThat(getEnvironment().getProperty("spring.ai.openai.audio.speech.options.model")).isNull();
73+
}
5174
}

java-cfenv-boot/src/test/java/io/pivotal/cfenv/spring/boot/GenAIEmbeddingCfEnvProcessorTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
/**
2525
* @author Stuart Charlton
2626
* @author Ed King
27+
* @author Gareth Evans
2728
*/
2829
public class GenAIEmbeddingCfEnvProcessorTests extends AbstractCfEnvTests {
2930

@@ -48,4 +49,26 @@ public void testGenAIBootPropertiesWithEmbeddingModelCapability() {
4849
assertThat(getEnvironment().getProperty("spring.ai.openai.audio.transcription.options.model")).isNull();
4950
assertThat(getEnvironment().getProperty("spring.ai.openai.audio.speech.options.model")).isNull();
5051
}
52+
53+
@Test
54+
public void testGenAIBootPropertiesWithEmbeddingModelCapabilityEndpointFormat() {
55+
String TEST_GENAI_JSON_FILE = "test-genai-endpoint-embedding-model.json";
56+
57+
String EXPECTED_URI_FROM_JSON_FILE = "https://genai-proxy.tpcf.io/test/openai";
58+
String EXPECTED_TOKEN_FROM_JSON_FILE = "sk-KW5kiNOKDd_1dFxsAjpVa";
59+
String EXPECTED_MODEL_FROM_JSON_FILE = "tanzu://embedding";
60+
61+
mockVcapServices(getServicesPayload(readTestDataFile(TEST_GENAI_JSON_FILE)));
62+
63+
assertThat(getEnvironment().getProperty("spring.ai.openai.api-key")).isEqualTo("redundant");
64+
65+
assertThat(getEnvironment().getProperty("spring.ai.openai.embedding.base-url")).isEqualTo(EXPECTED_URI_FROM_JSON_FILE);
66+
assertThat(getEnvironment().getProperty("spring.ai.openai.embedding.api-key")).isEqualTo(EXPECTED_TOKEN_FROM_JSON_FILE);
67+
assertThat(getEnvironment().getProperty("spring.ai.openai.embedding.options.model")).isEqualTo(EXPECTED_MODEL_FROM_JSON_FILE);
68+
69+
assertThat(getEnvironment().getProperty("spring.ai.openai.chat.options.model")).isNotNull();
70+
assertThat(getEnvironment().getProperty("spring.ai.openai.image.options.model")).isNull();
71+
assertThat(getEnvironment().getProperty("spring.ai.openai.audio.transcription.options.model")).isNull();
72+
assertThat(getEnvironment().getProperty("spring.ai.openai.audio.speech.options.model")).isNull();
73+
}
5174
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"credentials": {
3+
"endpoint": {
4+
"api_base": "https://genai-proxy.tpcf.io/test",
5+
"api_key": "sk-KW5kiNOKDd_1dFxsAjpVa",
6+
"config_url": "https://genai-proxy.tpcf.io/test/config/v1/endpoint"
7+
}
8+
},
9+
"instance_name": "genai",
10+
"label": "genai",
11+
"name": "genai",
12+
"plan": "meta-llama/Meta-Llama-3-8B",
13+
"provider": null,
14+
"syslog_drain_url": null,
15+
"tags": [
16+
"genai",
17+
"llm"
18+
],
19+
"volume_mounts": []
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"credentials": {
3+
"endpoint": {
4+
"api_base": "https://genai-proxy.tpcf.io/test",
5+
"api_key": "sk-KW5kiNOKDd_1dFxsAjpVa",
6+
"config_url": "https://genai-proxy.tpcf.io/test/config/v1/endpoint"
7+
}
8+
},
9+
"instance_name": "genai",
10+
"label": "genai",
11+
"name": "genai",
12+
"plan": "mixedbread-ai/mxbai-embed-large-v1",
13+
"provider": null,
14+
"syslog_drain_url": null,
15+
"tags": [
16+
"genai",
17+
"llm"
18+
],
19+
"volume_mounts": []
20+
}

0 commit comments

Comments
 (0)