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/126629.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 126629
summary: Default new `semantic_text` fields to use BBQ when models are compatible
area: Relevance
type: enhancement
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ private static IndexVersion def(int id, Version luceneVersion) {
public static final IndexVersion ADD_RESCORE_PARAMS_TO_QUANTIZED_VECTORS = def(8_528_0_00, Version.LUCENE_9_12_1);
public static final IndexVersion RESCORE_PARAMS_ALLOW_ZERO_TO_QUANTIZED_VECTORS = def(8_529_0_00, Version.LUCENE_9_12_1);
public static final IndexVersion DEFAULT_OVERSAMPLE_VALUE_FOR_BBQ_BACKPORT_8_X = def(8_530_0_00, Version.LUCENE_9_12_1);
public static final IndexVersion SEMANTIC_TEXT_DEFAULTS_TO_BBQ_BACKPORT_8_X = def(8_531_0_00, Version.LUCENE_9_12_1);
/*
* STOP! READ THIS FIRST! No, really,
* ____ _____ ___ ____ _ ____ _____ _ ____ _____ _ _ ___ ____ _____ ___ ____ ____ _____ _
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@ public Builder elementType(ElementType elementType) {
return this;
}

public Builder indexOptions(IndexOptions indexOptions) {
this.indexOptions.setValue(indexOptions);
return this;
}

@Override
public DenseVectorFieldMapper build(MapperBuilderContext context) {
// Validate again here because the dimensions or element type could have been set programmatically,
Expand Down Expand Up @@ -1202,7 +1207,7 @@ public final String toString() {
public abstract VectorSimilarityFunction vectorSimilarityFunction(IndexVersion indexVersion, ElementType elementType);
}

abstract static class IndexOptions implements ToXContent {
public abstract static class IndexOptions implements ToXContent {
final VectorIndexType type;

IndexOptions(VectorIndexType type) {
Expand All @@ -1211,21 +1216,36 @@ abstract static class IndexOptions implements ToXContent {

abstract KnnVectorsFormat getVectorsFormat(ElementType elementType);

final void validateElementType(ElementType elementType) {
if (type.supportsElementType(elementType) == false) {
public boolean validate(ElementType elementType, int dim, boolean throwOnError) {
return validateElementType(elementType, throwOnError) && validateDimension(dim, throwOnError);
}

public boolean validateElementType(ElementType elementType) {
return validateElementType(elementType, true);
}

final boolean validateElementType(ElementType elementType, boolean throwOnError) {
boolean validElementType = type.supportsElementType(elementType);
if (throwOnError && validElementType == false) {
throw new IllegalArgumentException(
"[element_type] cannot be [" + elementType.toString() + "] when using index type [" + type + "]"
);
}
return validElementType;
}

abstract boolean updatableTo(IndexOptions update);

public void validateDimension(int dim) {
if (type.supportsDimension(dim)) {
return;
public boolean validateDimension(int dim) {
return validateDimension(dim, true);
}

public boolean validateDimension(int dim, boolean throwOnError) {
boolean supportsDimension = type.supportsDimension(dim);
if (throwOnError && supportsDimension == false) {
throw new IllegalArgumentException(type.name + " only supports even dimensions; provided=" + dim);
}
throw new IllegalArgumentException(type.name + " only supports even dimensions; provided=" + dim);
return supportsDimension;
}

abstract boolean doEquals(IndexOptions other);
Expand Down Expand Up @@ -1734,12 +1754,12 @@ boolean updatableTo(IndexOptions update) {

}

static class Int8HnswIndexOptions extends QuantizedIndexOptions {
public static class Int8HnswIndexOptions extends QuantizedIndexOptions {
private final int m;
private final int efConstruction;
private final Float confidenceInterval;

Int8HnswIndexOptions(int m, int efConstruction, Float confidenceInterval, RescoreVector rescoreVector) {
public Int8HnswIndexOptions(int m, int efConstruction, Float confidenceInterval, RescoreVector rescoreVector) {
super(VectorIndexType.INT8_HNSW, rescoreVector);
this.m = m;
this.efConstruction = efConstruction;
Expand Down Expand Up @@ -1877,11 +1897,11 @@ public String toString() {
}
}

static class BBQHnswIndexOptions extends QuantizedIndexOptions {
public static class BBQHnswIndexOptions extends QuantizedIndexOptions {
private final int m;
private final int efConstruction;

BBQHnswIndexOptions(int m, int efConstruction, RescoreVector rescoreVector) {
public BBQHnswIndexOptions(int m, int efConstruction, RescoreVector rescoreVector) {
super(VectorIndexType.BBQ_HNSW, rescoreVector);
this.m = m;
this.efConstruction = efConstruction;
Expand Down Expand Up @@ -1923,11 +1943,14 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
}

@Override
public void validateDimension(int dim) {
if (type.supportsDimension(dim)) {
return;
public boolean validateDimension(int dim, boolean throwOnError) {
boolean supportsDimension = type.supportsDimension(dim);
if (throwOnError && supportsDimension == false) {
throw new IllegalArgumentException(
type.name + " does not support dimensions fewer than " + BBQ_MIN_DIMS + "; provided=" + dim
);
}
throw new IllegalArgumentException(type.name + " does not support dimensions fewer than " + BBQ_MIN_DIMS + "; provided=" + dim);
return supportsDimension;
}
}

Expand Down Expand Up @@ -1971,15 +1994,19 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
}

@Override
public void validateDimension(int dim) {
if (type.supportsDimension(dim)) {
return;
public boolean validateDimension(int dim, boolean throwOnError) {
boolean supportsDimension = type.supportsDimension(dim);
if (throwOnError && supportsDimension == false) {
throw new IllegalArgumentException(
type.name + " does not support dimensions fewer than " + BBQ_MIN_DIMS + "; provided=" + dim
);
}
throw new IllegalArgumentException(type.name + " does not support dimensions fewer than " + BBQ_MIN_DIMS + "; provided=" + dim);
return supportsDimension;
}

}

record RescoreVector(float oversample) implements ToXContentObject {
public record RescoreVector(float oversample) implements ToXContentObject {
static final String NAME = "rescore_vector";
static final String OVERSAMPLE = "oversample";

Expand Down Expand Up @@ -2299,7 +2326,7 @@ ElementType getElementType() {
return elementType;
}

IndexOptions getIndexOptions() {
public IndexOptions getIndexOptions() {
return indexOptions;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,13 @@ protected final MapperService createMapperService(Settings settings, String mapp
return mapperService;
}

protected final MapperService createMapperService(IndexVersion indexVersion, Settings settings, XContentBuilder mappings)
throws IOException {
MapperService mapperService = createMapperService(indexVersion, settings, () -> true, mappings);
merge(mapperService, mappings);
return mapperService;
}

protected final MapperService createMapperService(IndexVersion version, XContentBuilder mapping) throws IOException {
return createMapperService(version, getIndexSettings(), () -> true, mapping);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.lucene.codecs.lucene99.Lucene99HnswVectorsFormat;
import org.apache.lucene.index.FieldInfos;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DocIdSetIterator;
Expand Down Expand Up @@ -96,6 +97,7 @@
import java.util.function.Function;
import java.util.function.Supplier;

import static org.elasticsearch.index.IndexVersions.SEMANTIC_TEXT_DEFAULTS_TO_BBQ_BACKPORT_8_X;
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 Down Expand Up @@ -136,6 +138,8 @@ public class SemanticTextFieldMapper extends FieldMapper implements InferenceFie
public static final String CONTENT_TYPE = "semantic_text";
public static final String DEFAULT_ELSER_2_INFERENCE_ID = DEFAULT_ELSER_ID;

public static final float DEFAULT_RESCORE_OVERSAMPLE = 3.0f;

public static final TypeParser parser(Supplier<ModelRegistry> modelRegistry) {
return new TypeParser(
(n, c) -> new Builder(n, c::bitSetProducer, c.getIndexSettings(), modelRegistry.get()),
Expand Down Expand Up @@ -1078,12 +1082,30 @@ private static Mapper.Builder createEmbeddingsField(
denseVectorMapperBuilder.dimensions(modelSettings.dimensions());
denseVectorMapperBuilder.elementType(modelSettings.elementType());

DenseVectorFieldMapper.IndexOptions defaultIndexOptions = null;
if (indexVersionCreated.onOrAfter(SEMANTIC_TEXT_DEFAULTS_TO_BBQ_BACKPORT_8_X)) {
defaultIndexOptions = defaultSemanticDenseIndexOptions();
}
if (defaultIndexOptions != null
&& defaultIndexOptions.validate(modelSettings.elementType(), modelSettings.dimensions(), false)) {
denseVectorMapperBuilder.indexOptions(defaultIndexOptions);
}

yield denseVectorMapperBuilder;
}
default -> throw new IllegalArgumentException("Invalid task_type in model_settings [" + modelSettings.taskType().name() + "]");
};
}

static DenseVectorFieldMapper.IndexOptions defaultSemanticDenseIndexOptions() {
// As embedding models for text perform better with BBQ, we aggressively default semantic_text fields to use optimized index
// options outside of dense_vector defaults
int m = Lucene99HnswVectorsFormat.DEFAULT_MAX_CONN;
int efConstruction = Lucene99HnswVectorsFormat.DEFAULT_BEAM_WIDTH;
DenseVectorFieldMapper.RescoreVector rescoreVector = new DenseVectorFieldMapper.RescoreVector(DEFAULT_RESCORE_OVERSAMPLE);
return new DenseVectorFieldMapper.BBQHnswIndexOptions(m, efConstruction, rescoreVector);
}

private static boolean canMergeModelSettings(MinimalServiceSettings previous, MinimalServiceSettings current, Conflicts conflicts) {
if (previous != null && current != null && previous.canMergeWith(current)) {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,34 @@
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.FieldInfos;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexVersion;
import org.elasticsearch.index.IndexVersions;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.MapperServiceTestCase;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.index.IndexVersionUtils;
import org.elasticsearch.xpack.inference.InferencePlugin;

import java.util.Collection;
import java.util.Collections;

public class SemanticInferenceMetadataFieldsMapperTests extends MapperServiceTestCase {

static IndexVersion getRandomCompatibleIndexVersion(boolean useLegacyFormat) {
return getRandomCompatibleIndexVersion(useLegacyFormat, IndexVersion.current());
}

static IndexVersion getRandomCompatibleIndexVersion(boolean useLegacyFormat, IndexVersion maxVersion) {
if (useLegacyFormat) {
if (randomBoolean()) {
return IndexVersionUtils.randomVersionBetween(random(), IndexVersions.INFERENCE_METADATA_FIELDS_BACKPORT, maxVersion);
}
return IndexVersionUtils.randomPreviousCompatibleVersion(random(), IndexVersions.INFERENCE_METADATA_FIELDS_BACKPORT);
} else {
return IndexVersionUtils.randomVersionBetween(random(), IndexVersions.INFERENCE_METADATA_FIELDS_BACKPORT, maxVersion);
}
}

@Override
protected Collection<? extends Plugin> getPlugins() {
return Collections.singletonList(new InferencePlugin(Settings.EMPTY));
Expand Down
Loading