This is an automated email from the ASF dual-hosted git repository.

aldettinger pushed a commit to branch camel-quarkus-main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus-examples.git


The following commit(s) were added to refs/heads/camel-quarkus-main by this 
push:
     new 7bdbc9dd data-extract: reinstate the structured output feature
7bdbc9dd is described below

commit 7bdbc9dd481b95eca5b445786a4c5d81786e18bf
Author: aldettinger <[email protected]>
AuthorDate: Thu Dec 18 14:28:41 2025 +0100

    data-extract: reinstate the structured output feature
---
 data-extract-langchain4j/README.adoc               |  2 --
 .../extraction/CustomPojoExtractionService.java    |  7 +++++--
 .../extraction/DataExtractAgentConfiguration.java  |  2 ++
 .../langchain4j-ollama/reflect-config.json         |  7 +++++++
 ..._chat-2458b71a-4789-4a07-9424-ba7a1da8bf07.json | 24 ----------------------
 ..._chat-3867080e-87d5-40d6-b9a8-b90817d980f9.json | 24 ++++++++++++++++++++++
 ..._chat-3ac79428-f534-4e6a-aa8f-8e401ac22256.json | 24 ++++++++++++++++++++++
 ..._chat-4a005fe6-e449-482d-8ce6-8c341fa4cb9f.json | 24 ++++++++++++++++++++++
 ..._chat-5dbaaf5e-5436-470c-a629-cee5ea860e64.json | 24 ----------------------
 ..._chat-a359a6fc-e37c-4383-a99c-efa92d6e650d.json | 24 ----------------------
 10 files changed, 86 insertions(+), 76 deletions(-)

diff --git a/data-extract-langchain4j/README.adoc 
b/data-extract-langchain4j/README.adoc
index 8f0b98dd..b72a898f 100644
--- a/data-extract-langchain4j/README.adoc
+++ b/data-extract-langchain4j/README.adoc
@@ -17,8 +17,6 @@ image::schema.png[]
 In order to achieve this extraction, we'll need a 
https://en.wikipedia.org/wiki/Large_language_model[Large Language Model (LLM)] 
and related serving framework that natively supports 
https://ollama.com/blog/structured-outputs[JSON structured output].
 Here, we choose https://ollama.com/library/granite3.3:2b[granite3.3:2b] served 
through https://ollama.com/[ollama] as it seems compute friendly and under 
Apache V2 license.
 In order to request inference to the served model, we'll use the high-level 
LangChain4j APIs like 
https://docs.langchain4j.dev/tutorials/ai-services[AiServices].
-More precisely, we'll setup the 
https://docs.quarkiverse.io/quarkus-langchain4j/dev/index.html[Quarkus 
LangChain4j extension] to register an AiService bean.
-Finally, we'll invoke the AiService extraction method via the 
https://camel.apache.org/camel-quarkus/latest/reference/extensions/bean.html[Camel
 Quarkus bean extension].
 
 === Start the Large Language Model
 
diff --git 
a/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoExtractionService.java
 
b/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoExtractionService.java
index 9392c9ad..82fad99e 100644
--- 
a/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoExtractionService.java
+++ 
b/data-extract-langchain4j/src/main/java/org/acme/extraction/CustomPojoExtractionService.java
@@ -22,7 +22,9 @@ import java.util.Locale;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import dev.langchain4j.service.UserMessage;
 import dev.langchain4j.service.V;
+import io.quarkus.runtime.annotations.RegisterForReflection;
 
