This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch 3.40.x in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit a46f0b432d05e0008c75b72496b1909b00614b77 Author: James Netherton <[email protected]> AuthorDate: Tue Oct 20 07:08:52 2026 +0100 Make OpenaiChatTest.chatWithImage produce more consistent results across LLMs and models --- .../src/main/resources/application.properties | 3 +++ .../component/openai/it/OpenaiChatTest.java | 28 +++++++-------------- .../openai/src/test/resources/img/camel-logo.png | Bin 13008 -> 0 bytes .../openai/src/test/resources/img/orange.png | Bin 0 -> 566 bytes ...tions-6dcb56c2-44cf-48e5-9ea0-a1696d851b90.json | 4 +-- 5 files changed, 14 insertions(+), 21 deletions(-) diff --git a/integration-tests/openai/src/main/resources/application.properties b/integration-tests/openai/src/main/resources/application.properties index ce006b27b3..0ea714de13 100644 --- a/integration-tests/openai/src/main/resources/application.properties +++ b/integration-tests/openai/src/main/resources/application.properties @@ -22,3 +22,6 @@ quarkus.native.resources.includes=schema/product.json # Set to false to skip OpenaiAudioTest when the target endpoint has no audio transcription support openai.audio.enabled=true +# Set to false to skip OpenaiChatTest.chatWithImage when the target endpoint has no vision support +openai.vision.enabled=true + diff --git a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatTest.java b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatTest.java index 84b652a095..4490f671c5 100644 --- a/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatTest.java +++ b/integration-tests/openai/src/test/java/org/apache/camel/quarkus/component/openai/it/OpenaiChatTest.java @@ -32,13 +32,12 @@ import java.util.stream.IntStream; import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.junit.condition.EnabledIfConfig; import io.restassured.RestAssured; import io.restassured.http.ContentType; import org.apache.camel.util.FileUtil; -import org.apache.commons.lang3.StringUtils; 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; @@ -71,23 +70,14 @@ class OpenaiChatTest { .body(containsStringIgnoringCase("camel")); } + @EnabledIfConfig(named = "openai.vision.enabled", matches = "true") @Test void chatWithImage() throws IOException { - String wireMockUrl = RestAssured.get("/openai/configProperty/wiremock.url") - .then() - .statusCode(200).extract().body().asString(); - String openaiUrl = RestAssured.get("/openai/configProperty/camel.component.openai.baseUrl") - .then() - .statusCode(200).extract().body().asString(); - // run image test only on openai model or on wiremock - Assumptions.assumeTrue( - OpenaiTestResource.OPENAI_API_URL.equals(openaiUrl) || StringUtils.isNotEmpty(wireMockUrl), - "Needs model which support image operations."); - Path path = Paths.get("target/camel-log.png"); - - try (InputStream stream = OpenaiChatTest.class.getResourceAsStream("/img/camel-logo.png")) { + Path path = Paths.get("target/orange.png"); + + try (InputStream stream = OpenaiChatTest.class.getResourceAsStream("/img/orange.png")) { if (stream == null) { - throw new IllegalStateException("Failed loading camel-logo.png"); + throw new IllegalStateException("Failed loading orange.png"); } try (OutputStream out = new FileOutputStream(path.toFile())) { @@ -95,12 +85,12 @@ class OpenaiChatTest { } RestAssured.given() - .queryParam("userMessage", "Describe what you see in this image") - .body("target/camel-log.png") + .queryParam("userMessage", "What colour is this image? Answer with one word.") + .body("target/orange.png") .post("/openai/chat/image") .then() .statusCode(200) - .body(containsStringIgnoringCase("camel")); + .body(containsStringIgnoringCase("orange")); } finally { if (FileUtil.isWindows()) { // File may be locked by the Quarkus process, so clean up on VM exit diff --git a/integration-tests/openai/src/test/resources/img/camel-logo.png b/integration-tests/openai/src/test/resources/img/camel-logo.png deleted file mode 100644 index e5d56708dc..0000000000 Binary files a/integration-tests/openai/src/test/resources/img/camel-logo.png and /dev/null differ diff --git a/integration-tests/openai/src/test/resources/img/orange.png b/integration-tests/openai/src/test/resources/img/orange.png new file mode 100644 index 0000000000..c783a69a93 Binary files /dev/null and b/integration-tests/openai/src/test/resources/img/orange.png differ diff --git a/integration-tests/openai/src/test/resources/mappings/chat_completions-6dcb56c2-44cf-48e5-9ea0-a1696d851b90.json b/integration-tests/openai/src/test/resources/mappings/chat_completions-6dcb56c2-44cf-48e5-9ea0-a1696d851b90.json index 8bbb052dcf..dbb911225f 100644 --- a/integration-tests/openai/src/test/resources/mappings/chat_completions-6dcb56c2-44cf-48e5-9ea0-a1696d851b90.json +++ b/integration-tests/openai/src/test/resources/mappings/chat_completions-6dcb56c2-44cf-48e5-9ea0-a1696d851b90.json @@ -5,14 +5,14 @@ "url" : "/chat/completions", "method" : "POST", "bodyPatterns" : [ { - "equalToJson" : "{\"messages\":[{\"content\":[{\"text\":\"Describe what you see in this image\",\"type\":\"text\"},{\"image_url\":{\"url\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIgAAACACAYAAADQ6SE/AAAKomlDQ1BJQ0MgUHJvZmlsZQAASImVlwdQk9kWx+/3pYeElhA6hN6ktwBSQg+9NxshCRBKDAlBxa4sruBaEBEBRdBVEQXXAogdUWyLgGLXDbKIKOtiQVRU3gcMYXffvPfmnZkz9zf/nHvuuXfu/eYEALIiWyjMghUByBbkiqICvOkJiUl03CsAAQKQBwrAiM0RC5kRESEAsZnx7/bxHhKN2B3LyVz//vt/NSUuT8wBAIpAOIUr5mQjfBLxYY5QlAsAai+iGyzJFU5yO8JUEVI [...] + "equalToJson" : "{\"messages\":[{\"content\":[{\"text\":\"What colour is this image? Answer with one word.\",\"type\":\"text\"},{\"image_url\":{\"url\":\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAAB/UlEQVR42u3TwQkAAAgDsY7u5vbvCgYywcFlJ/CWBBgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGwAAqYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADAAGAAOAAcAAYAAwABgADA [...] "ignoreArrayOrder" : true, "ignoreExtraElements" : true } ] }, "response" : { "status" : 200, - "body" : "{\n \"id\": \"chatcmpl-D6FgaNoDxKIPWVL7AX3tUPCKuoEnO\",\n \"object\": \"chat.completion\",\n \"created\": 1770382636,\n \"model\": \"gpt-5-2025-08-07\",\n \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"It’s a circular icon with an orange-to-yellow gradient background suggesting desert dunes. In the foreground is a white, stylized silhouette of a camel’s head and neck, curving upward from left t [...] + "body" : "{\n \"id\": \"chatcmpl-D6FgaNoDxKIPWVL7AX3tUPCKuoEnO\",\n \"object\": \"chat.completion\",\n \"created\": 1770382636,\n \"model\": \"gpt-5-2025-08-07\",\n \"choices\": [\n {\n \"index\": 0,\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"Orange\",\n \"refusal\": null,\n \"annotations\": []\n },\n \"finish_reason\": \"stop\"\n }\n ],\n \"usage\": {\n \"prompt_tokens\": 223,\n \"completion_tokens\ [...] "headers" : { "Server" : "cloudflare", "x-ratelimit-reset-input-images" : "1ms",
