Skip to content

Commit 5f25cf9

Browse files
authored
[ML] Filter empty task settings objects from the API response (#114389)
Inference endpoints that do not define task settings or where there are no defaults return an empty task_setting object. Filter this object from the response
1 parent ee5be48 commit 5f25cf9

File tree

57 files changed

+263
-30
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+263
-30
lines changed

docs/changelog/114389.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 114389
2+
summary: Filter empty task settings objects from the API response
3+
area: Machine Learning
4+
type: enhancement
5+
issues: []

server/src/main/java/org/elasticsearch/inference/EmptyTaskSettings.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ public EmptyTaskSettings(StreamInput in) {
2929
this();
3030
}
3131

32+
@Override
33+
public boolean isEmpty() {
34+
return true;
35+
}
36+
3237
@Override
3338
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
3439
builder.startObject();

server/src/main/java/org/elasticsearch/inference/ModelConfigurations.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,11 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
173173
builder.field(TaskType.NAME, taskType.toString());
174174
builder.field(SERVICE, service);
175175
builder.field(SERVICE_SETTINGS, serviceSettings);
176-
builder.field(TASK_SETTINGS, taskSettings);
176+
// Always write task settings to the index even if empty.
177+
// But do not show empty settings in the response
178+
if (params.paramAsBoolean(USE_ID_FOR_INDEX, false) || (taskSettings != null && taskSettings.isEmpty() == false)) {
179+
builder.field(TASK_SETTINGS, taskSettings);
180+
}
177181
if (chunkingSettings != null) {
178182
builder.field(CHUNKING_SETTINGS, chunkingSettings);
179183
}
@@ -192,7 +196,11 @@ public XContentBuilder toFilteredXContent(XContentBuilder builder, Params params
192196
builder.field(TaskType.NAME, taskType.toString());
193197
builder.field(SERVICE, service);
194198
builder.field(SERVICE_SETTINGS, serviceSettings.getFilteredXContentObject());
195-
builder.field(TASK_SETTINGS, taskSettings);
199+
// Always write task settings to the index even if empty.
200+
// But do not show empty settings in the response
201+
if (params.paramAsBoolean(USE_ID_FOR_INDEX, false) || (taskSettings != null && taskSettings.isEmpty() == false)) {
202+
builder.field(TASK_SETTINGS, taskSettings);
203+
}
196204
if (chunkingSettings != null) {
197205
builder.field(CHUNKING_SETTINGS, chunkingSettings);
198206
}

server/src/main/java/org/elasticsearch/inference/TaskSettings.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@
1212
import org.elasticsearch.common.io.stream.VersionedNamedWriteable;
1313
import org.elasticsearch.xcontent.ToXContentObject;
1414

15-
public interface TaskSettings extends ToXContentObject, VersionedNamedWriteable {}
15+
public interface TaskSettings extends ToXContentObject, VersionedNamedWriteable {
16+
boolean isEmpty();
17+
}

x-pack/plugin/inference/qa/mixed-cluster/src/javaRestTest/java/org/elasticsearch/xpack/inference/qa/mixed/OpenAIServiceMixedIT.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@
1919
import java.util.List;
2020
import java.util.Map;
2121

22+
import static org.hamcrest.Matchers.anEmptyMap;
23+
import static org.hamcrest.Matchers.anyOf;
2224
import static org.hamcrest.Matchers.containsString;
2325
import static org.hamcrest.Matchers.empty;
2426
import static org.hamcrest.Matchers.hasEntry;
2527
import static org.hamcrest.Matchers.hasSize;
2628
import static org.hamcrest.Matchers.not;
29+
import static org.hamcrest.Matchers.nullValue;
2730

2831
public class OpenAIServiceMixedIT extends BaseMixedTestCase {
2932

@@ -118,14 +121,13 @@ public void testOpenAiCompletions() throws IOException {
118121
put(inferenceId, chatCompletionsConfig(getUrl(openAiChatCompletionsServer)), TaskType.COMPLETION);
119122

120123
var configsMap = get(TaskType.COMPLETION, inferenceId);
121-
logger.warn("Configs: {}", configsMap);
122124
var configs = (List<Map<String, Object>>) configsMap.get("endpoints");
123125
assertThat(configs, hasSize(1));
124126
assertEquals("openai", configs.get(0).get("service"));
125127
var serviceSettings = (Map<String, Object>) configs.get(0).get("service_settings");
126128
assertThat(serviceSettings, hasEntry("model_id", "gpt-4"));
127129
var taskSettings = (Map<String, Object>) configs.get(0).get("task_settings");
128-
assertThat(taskSettings.keySet(), empty());
130+
assertThat(taskSettings, anyOf(nullValue(), anEmptyMap()));
129131

130132
assertCompletionInference(inferenceId);
131133
}

x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/CohereServiceUpgradeIT.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@
2222
import java.util.List;
2323
import java.util.Map;
2424

25+
import static org.hamcrest.Matchers.anEmptyMap;
26+
import static org.hamcrest.Matchers.anyOf;
2527
import static org.hamcrest.Matchers.empty;
2628
import static org.hamcrest.Matchers.hasEntry;
2729
import static org.hamcrest.Matchers.hasSize;
2830
import static org.hamcrest.Matchers.not;
31+
import static org.hamcrest.Matchers.nullValue;
2932
import static org.hamcrest.Matchers.oneOf;
3033

3134
public class CohereServiceUpgradeIT extends InferenceUpgradeTestCase {
@@ -122,7 +125,7 @@ public void testCohereEmbeddings() throws IOException {
122125
assertThat(serviceSettings, hasEntry("model_id", "embed-english-light-v3.0"));
123126
assertThat(serviceSettings, hasEntry("embedding_type", "byte"));
124127
var taskSettings = (Map<String, Object>) configs.get(0).get("task_settings");
125-
assertThat(taskSettings.keySet(), empty());
128+
assertThat(taskSettings, anyOf(nullValue(), anEmptyMap()));
126129

127130
// Inference on old cluster models
128131
assertEmbeddingInference(oldClusterIdInt8, CohereEmbeddingType.BYTE);

x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/HuggingFaceServiceUpgradeIT.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@
2020
import java.util.List;
2121
import java.util.Map;
2222

23+
import static org.hamcrest.Matchers.anEmptyMap;
24+
import static org.hamcrest.Matchers.anyOf;
2325
import static org.hamcrest.Matchers.empty;
2426
import static org.hamcrest.Matchers.hasSize;
2527
import static org.hamcrest.Matchers.not;
28+
import static org.hamcrest.Matchers.nullValue;
2629

2730
public class HuggingFaceServiceUpgradeIT extends InferenceUpgradeTestCase {
2831

@@ -132,7 +135,7 @@ public void testElser() throws IOException {
132135
var configs = (List<Map<String, Object>>) get(testTaskType, oldClusterId).get("endpoints");
133136
assertEquals("hugging_face", configs.get(0).get("service"));
134137
var taskSettings = (Map<String, Object>) configs.get(0).get("task_settings");
135-
assertThat(taskSettings.keySet(), empty());
138+
assertThat(taskSettings, anyOf(nullValue(), anEmptyMap()));
136139

137140
assertElser(oldClusterId);
138141

x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/OpenAiServiceUpgradeIT.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919
import java.util.List;
2020
import java.util.Map;
2121

22+
import static org.hamcrest.Matchers.anEmptyMap;
23+
import static org.hamcrest.Matchers.anyOf;
2224
import static org.hamcrest.Matchers.empty;
2325
import static org.hamcrest.Matchers.hasEntry;
2426
import static org.hamcrest.Matchers.hasSize;
2527
import static org.hamcrest.Matchers.not;
28+
import static org.hamcrest.Matchers.nullValue;
2629

2730
public class OpenAiServiceUpgradeIT extends InferenceUpgradeTestCase {
2831

@@ -91,7 +94,7 @@ public void testOpenAiEmbeddings() throws IOException {
9194
// model id is moved to service settings
9295
assertThat(serviceSettings, hasEntry("model_id", "text-embedding-ada-002"));
9396
var taskSettings = (Map<String, Object>) configs.get(0).get("task_settings");
94-
assertThat(taskSettings.keySet(), empty());
97+
assertThat(taskSettings, anyOf(nullValue(), anEmptyMap()));
9598

9699
// Inference on old cluster model
97100
assertEmbeddingInference(oldClusterId);
@@ -145,7 +148,7 @@ public void testOpenAiCompletions() throws IOException {
145148
var serviceSettings = (Map<String, Object>) configs.get(0).get("service_settings");
146149
assertThat(serviceSettings, hasEntry("model_id", "gpt-4"));
147150
var taskSettings = (Map<String, Object>) configs.get(0).get("task_settings");
148-
assertThat(taskSettings.keySet(), empty());
151+
assertThat(taskSettings, anyOf(nullValue(), anEmptyMap()));
149152

150153
assertCompletionInference(oldClusterId);
151154
} else if (isUpgradedCluster()) {
@@ -154,7 +157,7 @@ public void testOpenAiCompletions() throws IOException {
154157
var serviceSettings = (Map<String, Object>) configs.get(0).get("service_settings");
155158
assertThat(serviceSettings, hasEntry("model_id", "gpt-4"));
156159
var taskSettings = (Map<String, Object>) configs.get(0).get("task_settings");
157-
assertThat(taskSettings.keySet(), empty());
160+
assertThat(taskSettings, anyOf(nullValue(), anEmptyMap()));
158161

159162
assertCompletionInference(oldClusterId);
160163

x-pack/plugin/inference/qa/test-service-plugin/src/main/java/org/elasticsearch/xpack/inference/mock/AbstractTestInferenceService.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.elasticsearch.xcontent.XContentBuilder;
2424

2525
import java.io.IOException;
26+
import java.util.HashMap;
2627
import java.util.Map;
2728

2829
public abstract class AbstractTestInferenceService implements InferenceService {
@@ -47,7 +48,7 @@ protected static Map<String, Object> getTaskSettingsMap(Map<String, Object> sett
4748
if (settings.containsKey(ModelConfigurations.TASK_SETTINGS)) {
4849
taskSettingsMap = (Map<String, Object>) settings.remove(ModelConfigurations.TASK_SETTINGS);
4950
} else {
50-
taskSettingsMap = Map.of();
51+
taskSettingsMap = new HashMap<>();
5152
}
5253

5354
return taskSettingsMap;
@@ -133,6 +134,11 @@ public TestTaskSettings(StreamInput in) throws IOException {
133134
this(in.readOptionalVInt());
134135
}
135136

137+
@Override
138+
public boolean isEmpty() {
139+
return temperature == null;
140+
}
141+
136142
@Override
137143
public void writeTo(StreamOutput out) throws IOException {
138144
out.writeOptionalVInt(temperature);

x-pack/plugin/inference/src/internalClusterTest/java/org/elasticsearch/xpack/inference/integration/ModelRegistryIT.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,11 @@ public TransportVersion getMinimalSupportedVersion() {
592592
public void writeTo(StreamOutput out) throws IOException {
593593

594594
}
595+
596+
@Override
597+
public boolean isEmpty() {
598+
return true;
599+
}
595600
}
596601

597602
record TestSecretSettings(String key) implements SecretSettings {

0 commit comments

Comments
 (0)