Make FunctionCallingOptions collections immutable

Prevent external modification of internal state by returning unmodifiable
collections and adding defensive copies in setters and builders.

Co-authored-by: youngmoneee@users.noreply.github.com
This commit is contained in:
Mark Pollack
2024-10-22 16:52:55 -04:00
committed by Christian Tzolov
parent c544d0c0a9
commit cf75640c86

View File

@@ -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 class FunctionCallingOptionsBuilder {
public FunctionCallingOptionsBuilder withToolContext(Map<String, Object> context) {
Assert.notNull(context, "Tool context must not be null");
this.options.getToolContext().putAll(context);
Map<String, Object> 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<String, Object> newContext = new HashMap<>(this.options.getToolContext());
newContext.put(key, value);
this.options.setToolContext(newContext);
return this;
}
@@ -158,22 +163,22 @@ public class FunctionCallingOptionsBuilder {
@Override
public List<FunctionCallback> getFunctionCallbacks() {
return this.functionCallbacks;
return Collections.unmodifiableList(this.functionCallbacks);
}
public void setFunctionCallbacks(List<FunctionCallback> functionCallbacks) {
Assert.notNull(functionCallbacks, "FunctionCallbacks must not be null");
this.functionCallbacks = functionCallbacks;
this.functionCallbacks = new ArrayList<>(functionCallbacks);
}
@Override
public Set<String> getFunctions() {
return this.functions;
return Collections.unmodifiableSet(this.functions);
}
public void setFunctions(Set<String> functions) {
Assert.notNull(functions, "Functions must not be null");
this.functions = functions;
this.functions = new HashSet<>(functions);
}
@Override
@@ -258,11 +263,12 @@ public class FunctionCallingOptionsBuilder {
}
public Map<String, Object> getToolContext() {
return context;
return Collections.unmodifiableMap(this.context);
}
public void setToolContext(Map<String, Object> context) {
this.context = context;
Assert.notNull(context, "Context must not be null");
this.context = new HashMap<>(context);
}
@Override
@@ -271,14 +277,14 @@ public class FunctionCallingOptionsBuilder {
.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();
}