77
88package org .elasticsearch .xpack .inference .mapper ;
99
10+ import org .apache .logging .log4j .LogManager ;
11+ import org .apache .logging .log4j .Logger ;
1012import org .apache .lucene .index .FieldInfos ;
1113import org .apache .lucene .index .LeafReaderContext ;
1214import org .apache .lucene .search .DocIdSetIterator ;
1820import org .apache .lucene .search .join .BitSetProducer ;
1921import org .apache .lucene .search .join .ScoreMode ;
2022import org .apache .lucene .util .BitSet ;
23+ import org .elasticsearch .ResourceNotFoundException ;
2124import org .elasticsearch .cluster .metadata .InferenceFieldMetadata ;
2225import org .elasticsearch .common .Strings ;
2326import org .elasticsearch .common .bytes .BytesReference ;
7578import org .elasticsearch .xpack .core .ml .inference .results .TextExpansionResults ;
7679import org .elasticsearch .xpack .core .ml .search .SparseVectorQueryBuilder ;
7780import org .elasticsearch .xpack .inference .highlight .SemanticTextHighlighter ;
81+ import org .elasticsearch .xpack .inference .registry .ModelRegistry ;
7882
7983import java .io .IOException ;
8084import java .io .UncheckedIOException ;
8993import java .util .Set ;
9094import java .util .function .BiConsumer ;
9195import java .util .function .Function ;
96+ import java .util .function .Supplier ;
9297
9398import static org .elasticsearch .inference .TaskType .SPARSE_EMBEDDING ;
9499import static org .elasticsearch .inference .TaskType .TEXT_EMBEDDING ;
112117 * A {@link FieldMapper} for semantic text fields.
113118 */
114119public class SemanticTextFieldMapper extends FieldMapper implements InferenceFieldMapper {
120+ private static final Logger logger = LogManager .getLogger (SemanticTextFieldMapper .class );
115121 public static final NodeFeature SEMANTIC_TEXT_IN_OBJECT_FIELD_FIX = new NodeFeature ("semantic_text.in_object_field_fix" );
116122 public static final NodeFeature SEMANTIC_TEXT_SINGLE_FIELD_UPDATE_FIX = new NodeFeature ("semantic_text.single_field_update_fix" );
117123 public static final NodeFeature SEMANTIC_TEXT_DELETE_FIX = new NodeFeature ("semantic_text.delete_fix" );
@@ -127,10 +133,12 @@ public class SemanticTextFieldMapper extends FieldMapper implements InferenceFie
127133 public static final String CONTENT_TYPE = "semantic_text" ;
128134 public static final String DEFAULT_ELSER_2_INFERENCE_ID = DEFAULT_ELSER_ID ;
129135
130- public static final TypeParser PARSER = new TypeParser (
131- (n , c ) -> new Builder (n , c ::bitSetProducer , c .getIndexSettings ()),
132- List .of (validateParserContext (CONTENT_TYPE ))
133- );
136+ public static final TypeParser parser (Supplier <ModelRegistry > modelRegistry ) {
137+ return new TypeParser (
138+ (n , c ) -> new Builder (n , c ::bitSetProducer , c .getIndexSettings (), modelRegistry .get ()),
139+ List .of (validateParserContext (CONTENT_TYPE ))
140+ );
141+ }
134142
135143 public static BiConsumer <String , MappingParserContext > validateParserContext (String type ) {
136144 return (n , c ) -> {
@@ -142,6 +150,7 @@ public static BiConsumer<String, MappingParserContext> validateParserContext(Str
142150 }
143151
144152 public static class Builder extends FieldMapper .Builder {
153+ private final ModelRegistry modelRegistry ;
145154 private final boolean useLegacyFormat ;
146155
147156 private final Parameter <String > inferenceId = Parameter .stringParam (
@@ -199,14 +208,21 @@ public static Builder from(SemanticTextFieldMapper mapper) {
199208 Builder builder = new Builder (
200209 mapper .leafName (),
201210 mapper .fieldType ().getChunksField ().bitsetProducer (),
202- mapper .fieldType ().getChunksField ().indexSettings ()
211+ mapper .fieldType ().getChunksField ().indexSettings (),
212+ mapper .modelRegistry
203213 );
204214 builder .init (mapper );
205215 return builder ;
206216 }
207217
208- public Builder (String name , Function <Query , BitSetProducer > bitSetProducer , IndexSettings indexSettings ) {
218+ public Builder (
219+ String name ,
220+ Function <Query , BitSetProducer > bitSetProducer ,
221+ IndexSettings indexSettings ,
222+ ModelRegistry modelRegistry
223+ ) {
209224 super (name );
225+ this .modelRegistry = modelRegistry ;
210226 this .useLegacyFormat = InferenceMetadataFieldsMapper .isEnabled (indexSettings .getSettings ()) == false ;
211227 this .inferenceFieldBuilder = c -> createInferenceField (
212228 c ,
@@ -264,9 +280,32 @@ public SemanticTextFieldMapper build(MapperBuilderContext context) {
264280 if (useLegacyFormat && multiFieldsBuilder .hasMultiFields ()) {
265281 throw new IllegalArgumentException (CONTENT_TYPE + " field [" + leafName () + "] does not support multi-fields" );
266282 }
283+
284+ if (modelSettings .get () == null ) {
285+ try {
286+ var resolvedModelSettings = modelRegistry .getMinimalServiceSettings (inferenceId .get ());
287+ if (resolvedModelSettings != null ) {
288+ modelSettings .setValue (resolvedModelSettings );
289+ }
290+ } catch (ResourceNotFoundException exc ) {
291+ // We allow the inference ID to be unregistered at this point.
292+ // This will delay the creation of sub-fields, so indexing and querying for this field won't work
293+ // until the corresponding inference endpoint is created.
294+ }
295+ }
296+
267297 if (modelSettings .get () != null ) {
268298 validateServiceSettings (modelSettings .get ());
299+ } else {
300+ logger .warn (
301+ "The field [{}] references an unknown inference ID [{}]. "
302+ + "Indexing and querying this field will not work correctly until the corresponding "
303+ + "inference endpoint is created." ,
304+ leafName (),
305+ inferenceId .get ()
306+ );
269307 }
308+
270309 final String fullName = context .buildFullName (leafName ());
271310
272311 if (context .isInNestedContext ()) {
@@ -287,7 +326,8 @@ public SemanticTextFieldMapper build(MapperBuilderContext context) {
287326 useLegacyFormat ,
288327 meta .getValue ()
289328 ),
290- builderParams (this , context )
329+ builderParams (this , context ),
330+ modelRegistry
291331 );
292332 }
293333
@@ -328,9 +368,17 @@ private SemanticTextFieldMapper copySettings(SemanticTextFieldMapper mapper, Map
328368 }
329369 }
330370
331- private SemanticTextFieldMapper (String simpleName , MappedFieldType mappedFieldType , BuilderParams builderParams ) {
371+ private final ModelRegistry modelRegistry ;
372+
373+ private SemanticTextFieldMapper (
374+ String simpleName ,
375+ MappedFieldType mappedFieldType ,
376+ BuilderParams builderParams ,
377+ ModelRegistry modelRegistry
378+ ) {
332379 super (simpleName , mappedFieldType , builderParams );
333380 ensureMultiFields (builderParams .multiFields ().iterator ());
381+ this .modelRegistry = modelRegistry ;
334382 }
335383
336384 private void ensureMultiFields (Iterator <FieldMapper > mappers ) {
0 commit comments