= LangChain4j Chat Component
:doctitle: LangChain4j Chat
:shortname: langchain4j-chat
:artifactid: camel-langchain4j-chat
:description: LangChain4j Chat component
:since: 4.5
:supportlevel: Stable
:tabs-sync-option:
:component-header: Both producer and consumer are supported
//Manually maintained attributes
:group: AI
:camel-spring-boot-name: langchain4j-chat

*Since Camel {since}*

*{component-header}*

The LangChain4j Chat Component allows you to integrate with any Large Language Model (LLM) supported by https://github.com/langchain4j/langchain4j[LangChain4j].

Maven users will need to add the following dependency to their `pom.xml`
for this component:

[source,xml]
----
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-langchain4j-chat</artifactId>
    <version>x.x.x</version>
    <!-- use the same version as your Camel core version -->
</dependency>
----

== URI format

----
langchain4j-chat:chatIdId[?options]
----

Where *chatId* can be any string to uniquely identify the endpoint


// component-configure options: START

// component-configure options: END

// component options: START
include::partial$component-configure-options.adoc[]
include::partial$component-endpoint-options.adoc[]
// component options: END

// endpoint options: START

// endpoint options: END

// component headers: START
include::partial$component-endpoint-headers.adoc[]
// component headers: END

include::spring-boot:partial$starter.adoc[]

== Usage

=== Using a specific Chat Model

The Camel LangChain4j chat component provides an abstraction for interacting with various types of Large Language Models (LLMs) supported by https://github.com/langchain4j/langchain4j[LangChain4j].

==== Integrating with specific LLM

To integrate with a specific LLM, users should follow the steps described below, which explain
how to integrate with OpenAI.

Add the dependency for LangChain4j OpenAI support:

.Example
[source,xml]
----
<dependency>
      <groupId>dev.langchain4j</groupId>
      <artifactId>langchain4j-open-ai</artifactId>
    <version>x.x.x</version>
</dependency>
----

Initialize the OpenAI Chat Language Model, and add it to the Camel Registry:

[source, java]
----
ChatLanguageModel model = OpenAiChatModel.builder()
                .apiKey(openApiKey)
                .modelName(GPT_3_5_TURBO)
                .temperature(0.3)
                .timeout(ofSeconds(3000))
                .build();
context.getRegistry().bind("chatModel", model);
----

Use the model in the Camel LangChain4j Chat Producer

[source, java]
----
 from("direct:chat")
      .to("langchain4j-chat:test?chatModel=#chatModel")

----

[NOTE]
====
To switch to another Large Language Model and its corresponding dependency, replace the `langchain4j-open-ai` dependency with the appropriate dependency for the desired model. Update the initialization parameters accordingly in the code snippet provided above.
====

=== Send a prompt with variables

To send a prompt with variables, use the Operation type `LangChain4jChatOperations.CHAT_SINGLE_MESSAGE_WITH_PROMPT`.
This operation allows you to send a single prompt message with dynamic variables, which will be replaced with values provided in the request.

.Route example:
[source, java]
----
 from("direct:chat")
      .to("langchain4j-chat:test?chatModel=#chatModel&chatOperation=CHAT_SINGLE_MESSAGE_WITH_PROMPT")

----

.Usage example:
[source, java]
----
var promptTemplate = "Create a recipe for a {{dishType}} with the following ingredients: {{ingredients}}";

Map<String, Object> variables = new HashMap<>();
variables.put("dishType", "oven dish");
variables.put("ingredients", "potato, tomato, feta, olive oil");

String response = template.requestBodyAndHeader("direct:chat", variables,
                LangChain4jChat.Headers.PROMPT_TEMPLATE, promptTemplate, String.class);
----

=== Chat with history

You can send a new prompt along with the chat message history by passing all messages in a list of type `dev.langchain4j.data.message.ChatMessage`.
Use the Operation type `LangChain4jChatOperations.CHAT_MULTIPLE_MESSAGES`.
This operation allows you to continue the conversation with the context of previous messages.

.Route example:
[source, java]
----
 from("direct:chat")
      .to("langchain4j-chat:test?chatModel=#chatModel&chatOperation=CHAT_MULTIPLE_MESSAGES")

