This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push:
new 9992116a89 Prepare OpenAI tests for external model testing
9992116a89 is described below
commit 9992116a8926b81efbac7dcd58c7efbbcfb1a925
Author: Lukas Lowinger <[email protected]>
AuthorDate: Wed Mar 18 08:09:14 2026 +0100
Prepare OpenAI tests for external model testing
---
integration-tests/openai/README.adoc | 11 +-
.../quarkus/component/openai/it/OpenaiRoutes.java | 5 +-
.../openai/it/{OpenaiIT.java => OpenaiChatIT.java} | 2 +-
.../it/{OpenaiTest.java => OpenaiChatTest.java} | 139 +++++----------------
.../{OpenaiIT.java => OpenaiChatTestResource.java} | 16 ++-
.../component/openai/it/OpenaiEmbeddingTest.java | 136 ++++++++++++++++++++
...naiIT.java => OpenaiEmbeddingTestResource.java} | 17 ++-
.../component/openai/it/OpenaiTestResource.java | 23 ++--
...tions-04e37f50-08ea-4d43-a43e-299940f6e117.json | 4 +-
...tions-323a6828-8117-4d20-9627-72939652f6e4.json | 2 +-
...tions-45c75cdd-225c-4e51-a133-a3146fff462b.json | 4 +-
...tions-741db9c0-e3ee-4dea-a702-ea609f5a10c5.json | 2 +-
12 files changed, 220 insertions(+), 141 deletions(-)
diff --git a/integration-tests/openai/README.adoc
b/integration-tests/openai/README.adoc
index e768f03544..f619546f41 100644
--- a/integration-tests/openai/README.adoc
+++ b/integration-tests/openai/README.adoc
@@ -11,7 +11,8 @@ With access to the developer area you can create a new
project together with an
[source,shell]
----
-export OPENAI_API_KEY=your-openai-api-key
+export OPENAI_CHAT_API_KEY=<your-chat-api-key>
+export OPENAI_EMBEDDING_API_KEY=$OPENAI_CHAT_API_KEY
----
This will test with model `gpt-5` against the default API endpoint of
https://api.openai.com/v1.
@@ -22,9 +23,11 @@ Alternatively, you can test against any OpenAI compatible
API by configuring the
[source,shell]
----
-export OPENAI_API_KEY=fake-key
-export OPENAI_BASE_URL=https://you-api-endpoint/v1
-export OPENAI_MODEL=your-model-name
+export OPENAI_CHAT_API_KEY=<your-chat-api-key>
+export OPENAI_EMBEDDING_API_KEY=<your-embedding-api-key>
+export OPENAI_CHAT_BASE_URL=https://you-chat-api-endpoint/v1
+export OPENAI_EMBEDDING_BASE_URL=https://you-embedding-api-endpoint/v1
+export OPENAI_CHAT_MODEL=your-chat-model-name
export OPENAI_EMBEDDING_MODEL=your-embedding-model-name
----
diff --git
a/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/OpenaiRoutes.java
b/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/OpenaiRoutes.java
index 48fcb2ffe2..a8b16a8c13 100644
---
a/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/OpenaiRoutes.java
+++
b/integration-tests/openai/src/main/java/org/apache/camel/quarkus/component/openai/it/OpenaiRoutes.java
@@ -76,9 +76,12 @@ public class OpenaiRoutes extends RouteBuilder {
.to("seda:filePromptResults");
from("direct:chatWithMemory")
+ // limit generation of useless tokens for this scenario on
slower models
+ .setHeader("CamelOpenAIMaxTokens", constant(10))
.to("openai:chat-completion?conversationMemory=true")
.log("Chat response 1: ${body}")
- .setBody(constant("What is my Camel species?"))
+ // here we will limit it via instruction, so the model can
"reorganize" the word "John" to fit in the shorter answer
+ .setBody(constant("What is my name? Respond maximum 5 words."))
.to("openai:chat-completion?conversationMemory=true")
.log("Chat response 2: ${body}");
diff --git
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatIT.java
similarity index 95%
copy from
integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
copy to
integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatIT.java
index b30598ff66..b731008c63 100644
---
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
+++
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatIT.java
@@ -19,6 +19,6 @@ package org.apache.camel.quarkus.component.openai.it;
import io.quarkus.test.junit.QuarkusIntegrationTest;
@QuarkusIntegrationTest
-class OpenaiIT extends OpenaiTest {
+class OpenaiChatIT extends OpenaiChatTest {
}
diff --git
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTest.java
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatTest.java
similarity index 61%
rename from
integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTest.java
rename to
integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatTest.java
index 69f0aa4113..4e61080c90 100644
---
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTest.java
+++
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatTest.java
@@ -25,7 +25,6 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -37,20 +36,28 @@ import io.restassured.http.ContentType;
import io.restassured.response.Response;
import org.apache.camel.util.FileUtil;
import org.awaitility.Awaitility;
+import org.jboss.logging.Logger;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
import static org.hamcrest.Matchers.containsStringIgnoringCase;
-import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-@QuarkusTestResource(OpenaiTestResource.class)
+@QuarkusTestResource(value = OpenaiChatTestResource.class,
restrictToAnnotatedClass = true)
@QuarkusTest
-class OpenaiTest {
+class OpenaiChatTest {
+
+ private static final Logger LOG = Logger.getLogger(OpenaiChatTest.class);
+
+ @BeforeEach
+ void logTestName(TestInfo testInfo) {
+ LOG.info(String.format("Running OpenaiChatTest test %s",
testInfo.getDisplayName()));
+ }
+
@Test
void simpleChat() {
RestAssured.given()
@@ -59,14 +66,18 @@ class OpenaiTest {
.post("/openai/chat")
.then()
.statusCode(200)
- .body(containsStringIgnoringCase("integration framework"));
+ .body(containsStringIgnoringCase("camel"));
}
@Test
void chatWithImage() throws IOException {
+ Assumptions.assumeTrue(
+
OpenaiChatTestResource.OPENAI_API_URL.equals(System.getenv(OpenaiChatTestResource.OPENAI_ENV_CHAT_BASE_URL))
+ ||
System.getProperty("camel.component.openai.baseUrl") == null,
+ "Needs model which support image operations.");
Path path = Paths.get("target/camel-log.png");
- try (InputStream stream =
OpenaiTest.class.getResourceAsStream("/img/camel-logo.png")) {
+ try (InputStream stream =
OpenaiChatTest.class.getResourceAsStream("/img/camel-logo.png")) {
if (stream == null) {
throw new IllegalStateException("Failed loading
camel-logo.png");
}
@@ -101,7 +112,7 @@ class OpenaiTest {
Path prompt = prompts.resolve("whatis-camel-prompt.txt");
Files.createDirectories(prompts);
- try (InputStream stream =
OpenaiTest.class.getResourceAsStream("/prompts/whatis-camel-prompt.txt")) {
+ try (InputStream stream =
OpenaiChatTest.class.getResourceAsStream("/prompts/whatis-camel-prompt.txt")) {
if (stream == null) {
throw new IllegalStateException("Failed loading
whatis-camel-prompt.txt");
}
@@ -116,13 +127,13 @@ class OpenaiTest {
.then()
.statusCode(204);
-
Awaitility.await().pollDelay(Duration.ofSeconds(1)).atMost(Duration.ofMinutes(1)).untilAsserted(()
-> {
+
Awaitility.await().pollDelay(Duration.ofSeconds(10)).atMost(Duration.ofMinutes(1)).untilAsserted(()
-> {
RestAssured.given()
.queryParam("endpointUri", "seda:filePromptResults")
.get("/openai/chat/results")
.then()
.statusCode(200)
- .body(containsStringIgnoringCase("integration
framework"));
+ .body(containsStringIgnoringCase("camel"));
});
} finally {
// Stop the file-prompts route
@@ -144,11 +155,11 @@ class OpenaiTest {
void chatWithMemory() {
RestAssured.given()
.contentType(ContentType.TEXT)
- .body("I am a Camel and my species is Camelus Dromedarius.")
+ .body("My name is John.")
.post("/openai/chat/memory")
.then()
.statusCode(200)
- .body(containsStringIgnoringCase("Camelus Dromedarius"));
+ .body(containsStringIgnoringCase("John"));
}
@Test
@@ -156,7 +167,7 @@ class OpenaiTest {
// Send the streaming request
RestAssured.given()
.contentType(ContentType.TEXT)
- .body("Stream the numbers 1 to 10 on a new line each time and
nothing else.")
+ .body("Stream the numbers 1 to 9 on a new line each time and
nothing else.")
.post("/openai/chat/streaming")
.then()
.statusCode(204);
@@ -177,10 +188,10 @@ class OpenaiTest {
receivedNumbers.add(result.trim());
}
}
- return receivedNumbers.size() >= 10;
+ return receivedNumbers.size() >= 9;
});
- Set<String> expectedNumbers = IntStream.rangeClosed(1, 10)
+ Set<String> expectedNumbers = IntStream.rangeClosed(1, 9)
.mapToObj(String::valueOf)
.collect(Collectors.toSet());
@@ -204,103 +215,13 @@ class OpenaiTest {
void structuredOutputWithOutputClass() {
RestAssured.given()
.contentType(ContentType.TEXT)
- .body("Create an example product for a product named
'Bluetooth Headphones'.")
+ .body("Create an example product for a product named
'Bluetooth'.")
.post("/openai/chat/structured/class")
.then()
.statusCode(200)
.body(
- "name", is("Bluetooth Headphones"),
+ "name", containsStringIgnoringCase("Bluetooth"),
"price", greaterThan(0.0F));
}
- @Test
- void simpleEmbedding() {
- String simpleText = "Simple text";
- List<?> result = RestAssured.given()
- .contentType(ContentType.TEXT)
- .body(simpleText)
- .post("/openai/embeddings")
- .then()
- .statusCode(200)
- .body(".", hasSize(greaterThan(0)))
- .extract()
- .body()
- .as(List.class);
-
- Double similarity = RestAssured.given()
- .contentType(ContentType.JSON)
- .queryParam("embeddingContent", simpleText)
- .body(result)
- .post("/openai/vector/similarity")
- .then()
- .statusCode(200)
- .extract()
- .body()
- .as(Double.class);
-
- assertTrue(similarity >= 0.9);
- }
-
- @SuppressWarnings("unchecked")
- @Test
- void batchEmbedding() {
- String batchText = "Text content 1,Text content 2,Text content 3";
- List<List<?>> result = RestAssured.given()
- .contentType(ContentType.TEXT)
- .body(batchText)
- .post("/openai/embeddings")
- .then()
- .statusCode(200)
- .body(
- ".", hasSize(equalTo(3)),
- "[0]", hasSize(greaterThan(0)),
- "[1]", hasSize(greaterThan(0)),
- "[2]", hasSize(greaterThan(0)))
- .extract()
- .body()
- .as(List.class);
-
- String[] batchTextParts = batchText.split(",");
- for (int i = 0; i < batchTextParts.length; i++) {
- Double similarity = RestAssured.given()
- .contentType(ContentType.JSON)
- .queryParam("embeddingContent", batchTextParts[i])
- .body(result.get(i))
- .post("/openai/vector/similarity")
- .then()
- .statusCode(200)
- .extract()
- .body()
- .as(Double.class);
- assertTrue(similarity >= 0.9);
- }
- }
-
- @Test
- void vectorSimilarity() {
- String simpleText = "Simple text";
- List<?> result = RestAssured.given()
- .contentType(ContentType.TEXT)
- .body(simpleText)
- .post("/openai/embeddings")
- .then()
- .statusCode(200)
- .body(".", hasSize(greaterThan(0)))
- .extract()
- .body()
- .as(List.class);
-
- Double similarity = RestAssured.given()
- .contentType(ContentType.JSON)
- .queryParam("embeddingContent", simpleText + " extra content")
- .body(result)
- .post("/openai/vector/similarity")
- .then()
- .statusCode(200)
- .extract()
- .body()
- .as(Double.class);
-
- assertTrue(similarity >= 0.6);
- }
}
diff --git
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatTestResource.java
similarity index 58%
copy from
integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
copy to
integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatTestResource.java
index b30598ff66..021ed023b2 100644
---
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
+++
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatTestResource.java
@@ -16,9 +16,19 @@
*/
package org.apache.camel.quarkus.component.openai.it;
-import io.quarkus.test.junit.QuarkusIntegrationTest;
+import java.util.Map;
-@QuarkusIntegrationTest
-class OpenaiIT extends OpenaiTest {
+public class OpenaiChatTestResource extends OpenaiTestResource {
+ @Override
+ public Map<String, String> start() {
+ Map<String, String> conf = super.start();
+ conf.put("camel.component.openai.model",
envOrDefault(OPENAI_ENV_CHAT_MODEL, "gpt-5"));
+ conf.put("camel.component.openai.apiKey",
envOrDefault(OPENAI_ENV_CHAT_API_KEY, "test-key"));
+
+ if (conf.get("camel.component.openai.baseUrl") == null) {
+ conf.put("camel.component.openai.baseUrl",
envOrDefault(OPENAI_ENV_CHAT_BASE_URL, OPENAI_API_URL));
+ }
+ return conf;
+ }
}
diff --git
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiEmbeddingTest.java
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiEmbeddingTest.java
new file mode 100644
index 0000000000..c9fa5b49f3
--- /dev/null
+++
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiEmbeddingTest.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.openai.it;
+
+import java.util.List;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+import org.jboss.logging.Logger;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@QuarkusTestResource(value = OpenaiEmbeddingTestResource.class,
restrictToAnnotatedClass = true)
+@QuarkusTest
+class OpenaiEmbeddingTest {
+
+ private static final Logger LOG =
Logger.getLogger(OpenaiEmbeddingTest.class);
+
+ @BeforeEach
+ void logTestName(TestInfo testInfo) {
+ LOG.info(String.format("Running OpenaiEmbeddingTest test %s",
testInfo.getDisplayName()));
+ }
+
+ @Test
+ void simpleEmbedding() {
+ String simpleText = "Simple text";
+ List<?> result = RestAssured.given()
+ .contentType(ContentType.TEXT)
+ .body(simpleText)
+ .post("/openai/embeddings")
+ .then()
+ .statusCode(200)
+ .body(".", hasSize(greaterThan(0)))
+ .extract()
+ .body()
+ .as(List.class);
+
+ Double similarity = RestAssured.given()
+ .contentType(ContentType.JSON)
+ .queryParam("embeddingContent", simpleText)
+ .body(result)
+ .post("/openai/vector/similarity")
+ .then()
+ .statusCode(200)
+ .extract()
+ .body()
+ .as(Double.class);
+
+ assertTrue(similarity >= 0.9);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void batchEmbedding() {
+ String batchText = "Text content 1,Text content 2,Text content 3";
+ List<List<?>> result = RestAssured.given()
+ .contentType(ContentType.TEXT)
+ .body(batchText)
+ .post("/openai/embeddings")
+ .then()
+ .statusCode(200)
+ .body(
+ ".", hasSize(equalTo(3)),
+ "[0]", hasSize(greaterThan(0)),
+ "[1]", hasSize(greaterThan(0)),
+ "[2]", hasSize(greaterThan(0)))
+ .extract()
+ .body()
+ .as(List.class);
+
+ String[] batchTextParts = batchText.split(",");
+ for (int i = 0; i < batchTextParts.length; i++) {
+ Double similarity = RestAssured.given()
+ .contentType(ContentType.JSON)
+ .queryParam("embeddingContent", batchTextParts[i])
+ .body(result.get(i))
+ .post("/openai/vector/similarity")
+ .then()
+ .statusCode(200)
+ .extract()
+ .body()
+ .as(Double.class);
+ assertTrue(similarity >= 0.9);
+ }
+ }
+
+ @Test
+ void vectorSimilarity() {
+ String simpleText = "Simple text";
+ List<?> result = RestAssured.given()
+ .contentType(ContentType.TEXT)
+ .body(simpleText)
+ .post("/openai/embeddings")
+ .then()
+ .statusCode(200)
+ .body(".", hasSize(greaterThan(0)))
+ .extract()
+ .body()
+ .as(List.class);
+
+ Double similarity = RestAssured.given()
+ .contentType(ContentType.JSON)
+ .queryParam("embeddingContent", simpleText + " extra content")
+ .body(result)
+ .post("/openai/vector/similarity")
+ .then()
+ .statusCode(200)
+ .extract()
+ .body()
+ .as(Double.class);
+
+ assertTrue(similarity >= 0.6);
+ }
+}
diff --git
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiEmbeddingTestResource.java
similarity index 56%
rename from
integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
rename to
integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiEmbeddingTestResource.java
index b30598ff66..180289b351 100644
---
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiIT.java
+++
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiEmbeddingTestResource.java
@@ -16,9 +16,20 @@
*/
package org.apache.camel.quarkus.component.openai.it;
-import io.quarkus.test.junit.QuarkusIntegrationTest;
+import java.util.Map;
-@QuarkusIntegrationTest
-class OpenaiIT extends OpenaiTest {
+public class OpenaiEmbeddingTestResource extends OpenaiTestResource {
+ @Override
+ public Map<String, String> start() {
+ Map<String, String> conf = super.start();
+ conf.put("camel.component.openai.embedding-model",
+ envOrDefault(OPENAI_ENV_EMBEDDING_MODEL,
"text-embedding-3-small"));
+ conf.put("camel.component.openai.apiKey",
envOrDefault(OPENAI_ENV_EMBEDDING_API_KEY, "test-key"));
+
+ if (conf.get("camel.component.openai.baseUrl") == null) {
+ conf.put("camel.component.openai.baseUrl",
envOrDefault(OPENAI_ENV_EMBEDDING_BASE_URL, OPENAI_API_URL));
+ }
+ return conf;
+ }
}
diff --git
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTestResource.java
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTestResource.java
index 70077b0adb..fd5f75a449 100644
---
a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTestResource.java
+++
b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiTestResource.java
@@ -34,11 +34,13 @@ import
org.apache.camel.quarkus.test.wiremock.WireMockTestResourceLifecycleManag
import org.apache.camel.util.ObjectHelper;
public class OpenaiTestResource extends WireMockTestResourceLifecycleManager {
- private static final String OPENAI_API_URL = ClientOptions.PRODUCTION_URL;
- private static final String OPENAI_ENV_API_KEY = "OPENAI_API_KEY";
- private static final String OPENAI_ENV_BASE_URL = "OPENAI_BASE_URL";
- private static final String OPENAI_ENV_MODEL = "OPENAI_MODEL";
- private static final String OPENAI_ENV_EMBEDDING_MODEL =
"OPENAI_EMBEDDING_MODEL";
+ public static final String OPENAI_API_URL = ClientOptions.PRODUCTION_URL;
+ public static final String OPENAI_ENV_CHAT_API_KEY = "OPENAI_CHAT_API_KEY";
+ public static final String OPENAI_ENV_EMBEDDING_API_KEY =
"OPENAI_EMBEDDING_API_KEY";
+ public static final String OPENAI_ENV_CHAT_BASE_URL =
"OPENAI_CHAT_BASE_URL";
+ public static final String OPENAI_ENV_EMBEDDING_BASE_URL =
"OPENAI_EMBEDDING_BASE_URL";
+ public static final String OPENAI_ENV_CHAT_MODEL = "OPENAI_CHAT_MODEL";
+ public static final String OPENAI_ENV_EMBEDDING_MODEL =
"OPENAI_EMBEDDING_MODEL";
@Override
public Map<String, String> start() {
@@ -46,25 +48,18 @@ public class OpenaiTestResource extends
WireMockTestResourceLifecycleManager {
String wiremockUrl = configuration.get("wiremock.url");
if (ObjectHelper.isNotEmpty(wiremockUrl)) {
configuration.put("camel.component.openai.baseUrl", wiremockUrl);
- } else {
- configuration.put("camel.component.openai.baseUrl",
OPENAI_API_URL);
}
-
- configuration.put("camel.component.openai.model",
envOrDefault(OPENAI_ENV_MODEL, "gpt-5"));
- configuration.put("camel.component.openai.embedding-model",
- envOrDefault(OPENAI_ENV_EMBEDDING_MODEL,
"text-embedding-3-small"));
- configuration.put("camel.component.openai.apiKey",
envOrDefault(OPENAI_ENV_API_KEY, "test-key"));
return configuration;
}
@Override
protected String getRecordTargetBaseUrl() {
- return envOrDefault(OPENAI_ENV_BASE_URL, OPENAI_API_URL);
+ return envOrDefault(OPENAI_ENV_CHAT_BASE_URL, OPENAI_API_URL);
}
@Override
protected boolean isMockingEnabled() {
- return !envVarsPresent(OPENAI_ENV_API_KEY);
+ return !envVarsPresent(OPENAI_ENV_CHAT_API_KEY);
}
@Override
diff --git
a/integration-tests/openai/src/test/resources/mappings/chat_completions-04e37f50-08ea-4d43-a43e-299940f6e117.json
b/integration-tests/openai/src/test/resources/mappings/chat_completions-04e37f50-08ea-4d43-a43e-299940f6e117.json
index 84bb74120a..11047dc050 100644
---
a/integration-tests/openai/src/test/resources/mappings/chat_completions-04e37f50-08ea-4d43-a43e-299940f6e117.json
+++
b/integration-tests/openai/src/test/resources/mappings/chat_completions-04e37f50-08ea-4d43-a43e-299940f6e117.json
@@ -5,14 +5,14 @@
"url" : "/chat/completions",
"method" : "POST",
"bodyPatterns" : [ {
- "equalToJson" : "{\"messages\":[{\"content\":\"Create an example product
for a product named 'Bluetooth
Headphones'.\",\"role\":\"user\"}],\"model\":\"gpt-5\",\"response_format\":{\"json_schema\":{\"name\":\"json-schema-from-Product\",\"schema\":{\"$schema\":\"https://json-schema.org/draft/2020-12/schema\",\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\"},\"price\":{\"type\":\"number\"}},\"required\":[\"name\",\"price\"],\"additionalProperties\":false},\"strict\":t
[...]
+ "equalToJson" : "{\"messages\":[{\"content\":\"Create an example product
for a product named
'Bluetooth'.\",\"role\":\"user\"}],\"model\":\"gpt-5\",\"response_format\":{\"json_schema\":{\"name\":\"json-schema-from-Product\",\"schema\":{\"$schema\":\"https://json-schema.org/draft/2020-12/schema\",\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\"},\"price\":{\"type\":\"number\"}},\"required\":[\"name\",\"price\"],\"additionalProperties\":false},\"strict\":true},\"type
[...]
"ignoreArrayOrder" : true,
"ignoreExtraElements" : true
} ]
},
"response" : {
"status" : 200,
- "body" : "{\n \"id\": \"chatcmpl-D6Fh0CqBFAJAHRl6M6kbhxZvY9kd9\",\n
\"object\": \"chat.completion\",\n \"created\": 1770382662,\n \"model\":
\"gpt-5-2025-08-07\",\n \"choices\": [\n {\n \"index\": 0,\n
\"message\": {\n \"role\": \"assistant\",\n \"content\":
\"{\\\"name\\\":\\\"Bluetooth Headphones\\\",\\\"price\\\":79.99}\",\n
\"refusal\": null,\n \"annotations\": []\n },\n
\"finish_reason\": \"stop\"\n }\n ],\n \"usage\": [...]
+ "body" : "{\n \"id\": \"chatcmpl-D6Fh0CqBFAJAHRl6M6kbhxZvY9kd9\",\n
\"object\": \"chat.completion\",\n \"created\": 1770382662,\n \"model\":
\"gpt-5-2025-08-07\",\n \"choices\": [\n {\n \"index\": 0,\n
\"message\": {\n \"role\": \"assistant\",\n \"content\":
\"{\\\"name\\\":\\\"Bluetooth\\\",\\\"price\\\":79.99}\",\n \"refusal\":
null,\n \"annotations\": []\n },\n \"finish_reason\":
\"stop\"\n }\n ],\n \"usage\": {\n \"p [...]
"headers" : {
"x-request-id" : "req_83e0c698f8b0468491d1799d1d971f4e",
"x-ratelimit-limit-tokens" : "500000",
diff --git
a/integration-tests/openai/src/test/resources/mappings/chat_completions-323a6828-8117-4d20-9627-72939652f6e4.json
b/integration-tests/openai/src/test/resources/mappings/chat_completions-323a6828-8117-4d20-9627-72939652f6e4.json
index ca7c0b0ad5..8c9b607a03 100644
---
a/integration-tests/openai/src/test/resources/mappings/chat_completions-323a6828-8117-4d20-9627-72939652f6e4.json
+++
b/integration-tests/openai/src/test/resources/mappings/chat_completions-323a6828-8117-4d20-9627-72939652f6e4.json
@@ -5,7 +5,7 @@
"url" : "/chat/completions",
"method" : "POST",
"bodyPatterns" : [ {
- "equalToJson" : "{\"messages\":[{\"content\":\"Stream the numbers 1 to
10 on a new line each time and nothing
else.\",\"role\":\"user\"}],\"model\":\"gpt-5\",\"stream\":true}",
+ "equalToJson" : "{\"messages\":[{\"content\":\"Stream the numbers 1 to 9
on a new line each time and nothing
else.\",\"role\":\"user\"}],\"model\":\"gpt-5\",\"stream\":true}",
"ignoreArrayOrder" : true,
"ignoreExtraElements" : true
} ]
diff --git
a/integration-tests/openai/src/test/resources/mappings/chat_completions-45c75cdd-225c-4e51-a133-a3146fff462b.json
b/integration-tests/openai/src/test/resources/mappings/chat_completions-45c75cdd-225c-4e51-a133-a3146fff462b.json
index f1e2651254..3f374fb7d3 100644
---
a/integration-tests/openai/src/test/resources/mappings/chat_completions-45c75cdd-225c-4e51-a133-a3146fff462b.json
+++
b/integration-tests/openai/src/test/resources/mappings/chat_completions-45c75cdd-225c-4e51-a133-a3146fff462b.json
@@ -5,14 +5,14 @@
"url" : "/chat/completions",
"method" : "POST",
"bodyPatterns" : [ {
- "equalToJson" :
"{\"messages\":[{\"role\":\"assistant\",\"content\":\"Hello, Camelus
dromedarius! Nice to meet you. How can I help you today?\\n\\nOptions:\\n-
Quick facts about dromedaries (diet, habitat, adaptations)\\n- A short story or
monologue from your perspective\\n- Comparison with Bactrian camels\\n- Q&A
about behavior, physiology, or history\\n\\nTell me what you’re in the mood
for.\"},{\"content\":\"What is my Camel
species?\",\"role\":\"user\"}],\"model\":\"gpt-5\"}",
+ "equalToJson" :
"{\"messages\":[{\"role\":\"assistant\",\"content\":\"Hello, Camelus
dromedarius! Nice to meet you. How can I help you today?\\n\\nOptions:\\n-
Quick facts about dromedaries (diet, habitat, adaptations)\\n- A short story or
monologue from your perspective\\n- Comparison with Bactrian camels\\n- Q&A
about behavior, physiology, or history\\n\\nTell me what you’re in the mood
for.\"},{\"content\":\"What is my name? Respond maximum 5
words.\",\"role\":\"user\"}],\"model [...]
"ignoreArrayOrder" : true,
"ignoreExtraElements" : true
} ]
},
"response" : {
"status" : 200,
- "body" : "{\n \"id\": \"chatcmpl-D6Fg8qzpwpUTx79NLTY7g5II4FnYz\",\n
\"object\": \"chat.completion\",\n \"created\": 1770382608,\n \"model\":
\"gpt-5-2025-08-07\",\n \"choices\": [\n {\n \"index\": 0,\n
\"message\": {\n \"role\": \"assistant\",\n \"content\": \"You’re
a dromedary camel: Camelus dromedarius.\\n\\nQuick ID:\\n- One hump (vs. two in
Bactrian camels)\\n- Origin in Arabian/North African regions; now
widespread\\n- Makes up ~90% of the world’ [...]
+ "body" : "{\n \"id\": \"chatcmpl-D6Fg8qzpwpUTx79NLTY7g5II4FnYz\",\n
\"object\": \"chat.completion\",\n \"created\": 1770382608,\n \"model\":
\"gpt-5-2025-08-07\",\n \"choices\": [\n {\n \"index\": 0,\n
\"message\": {\n \"role\": \"assistant\",\n \"content\": \"You’re
a John.\\n\\nQuick ID:\\n- One hump (vs. two in Bactrian camels)\\n- Origin in
Arabian/North African regions; now widespread\\n- Makes up ~90% of the world’s
camels\\n\\nFor comparison: tw [...]
"headers" : {
"x-request-id" : "req_0e75d17071994b3f996151aafe448380",
"x-ratelimit-limit-tokens" : "500000",
diff --git
a/integration-tests/openai/src/test/resources/mappings/chat_completions-741db9c0-e3ee-4dea-a702-ea609f5a10c5.json
b/integration-tests/openai/src/test/resources/mappings/chat_completions-741db9c0-e3ee-4dea-a702-ea609f5a10c5.json
index c354af3283..2c51a0952f 100644
---
a/integration-tests/openai/src/test/resources/mappings/chat_completions-741db9c0-e3ee-4dea-a702-ea609f5a10c5.json
+++
b/integration-tests/openai/src/test/resources/mappings/chat_completions-741db9c0-e3ee-4dea-a702-ea609f5a10c5.json
@@ -5,7 +5,7 @@
"url" : "/chat/completions",
"method" : "POST",
"bodyPatterns" : [ {
- "equalToJson" : "{\"messages\":[{\"content\":\"I am a Camel and my
species is Camelus Dromedarius.\",\"role\":\"user\"}],\"model\":\"gpt-5\"}",
+ "equalToJson" : "{\"messages\":[{\"content\":\"My name is
John.\",\"role\":\"user\"}],\"model\":\"gpt-5\"}",
"ignoreArrayOrder" : true,
"ignoreExtraElements" : true
} ]