From 322d0fb3361eb4eb4cc9152cb87cfc157f5cbc42 Mon Sep 17 00:00:00 2001 From: Christian Tzolov Date: Thu, 17 Oct 2024 12:53:44 +0200 Subject: [PATCH] Refactor Ollama implementation and improve documentation - Enhance OllamaModelPuller with configurable retry timeout - Update test cases to use LLAMA3_1 instead of LLAMA3_2 - Improve Ollama documentation with clearer prerequisites and model pulling instructions - Update Spring AI introduction page with new logo and diagram - Remove unnecessary main method from OllamaModelPuller --- .../ai/ollama/api/OllamaModelPuller.java | 28 +++++----- .../ai/ollama/BaseOllamaIT.java | 2 +- .../OllamaChatModelFunctionCallingIT.java | 2 +- .../api/tool/OllamaApiToolFunctionCallIT.java | 8 ++- ...svg => spring-ai-integration-diagram2.svg} | 22 ++++---- .../images/spring-ai-integrationproblem.png | Bin 232373 -> 0 bytes .../ROOT/images/spring_ai_logo_with_text.svg | 51 ++++++++++++++++++ .../ROOT/pages/api/chat/ollama-chat.adoc | 18 +++---- .../api/embeddings/ollama-embeddings.adoc | 13 +++-- .../main/antora/modules/ROOT/pages/index.adoc | 8 +-- .../tool/FunctionCallbackInPromptIT.java | 2 +- .../tool/FunctionCallbackWrapperIT.java | 2 +- 12 files changed, 104 insertions(+), 52 deletions(-) rename spring-ai-docs/src/main/antora/modules/ROOT/images/{spring-ai-integration-diagram.svg => spring-ai-integration-diagram2.svg} (99%) delete mode 100644 spring-ai-docs/src/main/antora/modules/ROOT/images/spring-ai-integrationproblem.png create mode 100644 spring-ai-docs/src/main/antora/modules/ROOT/images/spring_ai_logo_with_text.svg diff --git a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaModelPuller.java b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaModelPuller.java index 28138ce39..bbf8fefdb 100644 --- a/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaModelPuller.java +++ b/models/spring-ai-ollama/src/main/java/org/springframework/ai/ollama/api/OllamaModelPuller.java @@ -35,8 +35,15 @@ public class OllamaModelPuller { private OllamaApi ollamaApi; + private final long pullRetryTimeoutMs; + public OllamaModelPuller(OllamaApi ollamaApi) { + this(ollamaApi, 5000); + } + + public OllamaModelPuller(OllamaApi ollamaApi, long retryTimeoutMs) { this.ollamaApi = ollamaApi; + this.pullRetryTimeoutMs = retryTimeoutMs; } public boolean isModelAvailable(String modelName) { @@ -56,35 +63,24 @@ public class OllamaModelPuller { return this.ollamaApi.deleteModel(new DeleteModelRequest(modelName)).getStatusCode().equals(HttpStatus.OK); } - public String pullModel(String modelName, boolean reTry) { + public String pullModel(String modelName, boolean enablePullRetry) { String status = ""; do { logger.info("Start Pulling model: {}", modelName); var progress = this.ollamaApi.pullModel(new PullModelRequest(modelName)); status = progress.status(); logger.info("Pulling model: {} - Status: {}", modelName, status); + try { - Thread.sleep(5000); + Thread.sleep(this.pullRetryTimeoutMs); } catch (InterruptedException e) { e.printStackTrace(); } } - while (reTry && !status.equals("success")); + while (enablePullRetry && !status.equals("success")); + return status; } - public static void main(String[] args) { - - var utils = new OllamaModelPuller(new OllamaApi()); - - System.out.println(utils.isModelAvailable("orca-mini:latest")); - - String model = "hf.co/bartowski/Llama-3.2-3B-Instruct-GGUF:Q8_0"; - - if (!utils.isModelAvailable(model)) { - utils.pullModel(model, true); - } - } - } diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/BaseOllamaIT.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/BaseOllamaIT.java index ac78a718d..be5982d5f 100644 --- a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/BaseOllamaIT.java +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/BaseOllamaIT.java @@ -10,7 +10,7 @@ public class BaseOllamaIT { private static final Logger logger = LoggerFactory.getLogger(BaseOllamaIT.class); // Toggle for running tests locally on native Ollama for a faster feedback loop. - private static final boolean useTestcontainers = false; + private static final boolean useTestcontainers = true; public static final OllamaContainer ollamaContainer; diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatModelFunctionCallingIT.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatModelFunctionCallingIT.java index 91c8bbd37..a3933b047 100644 --- a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatModelFunctionCallingIT.java +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/OllamaChatModelFunctionCallingIT.java @@ -52,7 +52,7 @@ class OllamaChatModelFunctionCallingIT extends BaseOllamaIT { private static final Logger logger = LoggerFactory.getLogger(OllamaChatModelFunctionCallingIT.class); - private static final String MODEL = OllamaModel.LLAMA3_2.getName(); + private static final String MODEL = OllamaModel.LLAMA3_1.getName(); @Autowired ChatModel chatModel; diff --git a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/api/tool/OllamaApiToolFunctionCallIT.java b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/api/tool/OllamaApiToolFunctionCallIT.java index 77ee8f2ad..db374b5fe 100644 --- a/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/api/tool/OllamaApiToolFunctionCallIT.java +++ b/models/spring-ai-ollama/src/test/java/org/springframework/ai/ollama/api/tool/OllamaApiToolFunctionCallIT.java @@ -46,7 +46,7 @@ import static org.assertj.core.api.Assertions.assertThat; @DisabledIf("isDisabled") public class OllamaApiToolFunctionCallIT extends BaseOllamaIT { - private static final String MODEL = OllamaModel.LLAMA3_2.getName(); + private static final String MODEL = OllamaModel.LLAMA3_1.getName(); private static final Logger logger = LoggerFactory.getLogger(OllamaApiToolFunctionCallIT.class); @@ -64,13 +64,11 @@ public class OllamaApiToolFunctionCallIT extends BaseOllamaIT { public void toolFunctionCall() { // Step 1: send the conversation and available functions to the model var message = Message.builder(Role.USER) - // .withContent("What's the weather like in San Francisco, Tokyo, and Paris? - // Perform multiple function calls for each location.") - .withContent("What's the weather like in San Francisco, Tokyo, and Paris?") + .withContent("What's the weather like in San Francisco, Tokyo, and Paris? Return temperature in Celsius.") .build(); var functionTool = new OllamaApi.ChatRequest.Tool(new OllamaApi.ChatRequest.Tool.Function("getCurrentWeather", - "Get the weather in location. Return temperature in Celsius.", ModelOptionsUtils.jsonToMap(""" + "Get the weather in location like city names.", ModelOptionsUtils.jsonToMap(""" { "type": "object", "properties": { diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/images/spring-ai-integration-diagram.svg b/spring-ai-docs/src/main/antora/modules/ROOT/images/spring-ai-integration-diagram2.svg similarity index 99% rename from spring-ai-docs/src/main/antora/modules/ROOT/images/spring-ai-integration-diagram.svg rename to spring-ai-docs/src/main/antora/modules/ROOT/images/spring-ai-integration-diagram2.svg index 324ff25e0..98115792a 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/images/spring-ai-integration-diagram.svg +++ b/spring-ai-docs/src/main/antora/modules/ROOT/images/spring-ai-integration-diagram2.svg @@ -29,13 +29,13 @@ inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" - inkscape:zoom="1.1588034" - inkscape:cx="301.17275" - inkscape:cy="204.52132" + inkscape:zoom="2.6322001" + inkscape:cx="313.04611" + inkscape:cy="194.13418" inkscape:window-width="1728" inkscape:window-height="925" inkscape:window-x="2321" - inkscape:window-y="320" + inkscape:window-y="292" inkscape:window-maximized="0" inkscape:current-layer="g21" />