Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(WIP) CAMEL-21503: remove the tools feature from the chat component #16425

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,16 @@
package org.apache.camel.component.langchain4j.chat;

import java.util.Map;
import java.util.UUID;

import dev.langchain4j.agent.tool.JsonSchemaProperty;
import dev.langchain4j.agent.tool.ToolSpecification;
import org.apache.camel.Category;
import org.apache.camel.Consumer;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.component.langchain4j.chat.tool.CamelSimpleToolParameter;
import org.apache.camel.component.langchain4j.chat.tool.CamelToolExecutorCache;
import org.apache.camel.component.langchain4j.chat.tool.CamelToolSpecification;
import org.apache.camel.component.langchain4j.chat.tool.NamedJsonSchemaProperty;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.spi.UriParam;
import org.apache.camel.spi.UriPath;
import org.apache.camel.support.DefaultEndpoint;
import org.apache.camel.util.StringHelper;

import static org.apache.camel.component.langchain4j.chat.LangChain4jChat.SCHEME;

Expand All @@ -60,10 +52,6 @@ public class LangChain4jChatEndpoint extends DefaultEndpoint {
multiValue = true, enums = "string,integer,number,object,array,boolean,null")
private Map<String, String> parameters;

@Metadata(label = "consumer,advanced")
@UriParam(description = "Tool's Camel Parameters, programmatically define Tool description and parameters")
private CamelSimpleToolParameter camelToolParameter;

public LangChain4jChatEndpoint(String uri, LangChain4jChatComponent component, String chatId,
LangChain4jChatConfiguration configuration) {
super(uri, component);
Expand All @@ -78,44 +66,7 @@ public Producer createProducer() throws Exception {

@Override
public Consumer createConsumer(Processor processor) throws Exception {
ToolSpecification.Builder toolSpecificationBuilder = ToolSpecification.builder();
toolSpecificationBuilder.name(UUID.randomUUID().toString());
if (camelToolParameter != null) {
toolSpecificationBuilder.description(camelToolParameter.getDescription());

for (NamedJsonSchemaProperty namedJsonSchemaProperty : camelToolParameter.getProperties()) {
toolSpecificationBuilder.addParameter(namedJsonSchemaProperty.getName(),
namedJsonSchemaProperty.getProperties());
}
} else if (description != null) {
toolSpecificationBuilder.description(description);

if (parameters != null) {
parameters.forEach((name, type) -> toolSpecificationBuilder.addParameter(name, JsonSchemaProperty.type(type)));
}
} else {
// Consumer without toolParameter or description
throw new IllegalArgumentException(
"In order to use the langchain4j component as a consumer, you need to specify at least description, or a camelToolParameter");
}

String simpleDescription = null;
if (description != null) {
simpleDescription = StringHelper.dashToCamelCase(description.replace(" ", "-"));
}

ToolSpecification toolSpecification = toolSpecificationBuilder
.name(simpleDescription)
.build();

final LangChain4jChatConsumer langChain4jChatConsumer = new LangChain4jChatConsumer(this, processor);
configureConsumer(langChain4jChatConsumer);

CamelToolSpecification camelToolSpecification
= new CamelToolSpecification(toolSpecification, langChain4jChatConsumer);
CamelToolExecutorCache.getInstance().put(chatId, camelToolSpecification);

return camelToolSpecification.getConsumer();
throw new UnsupportedOperationException("Consumer not supported");
}

/**
Expand Down Expand Up @@ -147,18 +98,8 @@ public void setParameters(Map<String, String> parameters) {
this.parameters = parameters;
}

public CamelSimpleToolParameter getCamelToolParameter() {
return camelToolParameter;
}

public void setCamelToolParameter(CamelSimpleToolParameter camelToolParameter) {
this.camelToolParameter = camelToolParameter;
}

@Override
protected void doStop() throws Exception {
super.doStop();

CamelToolExecutorCache.getInstance().getTools().clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,10 @@

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.langchain4j.agent.tool.ToolExecutionRequest;
import dev.langchain4j.agent.tool.ToolSpecification;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.ToolExecutionResultMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.input.Prompt;
Expand All @@ -39,8 +33,6 @@
import org.apache.camel.Exchange;
import org.apache.camel.InvalidPayloadException;
import org.apache.camel.NoSuchHeaderException;
import org.apache.camel.component.langchain4j.chat.tool.CamelToolExecutorCache;
import org.apache.camel.component.langchain4j.chat.tool.CamelToolSpecification;
import org.apache.camel.support.DefaultProducer;
import org.apache.camel.util.ObjectHelper;

Expand Down Expand Up @@ -171,52 +163,7 @@ private String sendListChatMessage(List<ChatMessage> chatMessages, Exchange exch

}

final Map<String, Set<CamelToolSpecification>> tools = CamelToolExecutorCache.getInstance().getTools();
if (tools.containsKey(langChain4jChatEndpoint.getChatId())) {
final Set<CamelToolSpecification> camelToolSpecificationSet = tools
.get(langChain4jChatEndpoint.getChatId());

final List<ToolSpecification> toolSpecifications = camelToolSpecificationSet.stream()
.map(camelToolSpecification -> camelToolSpecification.getToolSpecification())
.collect(Collectors.toList());

response = this.chatLanguageModel.generate(chatMessages, toolSpecifications);
} else {
response = this.chatLanguageModel.generate(chatMessages);
}

if (response.content().hasToolExecutionRequests()) {
chatMessages.add(response.content());

for (ToolExecutionRequest toolExecutionRequest : response.content().toolExecutionRequests()) {
String toolName = toolExecutionRequest.name();
CamelToolSpecification camelToolSpecification = CamelToolExecutorCache.getInstance().getTools()
.get(langChain4jChatEndpoint.getChatId()).stream()
.filter(cts -> cts.getToolSpecification().name().equals(toolName))
.findFirst().orElseThrow(() -> new RuntimeException("Tool " + toolName + " not found"));
try {
// Map Json to Header
JsonNode jsonNode = objectMapper.readValue(toolExecutionRequest.arguments(), JsonNode.class);

jsonNode.fieldNames()
.forEachRemaining(name -> exchange.getMessage().setHeader(name, jsonNode.get(name)));

// Execute the consumer route
camelToolSpecification.getConsumer().getProcessor().process(exchange);
} catch (Exception e) {
// How to handle this exception?
exchange.setException(e);
}

chatMessages.add(new ToolExecutionResultMessage(
toolExecutionRequest.id(),
toolExecutionRequest.name(),
exchange.getIn().getBody(String.class)));
}

response = this.chatLanguageModel.generate(chatMessages);
}

response = this.chatLanguageModel.generate(chatMessages);
return extractAiResponse(response);
}

Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading