Skip to content

Commit 5b93282

Browse files
committed
Normalize Ollama model names in auto-pull feature
In order to support edge cases due to different naming formats, this PR introduced an explicit normalization logic to ensure the correct matching when checking for the availability of a certain model. Signed-off-by: Thomas Vitale <[email protected]>
1 parent 1252216 commit 5b93282

File tree

2 files changed

+25
-4
lines changed

2 files changed

+25
-4
lines changed

models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/management/OllamaModelManager.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.springframework.ai.ollama.api.OllamaApi.DeleteModelRequest;
2222
import org.springframework.ai.ollama.api.OllamaApi.ListModelResponse;
2323
import org.springframework.ai.ollama.api.OllamaApi.PullModelRequest;
24+
import org.springframework.util.Assert;
2425
import org.springframework.util.CollectionUtils;
2526
import reactor.util.retry.Retry;
2627

@@ -55,14 +56,30 @@ public OllamaModelManager(OllamaApi ollamaApi, ModelManagementOptions options) {
5556
}
5657

5758
public boolean isModelAvailable(String modelName) {
59+
Assert.hasText(modelName, "modelName must not be empty");
5860
ListModelResponse listModelResponse = ollamaApi.listModels();
5961
if (!CollectionUtils.isEmpty(listModelResponse.models())) {
60-
// Not an equality check to support the implicit ":latest" tag.
61-
return listModelResponse.models().stream().anyMatch(m -> m.name().contains(modelName));
62+
var normalizedModel = normalizeModelName(modelName);
63+
return listModelResponse.models().stream().anyMatch(m -> m.name().equals(normalizedModel));
6264
}
6365
return false;
6466
}
6567

68+
/**
69+
* If the name starts with "hf.co" or "huggingface.co", leave it as is. If the name
70+
* follows the format "<string>:<string>", leave it as is. If the name follows the
71+
* format "<string>" and doesn't include any ":" sign, then add ":latest" as a suffix.
72+
*/
73+
private String normalizeModelName(String modelName) {
74+
if (modelName.startsWith("hf.co") || modelName.startsWith("huggingface.co")) {
75+
return modelName;
76+
}
77+
if (modelName.contains(":")) {
78+
return modelName;
79+
}
80+
return modelName + ":latest";
81+
}
82+
6683
public void deleteModel(String modelName) {
6784
logger.info("Start deletion of model: {}", modelName);
6885
if (!isModelAvailable(modelName)) {

models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/management/OllamaModelManagerIT.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,24 @@ public void whenModelNotAvailableReturnFalse() {
6464

6565
@Test
6666
public void pullAndDeleteModel() {
67-
var model = "all-minilm";
67+
var model = "all-minilm:33m";
6868
modelManager.pullModel(model, PullModelStrategy.WHEN_MISSING);
6969
var isModelAvailable = modelManager.isModelAvailable(model);
7070
assertThat(isModelAvailable).isTrue();
7171

72+
model = "all-minilm";
7273
modelManager.deleteModel(model);
7374
isModelAvailable = modelManager.isModelAvailable(model);
7475
assertThat(isModelAvailable).isFalse();
7576

76-
model = "all-minilm:latest";
7777
modelManager.pullModel(model, PullModelStrategy.WHEN_MISSING);
7878
isModelAvailable = modelManager.isModelAvailable(model);
7979
assertThat(isModelAvailable).isTrue();
8080

81+
model = "all-minilm:latest";
82+
isModelAvailable = modelManager.isModelAvailable(model);
83+
assertThat(isModelAvailable).isTrue();
84+
8185
modelManager.deleteModel(model);
8286
isModelAvailable = modelManager.isModelAvailable(model);
8387
assertThat(isModelAvailable).isFalse();

0 commit comments

Comments
 (0)