+@RegisterForReflection(targets = LocalDate.class)
 public interface CustomPojoExtractionService {
 
     class CustomPojo {
@@ -48,9 +50,10 @@ public interface CustomPojoExtractionService {
         }
     }
 
-    String CUSTOM_POJO_EXTRACT_PROMPT = "Extract information about a customer 
from the text delimited by triple backticks: ```{{text}}```."
+    String CUSTOM_POJO_EXTRACT_PROMPT = "Extract information about a customer 
from the transcript delimited by triple backticks: ```{{text}}```."
             + "The customerBirthday field should be formatted as 
{{dateFormat}}."
-            + "The summary field should concisely relate the customer main 
ask.";
+            + "The summary field should concisely relate the customer main 
ask."
+            + "Source any extracted field values from what is explicitly 
mentioned in the transcript.";
 
     /**
      * The text and dateFormat parameters of this method are automatically 
injected as {{text}} & {{dateFormat}} in the
diff --git 
a/data-extract-langchain4j/src/main/java/org/acme/extraction/DataExtractAgentConfiguration.java
 
b/data-extract-langchain4j/src/main/java/org/acme/extraction/DataExtractAgentConfiguration.java
index d294f888..3d63ca27 100644
--- 
a/data-extract-langchain4j/src/main/java/org/acme/extraction/DataExtractAgentConfiguration.java
+++ 
b/data-extract-langchain4j/src/main/java/org/acme/extraction/DataExtractAgentConfiguration.java
@@ -18,6 +18,7 @@ package org.acme.extraction;
 
 import java.time.Duration;
 
+import dev.langchain4j.model.chat.Capability;
 import dev.langchain4j.model.ollama.OllamaChatModel;
 import io.smallrye.common.annotation.Identifier;
 import jakarta.enterprise.context.ApplicationScoped;
@@ -43,6 +44,7 @@ public class DataExtractAgentConfiguration {
                 .topK(1)
                 .topP(0.1)
                 .modelName(chatModelId)
+                .supportedCapabilities(Capability.RESPONSE_FORMAT_JSON_SCHEMA)
                 .temperature(0.0)
                 .timeout(Duration.ofMinutes(3))
                 .build());
diff --git 
a/data-extract-langchain4j/src/main/resources/META-INF/native-image/dev.langchain4j/langchain4j-ollama/reflect-config.json
 
b/data-extract-langchain4j/src/main/resources/META-INF/native-image/dev.langchain4j/langchain4j-ollama/reflect-config.json
new file mode 100644
index 00000000..212db31f
--- /dev/null
+++ 
b/data-extract-langchain4j/src/main/resources/META-INF/native-image/dev.langchain4j/langchain4j-ollama/reflect-config.json
@@ -0,0 +1,7 @@
+[
+  {
+    "name" : "dev.langchain4j.model.ollama.OllamaChatRequest",
+    "allDeclaredFields" : true,
+    "allPublicFields" : true
+  }
+]
\ No newline at end of file
diff --git 
a/data-extract-langchain4j/src/test/resources/mappings/api_chat-2458b71a-4789-4a07-9424-ba7a1da8bf07.json
 
b/data-extract-langchain4j/src/test/resources/mappings/api_chat-2458b71a-4789-4a07-9424-ba7a1da8bf07.json
deleted file mode 100644
index 6445703c..00000000
--- 
a/data-extract-langchain4j/src/test/resources/mappings/api_chat-2458b71a-4789-4a07-9424-ba7a1da8bf07.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-  "id" : "2458b71a-4789-4a07-9424-ba7a1da8bf07",
-  "name" : "api_chat",
-  "request" : {
-    "url" : "/api/chat",
-    "method" : "POST",
-    "bodyPatterns" : [ {
-      "equalToJson" : "{\n  \"model\" : \"granite3.3:2b\",\n  \"messages\" : [ 
{\n    \"role\" : \"user\",\n    \"content\" : \"Extract information about a 
customer from the text delimited by triple backticks: ```Operator: Hello, how 
may I help you ?\\nCustomer: Hello, I'm John. I need to share a problem with 
you. Actually, the insurance has reimbursed only half the money I have spent 
due to the accident.\\nOperator: Hello John, could you please give me your last 
name so that I can find  [...]
-      "ignoreArrayOrder" : true,
-      "ignoreExtraElements" : true
-    } ]
-  },
-  "response" : {
-    "status" : 200,
-    "body" : 
"{\"model\":\"granite3.3:2b\",\"created_at\":\"2025-09-01T09:21:38.075300267Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n\\\"customerSatisfied\\\":
 false,\\n\\\"customerName\\\": \\\"John Doe\\\",\\n\\\"customerBirthday\\\": 
\\\"2001-11-01\\\",\\n\\\"summary\\\": \\\"Customer John Doe is dissatisfied 
with the insurance reimbursement issue. The full reimbursement option was 
automatically cancelled, causing him to receive only half the amount due to an 
accident.\\ [...]
-    "headers" : {
-      "Date" : "Mon, 01 Sep 2025 09:21:38 GMT",
-      "Content-Type" : "application/json; charset=utf-8"
-    }
-  },
-  "uuid" : "2458b71a-4789-4a07-9424-ba7a1da8bf07",
-  "persistent" : true,
-  "insertionIndex" : 5
-}
\ No newline at end of file
diff --git 
a/data-extract-langchain4j/src/test/resources/mappings/api_chat-3867080e-87d5-40d6-b9a8-b90817d980f9.json
 
b/data-extract-langchain4j/src/test/resources/mappings/api_chat-3867080e-87d5-40d6-b9a8-b90817d980f9.json
new file mode 100644
index 00000000..deacf720
--- /dev/null
+++ 
b/data-extract-langchain4j/src/test/resources/mappings/api_chat-3867080e-87d5-40d6-b9a8-b90817d980f9.json
@@ -0,0 +1,24 @@
+{
+  "id" : "3867080e-87d5-40d6-b9a8-b90817d980f9",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"granite3.3:2b\",\n  \"messages\" : [ 
{\n    \"role\" : \"user\",\n    \"content\" : \"Extract information about a 
customer from the transcript delimited by triple backticks: ```Operator: Hello, 
how may I help you ?\\nCustomer: Hello, I'm calling because I need to declare 
an accident on my main vehicle.\\nOperator: Ok, can you please give me your 
name ?\\nCustomer: My name is Sarah London.\\nOperator: Could you please give 
me your birth date ?\\nC [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"granite3.3:2b\",\"created_at\":\"2025-12-18T13:25:30.629932212Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n
  \\\"customerSatisfied\\\": true,\\n  \\\"customerName\\\": \\\"Sarah 
London\\\",\\n  \\\"customerBirthday\\\": {\\\"year\\\": 1986, \\\"month\\\": 
7, \\\"day\\\": 10},\\n  \\\"summary\\\": \\\"The customer, Sarah London, is 
calling to declare an accident and seek reimbursement for related 
expenses.\\\"\\n}\"},\"done_reason\":\"stop\",\"done\ [...]
+    "headers" : {
+      "Date" : "Thu, 18 Dec 2025 13:25:30 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "3867080e-87d5-40d6-b9a8-b90817d980f9",
+  "persistent" : true,
+  "insertionIndex" : 6
+}
\ No newline at end of file
diff --git 
a/data-extract-langchain4j/src/test/resources/mappings/api_chat-3ac79428-f534-4e6a-aa8f-8e401ac22256.json
 
b/data-extract-langchain4j/src/test/resources/mappings/api_chat-3ac79428-f534-4e6a-aa8f-8e401ac22256.json
new file mode 100644
index 00000000..8b687b63
--- /dev/null
+++ 
b/data-extract-langchain4j/src/test/resources/mappings/api_chat-3ac79428-f534-4e6a-aa8f-8e401ac22256.json
@@ -0,0 +1,24 @@
+{
+  "id" : "3ac79428-f534-4e6a-aa8f-8e401ac22256",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"granite3.3:2b\",\n  \"messages\" : [ 
{\n    \"role\" : \"user\",\n    \"content\" : \"Extract information about a 
customer from the transcript delimited by triple backticks: ```Operator: Hello, 
how may I help you?\\nCustomer: Hello, I am currently at the police station 
because I've got an accident. The police would need a proof that I have an 
insurance. Could you please help me?\\nOperator: Sure, could you please remind 
me your name and birth dat [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"granite3.3:2b\",\"created_at\":\"2025-12-18T13:25:52.676173019Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n
  \\\"customerSatisfied\\\": true,\\n  \\\"customerName\\\": \\\"Kate 
Boss\\\",\\n  \\\"customerBirthday\\\": {\\\"year\\\": 1999, \\\"month\\\": 8, 
\\\"day\\\": 13},\\n  \\\"summary\\\": \\\"The customer, Kate Boss, needed to 
provide proof of insurance at the police station due to an accident. Initially, 
there was a misunderstanding regarding [...]
+    "headers" : {
+      "Date" : "Thu, 18 Dec 2025 13:25:52 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "3ac79428-f534-4e6a-aa8f-8e401ac22256",
+  "persistent" : true,
+  "insertionIndex" : 4
+}
\ No newline at end of file
diff --git 
a/data-extract-langchain4j/src/test/resources/mappings/api_chat-4a005fe6-e449-482d-8ce6-8c341fa4cb9f.json
 
b/data-extract-langchain4j/src/test/resources/mappings/api_chat-4a005fe6-e449-482d-8ce6-8c341fa4cb9f.json
new file mode 100644
index 00000000..269fdb3b
--- /dev/null
+++ 
b/data-extract-langchain4j/src/test/resources/mappings/api_chat-4a005fe6-e449-482d-8ce6-8c341fa4cb9f.json
@@ -0,0 +1,24 @@
+{
+  "id" : "4a005fe6-e449-482d-8ce6-8c341fa4cb9f",
+  "name" : "api_chat",
+  "request" : {
+    "url" : "/api/chat",
+    "method" : "POST",
+    "bodyPatterns" : [ {
+      "equalToJson" : "{\n  \"model\" : \"granite3.3:2b\",\n  \"messages\" : [ 
{\n    \"role\" : \"user\",\n    \"content\" : \"Extract information about a 
customer from the transcript delimited by triple backticks: ```Operator: Hello, 
how may I help you ?\\nCustomer: Hello, I'm John. I need to share a problem 
with you. Actually, the insurance has reimbursed only half the money I have 
spent due to the accident.\\nOperator: Hello John, could you please give me 
your last name so that I can [...]
+      "ignoreArrayOrder" : true,
+      "ignoreExtraElements" : true
+    } ]
+  },
+  "response" : {
+    "status" : 200,
+    "body" : 
"{\"model\":\"granite3.3:2b\",\"created_at\":\"2025-12-18T13:25:40.569059754Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n
  \\\"customerSatisfied\\\": false,\\n  \\\"customerName\\\": \\\"John 
Doe\\\",\\n  \\\"customerBirthday\\\": {\\\"year\\\": 2001, \\\"month\\\": 11, 
\\\"day\\\": 1},\\n  \\\"summary\\\": \\\"Customer, John Doe, is dissatisfied 
with being reimbursed only half the amount due to an accident, as the full 
reimbursement option was automatically can [...]
+    "headers" : {
+      "Date" : "Thu, 18 Dec 2025 13:25:40 GMT",
+      "Content-Type" : "application/json; charset=utf-8"
+    }
+  },
+  "uuid" : "4a005fe6-e449-482d-8ce6-8c341fa4cb9f",
+  "persistent" : true,
+  "insertionIndex" : 5
+}
\ No newline at end of file
diff --git 
a/data-extract-langchain4j/src/test/resources/mappings/api_chat-5dbaaf5e-5436-470c-a629-cee5ea860e64.json
 
b/data-extract-langchain4j/src/test/resources/mappings/api_chat-5dbaaf5e-5436-470c-a629-cee5ea860e64.json
deleted file mode 100644
index 4dcd006f..00000000
--- 
a/data-extract-langchain4j/src/test/resources/mappings/api_chat-5dbaaf5e-5436-470c-a629-cee5ea860e64.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-  "id" : "5dbaaf5e-5436-470c-a629-cee5ea860e64",
-  "name" : "api_chat",
-  "request" : {
-    "url" : "/api/chat",
-    "method" : "POST",
-    "bodyPatterns" : [ {
-      "equalToJson" : "{\n  \"model\" : \"granite3.3:2b\",\n  \"messages\" : [ 
{\n    \"role\" : \"user\",\n    \"content\" : \"Extract information about a 
customer from the text delimited by triple backticks: ```Operator: Hello, how 
may I help you ?\\nCustomer: Hello, I'm calling because I need to declare an 
accident on my main vehicle.\\nOperator: Ok, can you please give me your name 
?\\nCustomer: My name is Sarah London.\\nOperator: Could you please give me 
your birth date ?\\nCustome [...]
-      "ignoreArrayOrder" : true,
-      "ignoreExtraElements" : true
-    } ]
-  },
-  "response" : {
-    "status" : 200,
-    "body" : 
"{\"model\":\"granite3.3:2b\",\"created_at\":\"2025-09-01T09:21:30.815238592Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n\\\"customerSatisfied\\\":
 true,\\n\\\"customerName\\\": \\\"Sarah 
London\\\",\\n\\\"customerBirthday\\\": \\\"1986-07-10\\\",\\n\\\"summary\\\": 
\\\"The customer, Sarah London, is calling to declare an accident on her main 
vehicle and seek reimbursement for related 
expenses.\\\"\\n}\"},\"done_reason\":\"stop\",\"done\":true,\"total_duration\" 
[...]
-    "headers" : {
-      "Date" : "Mon, 01 Sep 2025 09:21:30 GMT",
-      "Content-Type" : "application/json; charset=utf-8"
-    }
-  },
-  "uuid" : "5dbaaf5e-5436-470c-a629-cee5ea860e64",
-  "persistent" : true,
-  "insertionIndex" : 6
-}
\ No newline at end of file
diff --git 
a/data-extract-langchain4j/src/test/resources/mappings/api_chat-a359a6fc-e37c-4383-a99c-efa92d6e650d.json
 
b/data-extract-langchain4j/src/test/resources/mappings/api_chat-a359a6fc-e37c-4383-a99c-efa92d6e650d.json
deleted file mode 100644
index 750cd181..00000000
--- 
a/data-extract-langchain4j/src/test/resources/mappings/api_chat-a359a6fc-e37c-4383-a99c-efa92d6e650d.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
-  "id" : "a359a6fc-e37c-4383-a99c-efa92d6e650d",
-  "name" : "api_chat",
-  "request" : {
-    "url" : "/api/chat",
-    "method" : "POST",
-    "bodyPatterns" : [ {
-      "equalToJson" : "{\n  \"model\" : \"granite3.3:2b\",\n  \"messages\" : [ 
{\n    \"role\" : \"user\",\n    \"content\" : \"Extract information about a 
customer from the text delimited by triple backticks: ```Operator: Hello, how 
may I help you?\\nCustomer: Hello, I am currently at the police station because 
I've got an accident. The police would need a proof that I have an insurance. 
Could you please help me?\\nOperator: Sure, could you please remind me your 
name and birth date?\\nC [...]
-      "ignoreArrayOrder" : true,
-      "ignoreExtraElements" : true
-    } ]
-  },
-  "response" : {
-    "status" : 200,
-    "body" : 
"{\"model\":\"granite3.3:2b\",\"created_at\":\"2025-09-01T09:21:46.990356099Z\",\"message\":{\"role\":\"assistant\",\"content\":\"{\\n\\\"customerSatisfied\\\":
 true,\\n\\\"customerName\\\": \\\"Kate Boss\\\",\\n\\\"customerBirthday\\\": 
\\\"1999-08-13\\\",\\n\\\"summary\\\": \\\"Customer Kate Boss sought assistance 
from the operator at a police station to provide proof of insurance following 
an accident. Initially, her name was mispronounced as Hart due to marriage, but 
she [...]
-    "headers" : {
-      "Date" : "Mon, 01 Sep 2025 09:21:46 GMT",
-      "Content-Type" : "application/json; charset=utf-8"
-    }
-  },
-  "uuid" : "a359a6fc-e37c-4383-a99c-efa92d6e650d",
-  "persistent" : true,
-  "insertionIndex" : 4
-}
\ No newline at end of file

Reply via email to