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-examples.git
commit a259408c0f69379dfa00ae618b2a2b367edf2602 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