----

.Usage example:
[source, java]
----
List<ChatMessage> messages = new ArrayList<>();
messages.add(new SystemMessage("You are asked to provide recommendations for a restaurant based on user reviews."));
// Add more chat messages as needed

String response = template.requestBody("direct:send-multiple", messages, String.class);
----

=== Chat with Tool

IMPORTANT: as of Camel 4.8.0 this feature is deprecated. Users should use the xref:langchain4j-tools-component.adoc[LangChain4j Tool component].

Camel langchain4j-chat component as a consumer can be used to implement a LangChain tool.
Right now tools are supported only via the OpenAiChatModel backed by OpenAI APIs.

Tool Input parameter can be defined as an Endpoint multiValue option in the form of `parameter.<name>=<type>`,
or via the endpoint option `camelToolParameter` for a programmatic approach.
The parameters can be found as headers in the consumer route, in particular, if you define `parameter.userId=5`,
in the consumer route `${header.userId}` can be used.

.Producer and consumer example:
[source, java]
----
from("direct:test")
    .to("langchain4j-chat:test1?chatOperation=CHAT_MULTIPLE_MESSAGES");

from("langchain4j-chat:test1?description=Query user database by number&parameter.number=integer")
    .to("sql:SELECT name FROM users WHERE id = :#number");
----

.Usage example:
[source, java]
----
List<ChatMessage> messages = new ArrayList<>();
        messages.add(new SystemMessage("""
                You provide information about specific user name querying the database given a number.
                """));
        messages.add(new UserMessage("""
                What is the name of the user 1?
                """));

        Exchange message = fluentTemplate.to("direct:test").withBody(messages).request(Exchange.class);
----

=== Retrieval Augmented Generation (RAG)

Use the RAG feature to enrich exchanges with data retrieved from any type of Camel endpoint. The feature is compatible with all LangChain4 Chat operations and is ideal for orchestrating the RAG workflow, utilizing the extensive library of components and Enterprise Integration Patterns (EIPs) available in Apache Camel.

There are two ways for utilizing the RAG feature:

==== Using RAG with Content Enricher and LangChain4jRagAggregatorStrategy
Enrich the exchange by retrieving a list of strings using any Camel producer. The `LangChain4jRagAggregatorStrategy` is specifically designed to augment data within LangChain4j chat producers.

.Usage example:
[source, java]
----
// Create an instance of the RAG aggregator strategy
LangChain4jRagAggregatorStrategy aggregatorStrategy = new LangChain4jRagAggregatorStrategy();

from("direct:test")
     .enrich("direct:rag", aggregatorStrategy)
     .to("langchain4j-chat:test1?chatOperation=CHAT_SIMPLE_MESSAGE");

  from("direct:rag")
          .process(exchange -> {
                List<String> augmentedData = List.of("data 1", "data 2" );
                exchange.getIn().setBody(augmentedData);
              });
----

[NOTE]
====
This method leverages a separate Camel route to fetch and process the augmented data.
====

It is possible to enrich the message from multiple sources within the same exchange.

.Usage example:
[source, java]
----
// Create an instance of the RAG aggregator strategy
LangChain4jRagAggregatorStrategy aggregatorStrategy = new LangChain4jRagAggregatorStrategy();

from("direct:test")
     .enrich("direct:rag-from-source-1", aggregatorStrategy)
     .enrich("direct:rag-from-source-2", aggregatorStrategy)
     .to("langchain4j-chat:test1?chatOperation=CHAT_SIMPLE_MESSAGE");
----

==== Using RAG with headers

Directly add augmented data into the header. This method is particularly efficient for straightforward use cases where the augmented data is predefined or static.
You must add augmented data as a List of `dev.langchain4j.rag.content.Content` directly inside the header `CamelLangChain4jChatAugmentedData`.

.Usage example:
[source, java]
----
import dev.langchain4j.rag.content.Content;

...

Content augmentedContent = new Content("data test");
List<Content> contents = List.of(augmentedContent);

String response = template.requestBodyAndHeader("direct:send-multiple", messages, LangChain4jChat.Headers.AUGMENTED_DATA , contents, String.class);
----
