Skip to content
Open
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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import java.util.List;

import dev.langchain4j.mcp.McpToolProvider;
import dev.langchain4j.model.chat.request.ChatRequestParameters;
import dev.langchain4j.model.chat.request.DefaultChatRequestParameters;
import dev.langchain4j.model.chat.request.ResponseFormat;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.tool.ToolProvider;
import org.apache.camel.util.ObjectHelper;
Expand All @@ -45,6 +48,7 @@
public abstract class AbstractAgent<S> implements Agent {

protected final AgentConfiguration configuration;
private ResponseFormat responseFormat;

protected AbstractAgent(AgentConfiguration configuration) {
this.configuration = configuration;
Expand All @@ -59,6 +63,24 @@ protected AgentConfiguration getConfiguration() {
return configuration;
}

/**
* Gets the response format for structured output.
*
* @return the response format, or {@code null} if not configured
*/
public ResponseFormat getResponseFormat() {
return responseFormat;
}

/**
* Sets the response format for structured output (JSON schema).
*
* @param responseFormat the langchain4j response format to apply to AI service requests
*/
public void setResponseFormat(ResponseFormat responseFormat) {
this.responseFormat = responseFormat;
}

/**
* Configures the common aspects of the AI service builder.
*
Expand Down Expand Up @@ -125,5 +147,19 @@ protected void configureBuilder(AiServices<S> builder, ToolProvider toolProvider
if (configuration.getOutputGuardrailClasses() != null && !configuration.getOutputGuardrailClasses().isEmpty()) {
builder.outputGuardrailClasses((List) configuration.getOutputGuardrailClasses());
}

// Response Format (structured output / JSON schema)
// Temporary fix: see https://issues.apache.org/jira/browse/CAMEL-23695
if (responseFormat != null) {
ResponseFormat format = responseFormat;
builder.chatRequestTransformer(req -> {
ChatRequestParameters existing = req.parameters();
ChatRequestParameters withFormat = existing != null
? existing.overrideWith(
DefaultChatRequestParameters.builder().responseFormat(format).build())
: DefaultChatRequestParameters.builder().responseFormat(format).build();
return req.toBuilder().parameters(withFormat).build();
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
case "autowiredenabled":
case "autowiredEnabled": target.setAutowiredEnabled(property(camelContext, boolean.class, value)); return true;
case "configuration": target.setConfiguration(property(camelContext, org.apache.camel.component.langchain4j.agent.LangChain4jAgentConfiguration.class, value)); return true;
case "jsonschema":
case "jsonSchema": getOrCreateConfiguration(target).setJsonSchema(property(camelContext, java.lang.String.class, value)); return true;
case "lazystartproducer":
case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
case "mcpclients":
Expand Down Expand Up @@ -65,6 +67,8 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
case "autowiredenabled":
case "autowiredEnabled": return boolean.class;
case "configuration": return org.apache.camel.component.langchain4j.agent.LangChain4jAgentConfiguration.class;
case "jsonschema":
case "jsonSchema": return java.lang.String.class;
case "lazystartproducer":
case "lazyStartProducer": return boolean.class;
case "mcpclients":
Expand All @@ -88,6 +92,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
case "autowiredenabled":
case "autowiredEnabled": return target.isAutowiredEnabled();
case "configuration": return target.getConfiguration();
case "jsonschema":
case "jsonSchema": return getOrCreateConfiguration(target).getJsonSchema();
case "lazystartproducer":
case "lazyStartProducer": return target.isLazyStartProducer();
case "mcpclients":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
case "agentConfiguration": target.setAgentConfiguration(property(camelContext, org.apache.camel.component.langchain4j.agent.api.AgentConfiguration.class, value)); return true;
case "agentfactory":
case "agentFactory": target.setAgentFactory(property(camelContext, org.apache.camel.component.langchain4j.agent.api.AgentFactory.class, value)); return true;
case "jsonschema":
case "jsonSchema": target.setJsonSchema(property(camelContext, java.lang.String.class, value)); return true;
case "mcpclients":
case "mcpClients": target.setMcpClients(property(camelContext, java.util.List.class, value)); return true;
case "mcpserver":
Expand All @@ -45,6 +47,8 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
case "agentConfiguration": return org.apache.camel.component.langchain4j.agent.api.AgentConfiguration.class;
case "agentfactory":
case "agentFactory": return org.apache.camel.component.langchain4j.agent.api.AgentFactory.class;
case "jsonschema":
case "jsonSchema": return java.lang.String.class;
case "mcpclients":
case "mcpClients": return java.util.List.class;
case "mcpserver":
Expand All @@ -63,6 +67,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
case "agentConfiguration": return target.getAgentConfiguration();
case "agentfactory":
case "agentFactory": return target.getAgentFactory();
case "jsonschema":
case "jsonSchema": return target.getJsonSchema();
case "mcpclients":
case "mcpClients": return target.getMcpClients();
case "mcpserver":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj
case "agentConfiguration": target.getConfiguration().setAgentConfiguration(property(camelContext, org.apache.camel.component.langchain4j.agent.api.AgentConfiguration.class, value)); return true;
case "agentfactory":
case "agentFactory": target.getConfiguration().setAgentFactory(property(camelContext, org.apache.camel.component.langchain4j.agent.api.AgentFactory.class, value)); return true;
case "jsonschema":
case "jsonSchema": target.getConfiguration().setJsonSchema(property(camelContext, java.lang.String.class, value)); return true;
case "lazystartproducer":
case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
case "mcpclients":
Expand All @@ -52,6 +54,8 @@ public Class<?> getOptionType(String name, boolean ignoreCase) {
case "agentConfiguration": return org.apache.camel.component.langchain4j.agent.api.AgentConfiguration.class;
case "agentfactory":
case "agentFactory": return org.apache.camel.component.langchain4j.agent.api.AgentFactory.class;
case "jsonschema":
case "jsonSchema": return java.lang.String.class;
case "lazystartproducer":
case "lazyStartProducer": return boolean.class;
case "mcpclients":
Expand All @@ -72,6 +76,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
case "agentConfiguration": return target.getConfiguration().getAgentConfiguration();
case "agentfactory":
case "agentFactory": return target.getConfiguration().getAgentFactory();
case "jsonschema":
case "jsonSchema": return target.getConfiguration().getJsonSchema();
case "lazystartproducer":
case "lazyStartProducer": return target.isLazyStartProducer();
case "mcpclients":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ public class LangChain4jAgentEndpointUriFactory extends org.apache.camel.support
private static final Set<String> ENDPOINT_IDENTITY_PROPERTY_NAMES;
private static final Map<String, String> MULTI_VALUE_PREFIXES;
static {
Set<String> props = new HashSet<>(8);
Set<String> props = new HashSet<>(9);
props.add("agent");
props.add("agentConfiguration");
props.add("agentFactory");
props.add("agentId");
props.add("jsonSchema");
props.add("lazyStartProducer");
props.add("mcpClients");
props.add("mcpServer");
Expand Down
Loading