diff --git a/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallingOptionsBuilder.java b/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallingOptionsBuilder.java index 685618da51..28346f3927 100644 --- a/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallingOptionsBuilder.java +++ b/spring-ai-core/src/main/java/org/springframework/ai/model/function/FunctionCallingOptionsBuilder.java @@ -16,6 +16,7 @@ package org.springframework.ai.model.function; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -111,14 +112,18 @@ public FunctionCallingOptionsBuilder withProxyToolCalls(Boolean proxyToolCalls) public FunctionCallingOptionsBuilder withToolContext(Map context) { Assert.notNull(context, "Tool context must not be null"); - this.options.getToolContext().putAll(context); + Map newContext = new HashMap<>(this.options.getToolContext()); + newContext.putAll(context); + this.options.setToolContext(newContext); return this; } public FunctionCallingOptionsBuilder withToolContext(String key, Object value) { Assert.notNull(key, "Key must not be null"); Assert.notNull(value, "Value must not be null"); - this.options.getToolContext().put(key, value); + Map newContext = new HashMap<>(this.options.getToolContext()); + newContext.put(key, value); + this.options.setToolContext(newContext); return this; } @@ -158,22 +163,22 @@ public static FunctionCallingOptionsBuilder builder() { @Override public List getFunctionCallbacks() { - return this.functionCallbacks; + return Collections.unmodifiableList(this.functionCallbacks); } public void setFunctionCallbacks(List functionCallbacks) { Assert.notNull(functionCallbacks, "FunctionCallbacks must not be null"); - this.functionCallbacks = functionCallbacks; + this.functionCallbacks = new ArrayList<>(functionCallbacks); } @Override public Set getFunctions() { - return this.functions; + return Collections.unmodifiableSet(this.functions); } public void setFunctions(Set functions) { Assert.notNull(functions, "Functions must not be null"); - this.functions = functions; + this.functions = new HashSet<>(functions); } @Override @@ -258,11 +263,12 @@ public void setProxyToolCalls(Boolean proxyToolCalls) { } public Map getToolContext() { - return context; + return Collections.unmodifiableMap(this.context); } public void setToolContext(Map context) { - this.context = context; + Assert.notNull(context, "Context must not be null"); + this.context = new HashMap<>(context); } @Override @@ -271,14 +277,14 @@ public ChatOptions copy() { .withFrequencyPenalty(this.frequencyPenalty) .withMaxTokens(this.maxTokens) .withPresencePenalty(this.presencePenalty) - .withStopSequences(this.stopSequences) + .withStopSequences(this.stopSequences != null ? new ArrayList<>(this.stopSequences) : null) .withTemperature(this.temperature) .withTopK(this.topK) .withTopP(this.topP) - .withFunctions(this.functions) - .withFunctionCallbacks(this.functionCallbacks) + .withFunctions(new HashSet<>(this.functions)) + .withFunctionCallbacks(new ArrayList<>(this.functionCallbacks)) .withProxyToolCalls(this.proxyToolCalls) - .withToolContext(this.getToolContext()) + .withToolContext(new HashMap<>(this.getToolContext())) .build(); }