From 2136650a18b08b98b00ab274483ac47c474e591e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Rinaldi?= Date: Mon, 27 Apr 2026 12:13:40 +0200 Subject: [PATCH 1/6] [text-to-vector-refactoring] Refactoring to accomodate future new feature "Document enrichment with LLMs" --- .../model/SolrLanguageModel.java | 48 ++++++ .../store => model}/package-info.java | 2 +- .../LanguageModelException.java} | 9 +- .../LanguageModelStore.java} | 32 ++-- .../languagemodels/store/package-info.java | 4 + .../store/rest/ManagedModelStore.java | 162 ++++++++++++++++++ .../store/rest/package-info.java | 20 +++ .../model/SolrTextToVectorModel.java | 46 ++--- .../rest/ManagedTextToVectorModelStore.java | 147 +--------------- .../cohere-model.json | 0 .../dummy-model-ambiguous.json | 0 .../dummy-model-unsupported.json | 0 .../dummy-model.json | 0 .../exception-throwing-model.json | 0 .../huggingface-model.json | 0 .../mistralai-model.json | 0 .../openai-model.json | 0 .../languagemodels/TestLanguageModelBase.java | 16 +- 18 files changed, 286 insertions(+), 200 deletions(-) create mode 100644 solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java rename solr/modules/language-models/src/java/org/apache/solr/languagemodels/{textvectorisation/store => model}/package-info.java (92%) rename solr/modules/language-models/src/java/org/apache/solr/languagemodels/{textvectorisation/store/TextToVectorModelException.java => store/LanguageModelException.java} (78%) rename solr/modules/language-models/src/java/org/apache/solr/languagemodels/{textvectorisation/store/TextToVectorModelStore.java => store/LanguageModelStore.java} (58%) create mode 100644 solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/package-info.java create mode 100644 solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedModelStore.java create mode 100644 solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java rename solr/modules/language-models/src/test-files/{modelExamples => embeddingModelExamples}/cohere-model.json (100%) rename solr/modules/language-models/src/test-files/{modelExamples => embeddingModelExamples}/dummy-model-ambiguous.json (100%) rename solr/modules/language-models/src/test-files/{modelExamples => embeddingModelExamples}/dummy-model-unsupported.json (100%) rename solr/modules/language-models/src/test-files/{modelExamples => embeddingModelExamples}/dummy-model.json (100%) rename solr/modules/language-models/src/test-files/{modelExamples => embeddingModelExamples}/exception-throwing-model.json (100%) rename solr/modules/language-models/src/test-files/{modelExamples => embeddingModelExamples}/huggingface-model.json (100%) rename solr/modules/language-models/src/test-files/{modelExamples => embeddingModelExamples}/mistralai-model.json (100%) rename solr/modules/language-models/src/test-files/{modelExamples => embeddingModelExamples}/openai-model.json (100%) diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java new file mode 100644 index 000000000000..f3da99e083f7 --- /dev/null +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.languagemodels.model; + +import java.util.Map; + +/** Base class for Solr-managed wrappers around langchain4j language model instances. */ +public abstract class SolrLanguageModel { + + // timeout is type Duration + protected static final String TIMEOUT_PARAM = "timeout"; + + // the following is Integer type + protected static final String MAX_RETRIES_PARAM = "maxRetries"; + + protected final String name; + protected final Map params; + + protected SolrLanguageModel(String name, Map params) { + this.name = name; + this.params = params; + } + + public String getName() { + return name; + } + + public Map getParams() { + return params; + } + + /** Returns the class name of the underlying langchain4j model instance. */ + public abstract String getModelClassName(); +} diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/package-info.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/package-info.java similarity index 92% rename from solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/package-info.java rename to solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/package-info.java index 5e79341f9927..c7e5c3d80c98 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/package-info.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/package-info.java @@ -16,4 +16,4 @@ */ /** Contains model store related classes. */ -package org.apache.solr.languagemodels.textvectorisation.store; +package org.apache.solr.languagemodels.model; diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/TextToVectorModelException.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelException.java similarity index 78% rename from solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/TextToVectorModelException.java rename to solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelException.java index 8709ebf69298..0a3454d6645b 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/TextToVectorModelException.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelException.java @@ -1,3 +1,4 @@ + /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -14,17 +15,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.languagemodels.textvectorisation.store; +package org.apache.solr.languagemodels.store; -public class TextToVectorModelException extends RuntimeException { +public class LanguageModelException extends RuntimeException { private static final long serialVersionUID = 1L; - public TextToVectorModelException(String message) { + public LanguageModelException(String message) { super(message); } - public TextToVectorModelException(String message, Exception cause) { + public LanguageModelException(String message, Exception cause) { super(message, cause); } } diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/TextToVectorModelStore.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelStore.java similarity index 58% rename from solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/TextToVectorModelStore.java rename to solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelStore.java index 7d24d25f57e3..d99de0d5f989 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/TextToVectorModelStore.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelStore.java @@ -14,25 +14,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.languagemodels.textvectorisation.store; +package org.apache.solr.languagemodels.store; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.apache.solr.languagemodels.textvectorisation.model.SolrTextToVectorModel; +import org.apache.solr.languagemodels.model.SolrLanguageModel; -/** Simple store to manage CRUD operations on the {@link SolrTextToVectorModel} */ -public class TextToVectorModelStore { +/** Generic store to manage CRUD operations on models that extend {@link SolrLanguageModel} */ +public class LanguageModelStore { - private final Map availableModels; + private final Map availableModels; - public TextToVectorModelStore() { + public LanguageModelStore() { availableModels = Collections.synchronizedMap(new LinkedHashMap<>()); } - public SolrTextToVectorModel getModel(String name) { + public M getModel(String name) { return availableModels.get(name); } @@ -40,27 +40,27 @@ public void clear() { availableModels.clear(); } - public List getModels() { + public List getModels() { synchronized (availableModels) { - final List availableModelsValues = - new ArrayList(availableModels.values()); + final List availableModelsValues = + new ArrayList<>(availableModels.values()); return Collections.unmodifiableList(availableModelsValues); } } @Override public String toString() { - return "ModelStore [availableModels=" + availableModels.keySet() + "]"; + return "LanguageModelStore [availableModels=" + availableModels.keySet() + "]"; } - public SolrTextToVectorModel delete(String modelName) { + public M delete(String modelName) { return availableModels.remove(modelName); } - public void addModel(SolrTextToVectorModel modeldata) throws TextToVectorModelException { - final String name = modeldata.getName(); - if (availableModels.putIfAbsent(modeldata.getName(), modeldata) != null) { - throw new TextToVectorModelException( + public void addModel(M modelData) throws LanguageModelException { + final String name = modelData.getName(); + if (availableModels.putIfAbsent(name, modelData) != null) { + throw new LanguageModelException( "model '" + name + "' already exists. Please use a different name"); } } diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/package-info.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/package-info.java new file mode 100644 index 000000000000..8d1f1a7def69 --- /dev/null +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/package-info.java @@ -0,0 +1,4 @@ + + +/** Contains model store related classes. */ +package org.apache.solr.languagemodels.store; diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedModelStore.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedModelStore.java new file mode 100644 index 000000000000..3223ec0a75b4 --- /dev/null +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedModelStore.java @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.solr.languagemodels.store.rest; + +import java.lang.invoke.MethodHandles; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import net.jcip.annotations.ThreadSafe; +import org.apache.solr.common.SolrException; +import org.apache.solr.common.util.NamedList; +import org.apache.solr.core.SolrResourceLoader; +import org.apache.solr.languagemodels.model.SolrLanguageModel; +import org.apache.solr.languagemodels.store.LanguageModelException; +import org.apache.solr.languagemodels.store.LanguageModelStore; +import org.apache.solr.response.SolrQueryResponse; +import org.apache.solr.rest.BaseSolrResource; +import org.apache.solr.rest.ManagedResource; +import org.apache.solr.rest.ManagedResourceStorage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract base class for {@link ManagedResource} wrappers that expose a {@link LanguageModelStore} + * via the REST API. Concrete subclasses supply the REST endpoint and the model instantiation logic. + */ +@ThreadSafe +public abstract class ManagedModelStore extends ManagedResource + implements ManagedResource.ChildResourceSupport { + private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + private static final String MODELS_JSON_FIELD = "models"; + + protected static final String CLASS_KEY = "class"; + protected static final String NAME_KEY = "name"; + protected static final String PARAMS_KEY = "params"; + + private final LanguageModelStore store; + private Object managedData; + + protected ManagedModelStore( + String resourceId, SolrResourceLoader loader, ManagedResourceStorage.StorageIO storageIO) + throws SolrException { + super(resourceId, loader, storageIO); + store = new LanguageModelStore<>(); + } + + /** + * Creates a model instance from the JSON map persisted in the managed resource storage. + * + * @param loader the resource loader for the current core + * @param modelMap a map containing {@code "class"}, {@code "name"}, and {@code "params"} keys + * @return the instantiated model + */ + protected abstract M fromModelMap(SolrResourceLoader loader, Map modelMap); + + private static LinkedHashMap toModelMap(SolrLanguageModel model) { + final LinkedHashMap modelMap = new LinkedHashMap<>(5, 1.0f); + modelMap.put(NAME_KEY, model.getName()); + modelMap.put(CLASS_KEY, model.getModelClassName()); + modelMap.put(PARAMS_KEY, model.getParams()); + return modelMap; + } + + @Override + protected ManagedResourceStorage createStorage( + ManagedResourceStorage.StorageIO storageIO, SolrResourceLoader loader) throws SolrException { + return new ManagedResourceStorage.JsonStorage(storageIO, loader, -1); + } + + @Override + protected void onManagedDataLoadedFromStorage(NamedList managedInitArgs, Object managedData) + throws SolrException { + store.clear(); + this.managedData = managedData; + } + + public void loadStoredModels() { + log.info("------ managed models ~ loading ------"); + if ((managedData != null) && (managedData instanceof List)) { + @SuppressWarnings("unchecked") + final List> models = (List>) managedData; + for (final Map model : models) { + addModelFromMap(model); + } + } + } + + private void addModelFromMap(Map modelMap) { + try { + addModel(fromModelMap(solrResourceLoader, modelMap)); + } catch (final LanguageModelException e) { + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e); + } + } + + public void addModel(M model) throws SolrException { + try { + if (log.isInfoEnabled()) { + log.info("adding model {}", model.getName()); + } + store.addModel(model); + } catch (final LanguageModelException e) { + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e); + } + } + + @SuppressWarnings("unchecked") + @Override + protected Object applyUpdatesToManagedData(Object updates) { + if (updates instanceof List) { + final List> models = (List>) updates; + for (final Map model : models) { + addModelFromMap(model); + } + } + if (updates instanceof Map) { + addModelFromMap((Map) updates); + } + return modelsAsManagedResources(store.getModels()); + } + + @Override + public void doDeleteChild(BaseSolrResource endpoint, String childId) { + store.delete(childId); + storeManagedData(applyUpdatesToManagedData(null)); + } + + @Override + public void doGet(BaseSolrResource endpoint, String childId) { + final SolrQueryResponse response = endpoint.getSolrResponse(); + response.add(MODELS_JSON_FIELD, modelsAsManagedResources(store.getModels())); + } + + public M getModel(String modelName) { + return store.getModel(modelName); + } + + private static List modelsAsManagedResources(List models) { + return models.stream().map(ManagedModelStore::toModelMap).collect(Collectors.toList()); + } + + @Override + public String toString() { + return getClass().getSimpleName() + " [store=" + store + "]"; + } +} diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java new file mode 100644 index 000000000000..3e21be9b03da --- /dev/null +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** Contains model store related classes. */ +package org.apache.solr.languagemodels.store.rest; + diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java index 21f7f8035be7..708ad1ad8807 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java @@ -28,26 +28,23 @@ import org.apache.lucene.util.RamUsageEstimator; import org.apache.solr.common.SolrException; import org.apache.solr.core.SolrResourceLoader; -import org.apache.solr.languagemodels.textvectorisation.store.TextToVectorModelException; +import org.apache.solr.languagemodels.model.SolrLanguageModel; +import org.apache.solr.languagemodels.store.LanguageModelException; import org.apache.solr.languagemodels.textvectorisation.store.rest.ManagedTextToVectorModelStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * This object wraps a {@link dev.langchain4j.model.embedding.EmbeddingModel} to encode text to + * This object wraps a {@link EmbeddingModel} to encode text to * vector. It's meant to be used as a managed resource with the {@link * ManagedTextToVectorModelStore} */ -public class SolrTextToVectorModel implements Accountable { +public class SolrTextToVectorModel extends SolrLanguageModel implements Accountable { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static final long BASE_RAM_BYTES = RamUsageEstimator.shallowSizeOfInstance(SolrTextToVectorModel.class); - private static final String TIMEOUT_PARAM = "timeout"; private static final String MAX_SEGMENTS_PER_BATCH_PARAM = "maxSegmentsPerBatch"; - private static final String MAX_RETRIES_PARAM = "maxRetries"; - private final String name; - private final Map params; private final EmbeddingModel textToVector; private final int hashCode; @@ -56,7 +53,7 @@ public static SolrTextToVectorModel getInstance( String className, String name, Map params) - throws TextToVectorModelException { + throws LanguageModelException { try { /* * The idea here is to build a {@link dev.langchain4j.model.embedding.EmbeddingModel} using inversion @@ -94,10 +91,10 @@ public static SolrTextToVectorModel getInstance( .getMethod(paramName, Integer.class) .invoke(builder, ((Long) params.get(paramName)).intValue()); - /* - * For primitive params if there's only one setter available, we call it. - * If there's choice we default to the string one - */ + /* + * For primitive params if there's only one setter available, we call it. + * If there's choice we default to the string one + */ default -> { ArrayList paramNameMatches = new ArrayList<>(); for (var method : builder.getClass().getMethods()) { @@ -125,15 +122,14 @@ public static SolrTextToVectorModel getInstance( textToVector = (EmbeddingModel) builder.getClass().getMethod("build").invoke(builder); return new SolrTextToVectorModel(name, textToVector, params); } catch (final Exception e) { - throw new TextToVectorModelException("Model loading failed for " + className, e); + throw new LanguageModelException("Model loading failed for " + className, e); } } public SolrTextToVectorModel( String name, EmbeddingModel textToVector, Map params) { - this.name = name; + super(name, params); this.textToVector = textToVector; - this.params = params; this.hashCode = calculateHashCode(); } @@ -142,6 +138,11 @@ public float[] vectorise(String text) { return vector.vector(); } + @Override + public String getModelClassName() { + return textToVector.getClass().getName(); + } + @Override public String toString() { return getClass().getSimpleName() + "(name=" + getName() + ")"; @@ -170,20 +171,7 @@ private int calculateHashCode() { @Override public boolean equals(Object obj) { if (this == obj) return true; - if (!(obj instanceof SolrTextToVectorModel)) return false; - final SolrTextToVectorModel other = (SolrTextToVectorModel) obj; + if (!(obj instanceof SolrTextToVectorModel other)) return false; return Objects.equals(textToVector, other.textToVector) && Objects.equals(name, other.name); } - - public String getName() { - return name; - } - - public String getEmbeddingModelClassName() { - return textToVector.getClass().getName(); - } - - public Map getParams() { - return params; - } } diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java index 70c03ffc47ea..1cf14db31959 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java @@ -16,48 +16,22 @@ */ package org.apache.solr.languagemodels.textvectorisation.store.rest; -import java.lang.invoke.MethodHandles; -import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import net.jcip.annotations.ThreadSafe; import org.apache.solr.common.SolrException; -import org.apache.solr.common.util.NamedList; import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrResourceLoader; +import org.apache.solr.languagemodels.store.rest.ManagedModelStore; import org.apache.solr.languagemodels.textvectorisation.model.SolrTextToVectorModel; -import org.apache.solr.languagemodels.textvectorisation.store.TextToVectorModelException; -import org.apache.solr.languagemodels.textvectorisation.store.TextToVectorModelStore; -import org.apache.solr.response.SolrQueryResponse; -import org.apache.solr.rest.BaseSolrResource; -import org.apache.solr.rest.ManagedResource; import org.apache.solr.rest.ManagedResourceObserver; import org.apache.solr.rest.ManagedResourceStorage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -/** Managed Resource wrapper for the {@link TextToVectorModelStore} to expose it via REST */ +/** Managed Resource wrapper for the text-to-vector model store, exposed via REST */ @ThreadSafe -public class ManagedTextToVectorModelStore extends ManagedResource - implements ManagedResource.ChildResourceSupport { - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); +public class ManagedTextToVectorModelStore extends ManagedModelStore { - /** the model store rest endpoint */ public static final String REST_END_POINT = "/schema/text-to-vector-model-store"; - /** Managed model store: the name of the attribute containing all the models of a model store */ - private static final String MODELS_JSON_FIELD = "models"; - - /** name of the attribute containing a class */ - static final String CLASS_KEY = "class"; - - /** name of the attribute containing a name */ - static final String NAME_KEY = "name"; - - /** name of the attribute containing parameters */ - static final String PARAMS_KEY = "params"; - public static void registerManagedTextToVectorModelStore( SolrResourceLoader solrResourceLoader, ManagedResourceObserver managedResourceObserver) { solrResourceLoader @@ -70,21 +44,9 @@ public static ManagedTextToVectorModelStore getManagedModelStore(SolrCore core) return (ManagedTextToVectorModelStore) core.getRestManager().getManagedResource(REST_END_POINT); } - /** - * Returns the available models as a list of Maps objects. After an update the managed resources - * needs to return the resources in this format in order to store in json somewhere (zookeeper, - * disk...) - * - * @return the available models as a list of Maps objects - */ - private static List modelsAsManagedResources(List models) { - return models.stream() - .map(ManagedTextToVectorModelStore::toModelMap) - .collect(Collectors.toList()); - } - + @Override @SuppressWarnings("unchecked") - public static SolrTextToVectorModel fromModelMap( + protected SolrTextToVectorModel fromModelMap( SolrResourceLoader solrResourceLoader, Map embeddingModel) { return SolrTextToVectorModel.getInstance( solrResourceLoader, @@ -93,108 +55,9 @@ public static SolrTextToVectorModel fromModelMap( (Map) embeddingModel.get(PARAMS_KEY)); } - private static LinkedHashMap toModelMap(SolrTextToVectorModel model) { - final LinkedHashMap modelMap = new LinkedHashMap<>(5, 1.0f); - modelMap.put(NAME_KEY, model.getName()); - modelMap.put(CLASS_KEY, model.getEmbeddingModelClassName()); - modelMap.put(PARAMS_KEY, model.getParams()); - return modelMap; - } - - private final TextToVectorModelStore store; - private Object managedData; - public ManagedTextToVectorModelStore( String resourceId, SolrResourceLoader loader, ManagedResourceStorage.StorageIO storageIO) throws SolrException { super(resourceId, loader, storageIO); - store = new TextToVectorModelStore(); - } - - @Override - protected ManagedResourceStorage createStorage( - ManagedResourceStorage.StorageIO storageIO, SolrResourceLoader loader) throws SolrException { - return new ManagedResourceStorage.JsonStorage(storageIO, loader, -1); - } - - @Override - protected void onManagedDataLoadedFromStorage(NamedList managedInitArgs, Object managedData) - throws SolrException { - store.clear(); - this.managedData = managedData; - } - - public void loadStoredModels() { - log.info("------ managed models ~ loading ------"); - - if ((managedData != null) && (managedData instanceof List)) { - @SuppressWarnings({"unchecked"}) - final List> textToVectorModels = (List>) managedData; - for (final Map textToVectorModel : textToVectorModels) { - addModelFromMap(textToVectorModel); - } - } - } - - private void addModelFromMap(Map modelMap) { - try { - addModel(fromModelMap(solrResourceLoader, modelMap)); - } catch (final TextToVectorModelException e) { - throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e); - } - } - - public void addModel(SolrTextToVectorModel model) throws TextToVectorModelException { - try { - if (log.isInfoEnabled()) { - log.info("adding model {}", model.getName()); - } - store.addModel(model); - } catch (final TextToVectorModelException e) { - throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e); - } - } - - @SuppressWarnings("unchecked") - @Override - protected Object applyUpdatesToManagedData(Object updates) { - if (updates instanceof List) { - final List> textToVectorModels = (List>) updates; - for (final Map textToVectorModel : textToVectorModels) { - addModelFromMap(textToVectorModel); - } - } - - if (updates instanceof Map) { - final Map map = (Map) updates; - addModelFromMap(map); - } - - return modelsAsManagedResources(store.getModels()); - } - - @Override - public void doDeleteChild(BaseSolrResource endpoint, String childId) { - store.delete(childId); - storeManagedData(applyUpdatesToManagedData(null)); - } - - /** - * Called to retrieve a named part (the given childId) of the resource at the given endpoint. - * Note: since we have a unique child managed store we ignore the childId. - */ - @Override - public void doGet(BaseSolrResource endpoint, String childId) { - final SolrQueryResponse response = endpoint.getSolrResponse(); - response.add(MODELS_JSON_FIELD, modelsAsManagedResources(store.getModels())); - } - - public SolrTextToVectorModel getModel(String modelName) { - return store.getModel(modelName); - } - - @Override - public String toString() { - return "ManagedModelStore [store=" + store + "]"; } } diff --git a/solr/modules/language-models/src/test-files/modelExamples/cohere-model.json b/solr/modules/language-models/src/test-files/embeddingModelExamples/cohere-model.json similarity index 100% rename from solr/modules/language-models/src/test-files/modelExamples/cohere-model.json rename to solr/modules/language-models/src/test-files/embeddingModelExamples/cohere-model.json diff --git a/solr/modules/language-models/src/test-files/modelExamples/dummy-model-ambiguous.json b/solr/modules/language-models/src/test-files/embeddingModelExamples/dummy-model-ambiguous.json similarity index 100% rename from solr/modules/language-models/src/test-files/modelExamples/dummy-model-ambiguous.json rename to solr/modules/language-models/src/test-files/embeddingModelExamples/dummy-model-ambiguous.json diff --git a/solr/modules/language-models/src/test-files/modelExamples/dummy-model-unsupported.json b/solr/modules/language-models/src/test-files/embeddingModelExamples/dummy-model-unsupported.json similarity index 100% rename from solr/modules/language-models/src/test-files/modelExamples/dummy-model-unsupported.json rename to solr/modules/language-models/src/test-files/embeddingModelExamples/dummy-model-unsupported.json diff --git a/solr/modules/language-models/src/test-files/modelExamples/dummy-model.json b/solr/modules/language-models/src/test-files/embeddingModelExamples/dummy-model.json similarity index 100% rename from solr/modules/language-models/src/test-files/modelExamples/dummy-model.json rename to solr/modules/language-models/src/test-files/embeddingModelExamples/dummy-model.json diff --git a/solr/modules/language-models/src/test-files/modelExamples/exception-throwing-model.json b/solr/modules/language-models/src/test-files/embeddingModelExamples/exception-throwing-model.json similarity index 100% rename from solr/modules/language-models/src/test-files/modelExamples/exception-throwing-model.json rename to solr/modules/language-models/src/test-files/embeddingModelExamples/exception-throwing-model.json diff --git a/solr/modules/language-models/src/test-files/modelExamples/huggingface-model.json b/solr/modules/language-models/src/test-files/embeddingModelExamples/huggingface-model.json similarity index 100% rename from solr/modules/language-models/src/test-files/modelExamples/huggingface-model.json rename to solr/modules/language-models/src/test-files/embeddingModelExamples/huggingface-model.json diff --git a/solr/modules/language-models/src/test-files/modelExamples/mistralai-model.json b/solr/modules/language-models/src/test-files/embeddingModelExamples/mistralai-model.json similarity index 100% rename from solr/modules/language-models/src/test-files/modelExamples/mistralai-model.json rename to solr/modules/language-models/src/test-files/embeddingModelExamples/mistralai-model.json diff --git a/solr/modules/language-models/src/test-files/modelExamples/openai-model.json b/solr/modules/language-models/src/test-files/embeddingModelExamples/openai-model.json similarity index 100% rename from solr/modules/language-models/src/test-files/modelExamples/openai-model.json rename to solr/modules/language-models/src/test-files/embeddingModelExamples/openai-model.json diff --git a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/TestLanguageModelBase.java b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/TestLanguageModelBase.java index a54e8e1875d5..240a75464f99 100644 --- a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/TestLanguageModelBase.java +++ b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/TestLanguageModelBase.java @@ -38,7 +38,7 @@ public class TestLanguageModelBase extends RestTestBase { protected static Path tmpSolrHome; protected static Path tmpConfDir; - public static final String MODEL_FILE_NAME = "_schema_text-to-vector-model-store.json"; + public static final String EMBEDDING_MODEL_FILE_NAME = "_schema_text-to-vector-model-store.json"; protected static final String COLLECTION = "collection1"; protected static final String CONF_DIR = COLLECTION + "/conf"; @@ -61,17 +61,17 @@ protected static void initFolders(boolean isPersistent) throws Exception { tmpSolrHome = createTempDir(); tmpConfDir = tmpSolrHome.resolve(CONF_DIR); PathUtils.copyDirectory(TEST_PATH(), tmpSolrHome.toAbsolutePath()); - final Path modelStore = tmpConfDir.resolve(MODEL_FILE_NAME); + final Path embeddingStore = tmpConfDir.resolve(EMBEDDING_MODEL_FILE_NAME); if (isPersistent) { - embeddingModelStoreFile = modelStore; + embeddingModelStoreFile = embeddingStore; } - if (Files.exists(modelStore)) { + if (Files.exists(embeddingStore)) { if (log.isInfoEnabled()) { - log.info("remove model store config file in {}", modelStore.toAbsolutePath()); + log.info("remove model store config file in {}", embeddingStore.toAbsolutePath()); } - Files.delete(modelStore); + Files.delete(embeddingStore); } System.setProperty("managed.schema.mutable", "true"); @@ -87,7 +87,7 @@ protected static void afterTest() throws Exception { } public static void loadModel(String fileName, String status) throws Exception { - final URL url = TestLanguageModelBase.class.getResource("/modelExamples/" + fileName); + final URL url = TestLanguageModelBase.class.getResource("/embeddingModelExamples/" + fileName); final String multipleModels = Files.readString(Path.of(url.toURI()), StandardCharsets.UTF_8); assertJPut( @@ -97,7 +97,7 @@ public static void loadModel(String fileName, String status) throws Exception { } public static void loadModel(String fileName) throws Exception { - final URL url = TestLanguageModelBase.class.getResource("/modelExamples/" + fileName); + final URL url = TestLanguageModelBase.class.getResource("/embeddingModelExamples/" + fileName); final String multipleModels = Files.readString(Path.of(url.toURI()), StandardCharsets.UTF_8); assertJPut( From 4c86f3532eb592b74790b86a52c5d76d633c3aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Rinaldi?= Date: Mon, 27 Apr 2026 12:21:52 +0200 Subject: [PATCH 2/6] [text-to-vector-refactoring] Quick fixes ported from review of document enrichment module --- .../solr/languagemodels/store/rest/ManagedModelStore.java | 8 +------- .../store/rest/TestModelManagerPersistence.java | 4 ++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedModelStore.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedModelStore.java index 3223ec0a75b4..0f37aa6cbc58 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedModelStore.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedModelStore.java @@ -70,19 +70,13 @@ protected ManagedModelStore( protected abstract M fromModelMap(SolrResourceLoader loader, Map modelMap); private static LinkedHashMap toModelMap(SolrLanguageModel model) { - final LinkedHashMap modelMap = new LinkedHashMap<>(5, 1.0f); + final LinkedHashMap modelMap = new LinkedHashMap<>(3, 1.0f); modelMap.put(NAME_KEY, model.getName()); modelMap.put(CLASS_KEY, model.getModelClassName()); modelMap.put(PARAMS_KEY, model.getParams()); return modelMap; } - @Override - protected ManagedResourceStorage createStorage( - ManagedResourceStorage.StorageIO storageIO, SolrResourceLoader loader) throws SolrException { - return new ManagedResourceStorage.JsonStorage(storageIO, loader, -1); - } - @Override protected void onManagedDataLoadedFromStorage(NamedList managedInitArgs, Object managedData) throws SolrException { diff --git a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestModelManagerPersistence.java b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestModelManagerPersistence.java index 92e8b68244e6..b98b7e73e892 100644 --- a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestModelManagerPersistence.java +++ b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestModelManagerPersistence.java @@ -39,12 +39,12 @@ public void cleanup() throws Exception { } @Test - public void testModelAreStoredCompact() throws Exception { + public void testModelAreStored() throws Exception { loadModel("cohere-model.json"); final String JSONOnDisk = Files.readString(embeddingModelStoreFile, StandardCharsets.UTF_8); Object objectFromDisk = Utils.fromJSONString(JSONOnDisk); - assertEquals(new String(Utils.toJSON(objectFromDisk, -1), UTF_8), JSONOnDisk); + assertEquals(new String(Utils.toJSON(objectFromDisk), UTF_8), JSONOnDisk); } @Test From 86949b32a1d7ebd7a2d8959eafdda50b66c122a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Rinaldi?= Date: Mon, 27 Apr 2026 12:21:52 +0200 Subject: [PATCH 3/6] [text-to-vector-refactoring] Quick fixes ported from review of document enrichment module --- .../model/SolrLanguageModel.java | 6 ++---- .../model/SolrTextToVectorModel.java | 18 +++++++++--------- .../rest/ManagedTextToVectorModelStore.java | 1 + 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java index f3da99e083f7..f91773b3484d 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java @@ -18,13 +18,11 @@ import java.util.Map; -/** Base class for Solr-managed wrappers around langchain4j language model instances. */ +/** Base class for Solr-managed wrappers around langchain4j used in {@code language-models} module */ public abstract class SolrLanguageModel { - // timeout is type Duration + // common parameters protected static final String TIMEOUT_PARAM = "timeout"; - - // the following is Integer type protected static final String MAX_RETRIES_PARAM = "maxRetries"; protected final String name; diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java index 708ad1ad8807..17d52f2da4bc 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java @@ -91,10 +91,10 @@ public static SolrTextToVectorModel getInstance( .getMethod(paramName, Integer.class) .invoke(builder, ((Long) params.get(paramName)).intValue()); - /* - * For primitive params if there's only one setter available, we call it. - * If there's choice we default to the string one - */ + /* + * For primitive params if there's only one setter available, we call it. + * If there's choice we default to the string one + */ default -> { ArrayList paramNameMatches = new ArrayList<>(); for (var method : builder.getClass().getMethods()) { @@ -138,11 +138,6 @@ public float[] vectorise(String text) { return vector.vector(); } - @Override - public String getModelClassName() { - return textToVector.getClass().getName(); - } - @Override public String toString() { return getClass().getSimpleName() + "(name=" + getName() + ")"; @@ -174,4 +169,9 @@ public boolean equals(Object obj) { if (!(obj instanceof SolrTextToVectorModel other)) return false; return Objects.equals(textToVector, other.textToVector) && Objects.equals(name, other.name); } + + @Override + public String getModelClassName() { + return textToVector.getClass().getName(); + } } diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java index 1cf14db31959..cf52f06ce75a 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java @@ -30,6 +30,7 @@ @ThreadSafe public class ManagedTextToVectorModelStore extends ManagedModelStore { + /** the model store rest endpoint */ public static final String REST_END_POINT = "/schema/text-to-vector-model-store"; public static void registerManagedTextToVectorModelStore( From 11bb601cb19fe4006e4604e3fccf523392b6ff62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Rinaldi?= Date: Tue, 28 Apr 2026 11:41:12 +0200 Subject: [PATCH 4/6] [language-model-refactoring] Pre-check changes --- .../languagemodels/model/SolrLanguageModel.java | 4 +++- .../store/LanguageModelException.java | 1 - .../store/LanguageModelStore.java | 3 +-- .../solr/languagemodels/store/package-info.java | 17 ++++++++++++++++- .../languagemodels/store/rest/package-info.java | 1 - .../model/SolrTextToVectorModel.java | 11 +++++------ 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java index f91773b3484d..b18b8508aa9b 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java @@ -18,7 +18,9 @@ import java.util.Map; -/** Base class for Solr-managed wrappers around langchain4j used in {@code language-models} module */ +/** + * Base class for Solr-managed wrappers around langchain4j used in {@code language-models} module + */ public abstract class SolrLanguageModel { // common parameters diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelException.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelException.java index 0a3454d6645b..6710ae85903a 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelException.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelException.java @@ -1,4 +1,3 @@ - /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelStore.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelStore.java index d99de0d5f989..a8c2aabaefaf 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelStore.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/LanguageModelStore.java @@ -42,8 +42,7 @@ public void clear() { public List getModels() { synchronized (availableModels) { - final List availableModelsValues = - new ArrayList<>(availableModels.values()); + final List availableModelsValues = new ArrayList<>(availableModels.values()); return Collections.unmodifiableList(availableModelsValues); } } diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/package-info.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/package-info.java index 8d1f1a7def69..7a80ec25fb37 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/package-info.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/package-info.java @@ -1,4 +1,19 @@ - +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /** Contains model store related classes. */ package org.apache.solr.languagemodels.store; diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java index 3e21be9b03da..a74e9742378b 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java @@ -17,4 +17,3 @@ /** Contains model store related classes. */ package org.apache.solr.languagemodels.store.rest; - diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java index 17d52f2da4bc..fc21d81fad63 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/model/SolrTextToVectorModel.java @@ -35,9 +35,8 @@ import org.slf4j.LoggerFactory; /** - * This object wraps a {@link EmbeddingModel} to encode text to - * vector. It's meant to be used as a managed resource with the {@link - * ManagedTextToVectorModelStore} + * This object wraps a {@link EmbeddingModel} to encode text to vector. It's meant to be used as a + * managed resource with the {@link ManagedTextToVectorModelStore} */ public class SolrTextToVectorModel extends SolrLanguageModel implements Accountable { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @@ -92,9 +91,9 @@ public static SolrTextToVectorModel getInstance( .invoke(builder, ((Long) params.get(paramName)).intValue()); /* - * For primitive params if there's only one setter available, we call it. - * If there's choice we default to the string one - */ + * For primitive params if there's only one setter available, we call it. + * If there's choice we default to the string one + */ default -> { ArrayList paramNameMatches = new ArrayList<>(); for (var method : builder.getClass().getMethods()) { From 56a4db4d2ba56af1e84819caf4f9eb97a474c823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Rinaldi?= Date: Wed, 29 Apr 2026 15:45:41 +0200 Subject: [PATCH 5/6] [text-to-vector-refactoring] Addressing Anna's comments --- .../apache/solr/languagemodels/model/SolrLanguageModel.java | 2 +- .../org/apache/solr/languagemodels/model/package-info.java | 2 +- ...anagedModelStore.java => ManagedLanguageModelStore.java} | 6 +++--- .../store/rest/ManagedTextToVectorModelStore.java | 4 ++-- ...ava => TestManagedLanguageModelStoreInitialization.java} | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) rename solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/{ManagedModelStore.java => ManagedLanguageModelStore.java} (95%) rename solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/{TestManagedModelStoreInitialization.java => TestManagedLanguageModelStoreInitialization.java} (96%) diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java index b18b8508aa9b..78a181d278a7 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/SolrLanguageModel.java @@ -19,7 +19,7 @@ import java.util.Map; /** - * Base class for Solr-managed wrappers around langchain4j used in {@code language-models} module + * Abstract base class for Solr-managed wrappers around langchain4j used in {@code language-models} module */ public abstract class SolrLanguageModel { diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/package-info.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/package-info.java index c7e5c3d80c98..f385bff798d3 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/package-info.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/model/package-info.java @@ -15,5 +15,5 @@ * limitations under the License. */ -/** Contains model store related classes. */ +/** Contains model related classes. */ package org.apache.solr.languagemodels.model; diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedModelStore.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedLanguageModelStore.java similarity index 95% rename from solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedModelStore.java rename to solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedLanguageModelStore.java index 0f37aa6cbc58..4d4316052524 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedModelStore.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/ManagedLanguageModelStore.java @@ -40,7 +40,7 @@ * via the REST API. Concrete subclasses supply the REST endpoint and the model instantiation logic. */ @ThreadSafe -public abstract class ManagedModelStore extends ManagedResource +public abstract class ManagedLanguageModelStore extends ManagedResource implements ManagedResource.ChildResourceSupport { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @@ -53,7 +53,7 @@ public abstract class ManagedModelStore extends Man private final LanguageModelStore store; private Object managedData; - protected ManagedModelStore( + protected ManagedLanguageModelStore( String resourceId, SolrResourceLoader loader, ManagedResourceStorage.StorageIO storageIO) throws SolrException { super(resourceId, loader, storageIO); @@ -146,7 +146,7 @@ public M getModel(String modelName) { } private static List modelsAsManagedResources(List models) { - return models.stream().map(ManagedModelStore::toModelMap).collect(Collectors.toList()); + return models.stream().map(ManagedLanguageModelStore::toModelMap).collect(Collectors.toList()); } @Override diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java index cf52f06ce75a..65a656291233 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/textvectorisation/store/rest/ManagedTextToVectorModelStore.java @@ -21,14 +21,14 @@ import org.apache.solr.common.SolrException; import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrResourceLoader; -import org.apache.solr.languagemodels.store.rest.ManagedModelStore; +import org.apache.solr.languagemodels.store.rest.ManagedLanguageModelStore; import org.apache.solr.languagemodels.textvectorisation.model.SolrTextToVectorModel; import org.apache.solr.rest.ManagedResourceObserver; import org.apache.solr.rest.ManagedResourceStorage; /** Managed Resource wrapper for the text-to-vector model store, exposed via REST */ @ThreadSafe -public class ManagedTextToVectorModelStore extends ManagedModelStore { +public class ManagedTextToVectorModelStore extends ManagedLanguageModelStore { /** the model store rest endpoint */ public static final String REST_END_POINT = "/schema/text-to-vector-model-store"; diff --git a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestManagedModelStoreInitialization.java b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestManagedLanguageModelStoreInitialization.java similarity index 96% rename from solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestManagedModelStoreInitialization.java rename to solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestManagedLanguageModelStoreInitialization.java index 244094b8764e..c384ff50f00d 100644 --- a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestManagedModelStoreInitialization.java +++ b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestManagedLanguageModelStoreInitialization.java @@ -20,7 +20,7 @@ import org.junit.After; import org.junit.Test; -public class TestManagedModelStoreInitialization extends TestLanguageModelBase { +public class TestManagedLanguageModelStoreInitialization extends TestLanguageModelBase { @After public void cleanUp() throws Exception { From de3328ffaaddb106ebcab1c7ea7381af6ee8b73e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Rinaldi?= Date: Thu, 30 Apr 2026 11:12:00 +0200 Subject: [PATCH 6/6] [text-to-vector-refactoring] Addressing Anna's comments --- .../solr/languagemodels/store/rest/package-info.java | 2 +- .../store/rest/TestModelManagerPersistence.java | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java index a74e9742378b..dd4548c93a5d 100644 --- a/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java +++ b/solr/modules/language-models/src/java/org/apache/solr/languagemodels/store/rest/package-info.java @@ -15,5 +15,5 @@ * limitations under the License. */ -/** Contains model store related classes. */ +/** Contains model store rest related classes. */ package org.apache.solr.languagemodels.store.rest; diff --git a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestModelManagerPersistence.java b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestModelManagerPersistence.java index b98b7e73e892..81988903f065 100644 --- a/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestModelManagerPersistence.java +++ b/solr/modules/language-models/src/test/org/apache/solr/languagemodels/textvectorisation/store/rest/TestModelManagerPersistence.java @@ -38,15 +38,6 @@ public void cleanup() throws Exception { afterTest(); } - @Test - public void testModelAreStored() throws Exception { - loadModel("cohere-model.json"); - - final String JSONOnDisk = Files.readString(embeddingModelStoreFile, StandardCharsets.UTF_8); - Object objectFromDisk = Utils.fromJSONString(JSONOnDisk); - assertEquals(new String(Utils.toJSON(objectFromDisk), UTF_8), JSONOnDisk); - } - @Test public void testModelStorePersistence() throws Exception { // check models are empty