This is an automated email from the ASF dual-hosted git repository.
Croway pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 674c0e05544a CAMEL-24540: camel-huggingface - honour the model
revision for sentence-embeddings and text-to-image, and set the text-to-image
OUTPUT header
674c0e05544a is described below
commit 674c0e05544a9bb57d5526028d3de07e1a0bcc74
Author: Andrea Cosentino <[email protected]>
AuthorDate: Mon Aug 31 09:51:19 2026 +0200
CAMEL-24540: camel-huggingface - honour the model revision for
sentence-embeddings and text-to-image, and set the text-to-image OUTPUT header
Two small correctness gaps in the task predictors:
- The configured model revision was dropped by SentenceEmbeddingsPredictor
and
TextToImagePredictor; the other eight tasks pass config.getRevision()
into their
Python script, so pinning a revision silently had no effect for these
two. Pass
the revision into sentence_embeddings.py (SentenceTransformer) and
text_to_image.py (StableDiffusionPipeline.from_pretrained).
- TextToImagePredictor set the image bytes as the body but never set the
OUTPUT
header, although its Javadoc documents it. Set
HuggingFaceConstants.OUTPUT to the
image bytes alongside the body.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Signed-off-by: Andrea Cosentino <[email protected]>
---
.../tasks/SentenceEmbeddingsPredictor.java | 2 +-
.../huggingface/tasks/TextToImagePredictor.java | 4 +-
.../huggingface/tasks/sentence_embeddings.py | 2 +-
.../component/huggingface/tasks/text_to_image.py | 1 +
.../tasks/RevisionAndOutputHeaderTest.java | 90 ++++++++++++++++++++++
5 files changed, 96 insertions(+), 3 deletions(-)
diff --git
a/components/camel-ai/camel-huggingface/src/main/java/org/apache/camel/component/huggingface/tasks/SentenceEmbeddingsPredictor.java
b/components/camel-ai/camel-huggingface/src/main/java/org/apache/camel/component/huggingface/tasks/SentenceEmbeddingsPredictor.java
index d6e9649f401e..40fb875d91ca 100644
---
a/components/camel-ai/camel-huggingface/src/main/java/org/apache/camel/component/huggingface/tasks/SentenceEmbeddingsPredictor.java
+++
b/components/camel-ai/camel-huggingface/src/main/java/org/apache/camel/component/huggingface/tasks/SentenceEmbeddingsPredictor.java
@@ -103,7 +103,7 @@ public class SentenceEmbeddingsPredictor extends
AbstractTaskPredictor {
@Override
protected String getPythonScript() {
- return loadPythonScript("sentence_embeddings.py", config.getDevice(),
config.getModelId());
+ return loadPythonScript("sentence_embeddings.py", config.getDevice(),
config.getModelId(), config.getRevision());
}
@Override
diff --git
a/components/camel-ai/camel-huggingface/src/main/java/org/apache/camel/component/huggingface/tasks/TextToImagePredictor.java
b/components/camel-ai/camel-huggingface/src/main/java/org/apache/camel/component/huggingface/tasks/TextToImagePredictor.java
index a928854acd1a..561e7cd0d381 100644
---
a/components/camel-ai/camel-huggingface/src/main/java/org/apache/camel/component/huggingface/tasks/TextToImagePredictor.java
+++
b/components/camel-ai/camel-huggingface/src/main/java/org/apache/camel/component/huggingface/tasks/TextToImagePredictor.java
@@ -22,6 +22,7 @@ import ai.djl.modality.Input;
import ai.djl.modality.Output;
import org.apache.camel.Exchange;
import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.component.huggingface.HuggingFaceConstants;
import org.apache.camel.component.huggingface.HuggingFaceEndpoint;
/**
@@ -92,7 +93,7 @@ public class TextToImagePredictor extends
AbstractTaskPredictor {
@Override
protected String getPythonScript() {
- return loadPythonScript("text_to_image.py", config.getModelId(),
config.getDevice());
+ return loadPythonScript("text_to_image.py", config.getModelId(),
config.getRevision(), config.getDevice());
}
@Override
@@ -117,5 +118,6 @@ public class TextToImagePredictor extends
AbstractTaskPredictor {
}
exchange.getMessage().setBody(imageBytes);
exchange.getMessage().setHeader("Content-Type", "image/png");
+ exchange.getMessage().setHeader(HuggingFaceConstants.OUTPUT,
imageBytes);
}
}
diff --git
a/components/camel-ai/camel-huggingface/src/main/resources/org/apache/camel/component/huggingface/tasks/sentence_embeddings.py
b/components/camel-ai/camel-huggingface/src/main/resources/org/apache/camel/component/huggingface/tasks/sentence_embeddings.py
index 6fe310f35f24..9ee585c2dde6 100644
---
a/components/camel-ai/camel-huggingface/src/main/resources/org/apache/camel/component/huggingface/tasks/sentence_embeddings.py
+++
b/components/camel-ai/camel-huggingface/src/main/resources/org/apache/camel/component/huggingface/tasks/sentence_embeddings.py
@@ -31,7 +31,7 @@ def handle(inputs: Input):
device = '%s'
if device == 'auto':
device = 'cuda' if torch.cuda.is_available() else 'cpu'
- model = SentenceTransformer('%s', device=device)
+ model = SentenceTransformer('%s', device=device, revision='%s')
logging.debug("Model initialized")
if inputs.content.size() == 0:
diff --git
a/components/camel-ai/camel-huggingface/src/main/resources/org/apache/camel/component/huggingface/tasks/text_to_image.py
b/components/camel-ai/camel-huggingface/src/main/resources/org/apache/camel/component/huggingface/tasks/text_to_image.py
index e8b41788c2b5..aa7eae92638c 100644
---
a/components/camel-ai/camel-huggingface/src/main/resources/org/apache/camel/component/huggingface/tasks/text_to_image.py
+++
b/components/camel-ai/camel-huggingface/src/main/resources/org/apache/camel/component/huggingface/tasks/text_to_image.py
@@ -31,6 +31,7 @@ def handle(inputs: Input):
logging.debug("Initializing pipeline")
pipe = StableDiffusionPipeline.from_pretrained(
'%s',
+ revision='%s',
torch_dtype=torch.float32, # CPU-safe
safety_checker=None
)
diff --git
a/components/camel-ai/camel-huggingface/src/test/java/org/apache/camel/component/huggingface/tasks/RevisionAndOutputHeaderTest.java
b/components/camel-ai/camel-huggingface/src/test/java/org/apache/camel/component/huggingface/tasks/RevisionAndOutputHeaderTest.java
new file mode 100644
index 000000000000..535a7fa69737
--- /dev/null
+++
b/components/camel-ai/camel-huggingface/src/test/java/org/apache/camel/component/huggingface/tasks/RevisionAndOutputHeaderTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.component.huggingface.tasks;
+
+import ai.djl.modality.Output;
+import org.apache.camel.Exchange;
+import org.apache.camel.component.huggingface.HuggingFaceConfiguration;
+import org.apache.camel.component.huggingface.HuggingFaceConstants;
+import org.apache.camel.component.huggingface.HuggingFaceEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.DefaultExchange;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * The sentence-embeddings and text-to-image tasks must honour the configured
model revision (they were the only two
+ * that dropped it), and the text-to-image task must publish its result on the
OUTPUT header as its Javadoc promises.
+ */
+class RevisionAndOutputHeaderTest {
+
+ private DefaultCamelContext context;
+
+ @BeforeEach
+ void setUp() {
+ context = new DefaultCamelContext();
+ }
+
+ @AfterEach
+ void tearDown() {
+ context.stop();
+ }
+
+ private HuggingFaceEndpoint endpoint(HuggingFaceConfiguration config) {
+ HuggingFaceEndpoint endpoint = new HuggingFaceEndpoint(null, null,
config);
+ endpoint.setCamelContext(context);
+ return endpoint;
+ }
+
+ @Test
+ void sentenceEmbeddingsScriptPinsRevision() {
+ HuggingFaceConfiguration config = new HuggingFaceConfiguration();
+ config.setModelId("sentence-transformers/all-MiniLM-L6-v2");
+ config.setRevision("v1.5");
+ SentenceEmbeddingsPredictor predictor = new
SentenceEmbeddingsPredictor(endpoint(config));
+ assertTrue(predictor.getPythonScript().contains("revision='v1.5'"),
+ "the generated script must pin the configured revision");
+ }
+
+ @Test
+ void textToImageScriptPinsRevision() {
+ HuggingFaceConfiguration config = new HuggingFaceConfiguration();
+ config.setModelId("stabilityai/stable-diffusion");
+ config.setRevision("fp16");
+ TextToImagePredictor predictor = new
TextToImagePredictor(endpoint(config));
+ assertTrue(predictor.getPythonScript().contains("revision='fp16'"),
+ "the generated script must pin the configured revision");
+ }
+
+ @Test
+ void textToImagePublishesTheImageOnTheOutputHeader() throws Exception {
+ HuggingFaceConfiguration config = new HuggingFaceConfiguration();
+ TextToImagePredictor predictor = new
TextToImagePredictor(endpoint(config));
+ Exchange exchange = new DefaultExchange(context);
+ Output output = new Output();
+ byte[] image = { 1, 2, 3, 4 };
+ output.add("data", image);
+
+ predictor.processOutput(exchange, output);
+
+ assertArrayEquals(image,
exchange.getMessage().getHeader(HuggingFaceConstants.OUTPUT, byte[].class));
+ }
+}