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

orpiske pushed a commit to branch camel-4.10.x
in repository https://gitbox.apache.org/repos/asf/camel.git

commit a95be3262743667ca9e51fd457a459a3c515219d
Author: Otavio Rodolfo Piske <angusyo...@gmail.com>
AuthorDate: Tue Apr 1 16:46:32 2025 +0200

    CAMEL-21923: LLM call should include all tools at the end of the flow
---
 .../tools/LangChain4jToolsProducer.java            | 48 ++++++++++++++++------
 1 file changed, 36 insertions(+), 12 deletions(-)

diff --git 
a/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsProducer.java
 
b/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsProducer.java
index 13aa4a1b42e..6a68d09b371 100644
--- 
a/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsProducer.java
+++ 
b/components/camel-ai/camel-langchain4j-tools/src/main/java/org/apache/camel/component/langchain4j/tools/LangChain4jToolsProducer.java
@@ -29,6 +29,7 @@ import dev.langchain4j.data.message.AiMessage;
 import dev.langchain4j.data.message.ChatMessage;
 import dev.langchain4j.data.message.ToolExecutionResultMessage;
 import dev.langchain4j.model.chat.ChatLanguageModel;
+import dev.langchain4j.model.output.FinishReason;
 import dev.langchain4j.model.output.Response;
 import org.apache.camel.Exchange;
 import org.apache.camel.InvalidPayloadException;
@@ -36,8 +37,11 @@ import 
org.apache.camel.component.langchain4j.tools.spec.CamelToolExecutorCache;
 import 
org.apache.camel.component.langchain4j.tools.spec.CamelToolSpecification;
 import org.apache.camel.support.DefaultProducer;
 import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class LangChain4jToolsProducer extends DefaultProducer {
+    private static final Logger LOG = 
LoggerFactory.getLogger(LangChain4jToolsProducer.class);
 
     private final LangChain4jToolsEndpoint endpoint;
 
@@ -99,25 +103,45 @@ public class LangChain4jToolsProducer extends 
DefaultProducer {
         }
 
         // First talk to the model to get the tools to be called
+        int i = 0;
         do {
-            final Response<AiMessage> response = 
chatWithLLMForTools(chatMessages, toolPair, exchange);
-            if (!response.content().hasToolExecutionRequests()) {
+            LOG.debug("Starting iteration {}", i);
+            final Response<AiMessage> response = chatWithLLM(chatMessages, 
toolPair, exchange);
+            if (isDoneExecuting(response)) {
                 return extractAiResponse(response);
             }
 
-            // Then, talk again to call the tools and compute the final 
response
-            final Response<AiMessage> toolsCallResponse = 
chatWithLLMForToolCalling(chatMessages, exchange, response, toolPair);
-            if (!toolsCallResponse.content().hasToolExecutionRequests()) {
-                return extractAiResponse(toolsCallResponse);
+            // Only invoke the tools ... the response will be computed on the 
next loop
+            invokeTools(chatMessages, exchange, response, toolPair);
+            LOG.debug("Finished iteration {}", i);
+            i++;
+        } while (true);
+    }
+
+    private boolean isDoneExecuting(Response<AiMessage> response) {
+        if (!response.content().hasToolExecutionRequests()) {
+            LOG.info("Finished executing tools because of there are no more 
execution requests");
+            return true;
+        }
+
+        if (response.finishReason() != null) {
+            LOG.info("Finished executing tools because of {}", 
response.finishReason());
+
+            if (response.finishReason() == FinishReason.STOP) {
+                return true;
             }
+        }
 
-        } while (true);
+        return false;
     }
 
-    private Response<AiMessage> chatWithLLMForToolCalling(
+    private void invokeTools(
             List<ChatMessage> chatMessages, Exchange exchange, 
Response<AiMessage> response, ToolPair toolPair) {
-        for (ToolExecutionRequest toolExecutionRequest : 
response.content().toolExecutionRequests()) {
+        int i = 0;
+        List<ToolExecutionRequest> toolExecutionRequests = 
response.content().toolExecutionRequests();
+        for (ToolExecutionRequest toolExecutionRequest : 
toolExecutionRequests) {
             String toolName = toolExecutionRequest.name();
+            LOG.info("Invoking tool {} ({}) of {}", i, toolName, 
toolExecutionRequests.size());
 
             final CamelToolSpecification camelToolSpecification = 
toolPair.callableTools().stream()
                     .filter(c -> 
c.getToolSpecification().name().equals(toolName)).findFirst().get();
@@ -130,7 +154,9 @@ public class LangChain4jToolsProducer extends 
DefaultProducer {
                         .forEachRemaining(name -> 
exchange.getMessage().setHeader(name, jsonNode.get(name)));
 
                 // Execute the consumer route
+
                 
camelToolSpecification.getConsumer().getProcessor().process(exchange);
+                i++;
             } catch (Exception e) {
                 // How to handle this exception?
                 exchange.setException(e);
@@ -141,8 +167,6 @@ public class LangChain4jToolsProducer extends 
DefaultProducer {
                     toolExecutionRequest.name(),
                     exchange.getIn().getBody(String.class)));
         }
-
-        return this.chatLanguageModel.generate(chatMessages);
     }
 
     /**
@@ -153,7 +177,7 @@ public class LangChain4jToolsProducer extends 
DefaultProducer {
      * @param  toolPair     the toolPair containing the available tools to be 
called
      * @return              the response provided by the model
      */
-    private Response<AiMessage> chatWithLLMForTools(List<ChatMessage> 
chatMessages, ToolPair toolPair, Exchange exchange) {
+    private Response<AiMessage> chatWithLLM(List<ChatMessage> chatMessages, 
ToolPair toolPair, Exchange exchange) {
         Response<AiMessage> response = 
this.chatLanguageModel.generate(chatMessages, toolPair.toolSpecifications());
 
         if (!response.content().hasToolExecutionRequests()) {

Reply via email to