Skip to content
Merged
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
5 changes: 5 additions & 0 deletions docs/changelog/133080.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 133080
summary: "Disallow creating `semantic_text` fields in indices created prior to 8.11.0"
area: Relevance
type: bug
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

package org.elasticsearch.xpack.inference.mapper;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.lucene.index.FieldInfos;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DocIdSetIterator;
Expand Down Expand Up @@ -89,6 +91,7 @@
import java.util.function.BiConsumer;
import java.util.function.Function;

import static org.elasticsearch.index.IndexVersions.NEW_SPARSE_VECTOR;
import static org.elasticsearch.inference.TaskType.SPARSE_EMBEDDING;
import static org.elasticsearch.inference.TaskType.TEXT_EMBEDDING;
import static org.elasticsearch.search.SearchService.DEFAULT_SIZE;
Expand All @@ -110,6 +113,8 @@
* A {@link FieldMapper} for semantic text fields.
*/
public class SemanticTextFieldMapper extends FieldMapper implements InferenceFieldMapper {
private static final Logger logger = LogManager.getLogger(SemanticTextFieldMapper.class);
public static final String UNSUPPORTED_INDEX_MESSAGE = "[semantic_text] is available on indices created with 8.11 or higher.";
public static final NodeFeature SEMANTIC_TEXT_IN_OBJECT_FIELD_FIX = new NodeFeature("semantic_text.in_object_field_fix");
public static final NodeFeature SEMANTIC_TEXT_SINGLE_FIELD_UPDATE_FIX = new NodeFeature("semantic_text.single_field_update_fix");
public static final NodeFeature SEMANTIC_TEXT_DELETE_FIX = new NodeFeature("semantic_text.delete_fix");
Expand All @@ -129,6 +134,9 @@ public class SemanticTextFieldMapper extends FieldMapper implements InferenceFie

public static BiConsumer<String, MappingParserContext> validateParserContext(String type) {
return (n, c) -> {
if (c.getIndexSettings().getIndexVersionCreated().before(NEW_SPARSE_VECTOR)) {
throw new UnsupportedOperationException(UNSUPPORTED_INDEX_MESSAGE);
}
if (InferenceMetadataFieldsMapper.isEnabled(c.getIndexSettings().getSettings()) == false) {
notInMultiFields(type).accept(n, c);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
import static org.elasticsearch.xpack.inference.mapper.SemanticTextField.getChunksFieldName;
import static org.elasticsearch.xpack.inference.mapper.SemanticTextField.getEmbeddingsFieldName;
import static org.elasticsearch.xpack.inference.mapper.SemanticTextFieldMapper.DEFAULT_ELSER_2_INFERENCE_ID;
import static org.elasticsearch.xpack.inference.mapper.SemanticTextFieldMapper.UNSUPPORTED_INDEX_MESSAGE;
import static org.elasticsearch.xpack.inference.mapper.SemanticTextFieldTests.randomSemanticText;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
Expand Down Expand Up @@ -339,6 +340,57 @@ public void testInvalidTaskTypes() {
}
}

@Override
protected IndexVersion boostNotAllowedIndexVersion() {
return IndexVersions.NEW_SPARSE_VECTOR;
}

public void testOldIndexSemanticTextDenseVectorRaisesError() throws IOException {
final String fieldName = "field";
final XContentBuilder fieldMapping = fieldMapping(b -> {
b.field("type", "semantic_text");
b.field(INFERENCE_ID_FIELD, "test_inference_id");
b.startObject("model_settings");
b.field("task_type", "text_embedding");
b.field("dimensions", 384);
b.field("similarity", "cosine");
b.field("element_type", "float");
b.endObject();
});
assertOldIndexUnsupported(fieldMapping);
}

public void testOldIndexSemanticTextMinimalMappingRaisesError() throws IOException {
final XContentBuilder fieldMapping = fieldMapping(this::minimalMapping);
assertOldIndexUnsupported(fieldMapping);
}

public void testOldIndexSemanticTextSparseVersionRaisesError() throws IOException {
final XContentBuilder fieldMapping = fieldMapping(b -> {
b.field("type", "semantic_text");
b.field("inference_id", "another_inference_id");
b.startObject("model_settings");
b.field("task_type", "sparse_embedding");
b.endObject();
});
assertOldIndexUnsupported(fieldMapping);
}

private void assertOldIndexUnsupported(XContentBuilder fieldMapping) {

MapperParsingException exception = assertThrows(
MapperParsingException.class,
() -> createMapperService(
fieldMapping,
true,
IndexVersions.V_8_0_0,
IndexVersionUtils.getPreviousVersion(IndexVersions.NEW_SPARSE_VECTOR)
)
);
assertTrue(exception.getMessage().contains(UNSUPPORTED_INDEX_MESSAGE));
assertTrue(exception.getRootCause() instanceof UnsupportedOperationException);
}

public void testMultiFieldsSupport() throws IOException {
if (useLegacyFormat) {
Exception e = expectThrows(MapperParsingException.class, () -> createMapperService(fieldMapping(b -> {
Expand Down