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