diff --git a/data-ingestion/document-readers/document-readers-json-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java b/data-ingestion/document-readers/document-readers-json-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java index 14a6301..3827cb3 100644 --- a/data-ingestion/document-readers/document-readers-json-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java +++ b/data-ingestion/document-readers/document-readers-json-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java @@ -21,7 +21,7 @@ class SearchController { List searchSimilarDocuments(@RequestBody String query) { var documents = vectorStore.similaritySearch(query); return documents.stream() - .map(document -> new Document(document.getId(), document.getContent(), document.getMedia(), document.getMetadata())) + .map(document -> document.mutate().build()) .toList(); } diff --git a/data-ingestion/document-readers/document-readers-markdown-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java b/data-ingestion/document-readers/document-readers-markdown-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java index 14a6301..3827cb3 100644 --- a/data-ingestion/document-readers/document-readers-markdown-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java +++ b/data-ingestion/document-readers/document-readers-markdown-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java @@ -21,7 +21,7 @@ class SearchController { List searchSimilarDocuments(@RequestBody String query) { var documents = vectorStore.similaritySearch(query); return documents.stream() - .map(document -> new Document(document.getId(), document.getContent(), document.getMedia(), document.getMetadata())) + .map(document -> document.mutate().build()) .toList(); } diff --git a/data-ingestion/document-readers/document-readers-pdf-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java b/data-ingestion/document-readers/document-readers-pdf-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java index 14a6301..3827cb3 100644 --- a/data-ingestion/document-readers/document-readers-pdf-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java +++ b/data-ingestion/document-readers/document-readers-pdf-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java @@ -21,7 +21,7 @@ class SearchController { List searchSimilarDocuments(@RequestBody String query) { var documents = vectorStore.similaritySearch(query); return documents.stream() - .map(document -> new Document(document.getId(), document.getContent(), document.getMedia(), document.getMetadata())) + .map(document -> document.mutate().build()) .toList(); } diff --git a/data-ingestion/document-readers/document-readers-text-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java b/data-ingestion/document-readers/document-readers-text-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java index 14a6301..3827cb3 100644 --- a/data-ingestion/document-readers/document-readers-text-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java +++ b/data-ingestion/document-readers/document-readers-text-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java @@ -21,7 +21,7 @@ class SearchController { List searchSimilarDocuments(@RequestBody String query) { var documents = vectorStore.similaritySearch(query); return documents.stream() - .map(document -> new Document(document.getId(), document.getContent(), document.getMedia(), document.getMetadata())) + .map(document -> document.mutate().build()) .toList(); } diff --git a/data-ingestion/document-readers/document-readers-tika-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java b/data-ingestion/document-readers/document-readers-tika-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java index 14a6301..3827cb3 100644 --- a/data-ingestion/document-readers/document-readers-tika-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java +++ b/data-ingestion/document-readers/document-readers-tika-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java @@ -21,7 +21,7 @@ class SearchController { List searchSimilarDocuments(@RequestBody String query) { var documents = vectorStore.similaritySearch(query); return documents.stream() - .map(document -> new Document(document.getId(), document.getContent(), document.getMedia(), document.getMetadata())) + .map(document -> document.mutate().build()) .toList(); } diff --git a/data-ingestion/document-transformers/document-transformers-metadata-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java b/data-ingestion/document-transformers/document-transformers-metadata-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java index 14a6301..3827cb3 100644 --- a/data-ingestion/document-transformers/document-transformers-metadata-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java +++ b/data-ingestion/document-transformers/document-transformers-metadata-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java @@ -21,7 +21,7 @@ class SearchController { List searchSimilarDocuments(@RequestBody String query) { var documents = vectorStore.similaritySearch(query); return documents.stream() - .map(document -> new Document(document.getId(), document.getContent(), document.getMedia(), document.getMetadata())) + .map(document -> document.mutate().build()) .toList(); } diff --git a/data-ingestion/document-transformers/document-transformers-splitters-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java b/data-ingestion/document-transformers/document-transformers-splitters-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java index 14a6301..3827cb3 100644 --- a/data-ingestion/document-transformers/document-transformers-splitters-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java +++ b/data-ingestion/document-transformers/document-transformers-splitters-ollama/src/main/java/com/thomasvitale/ai/spring/SearchController.java @@ -21,7 +21,7 @@ class SearchController { List searchSimilarDocuments(@RequestBody String query) { var documents = vectorStore.similaritySearch(query); return documents.stream() - .map(document -> new Document(document.getId(), document.getContent(), document.getMedia(), document.getMetadata())) + .map(document -> document.mutate().build()) .toList(); } diff --git a/models/chat/chat-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/models/chat/chat-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java index d21e20c..b4f8d09 100644 --- a/models/chat/chat-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/models/chat/chat-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -1,7 +1,7 @@ package com.thomasvitale.ai.spring; import org.springframework.ai.chat.client.ChatClient; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.mistralai.MistralAiChatOptions; import org.springframework.ai.mistralai.api.MistralAiApi; import org.springframework.web.bind.annotation.GetMapping; @@ -32,9 +32,9 @@ String chat(String question) { String chatGenericOptions(String question) { return chatClient .prompt(question) - .options(ChatOptionsBuilder.builder() - .withModel(MistralAiApi.ChatModel.OPEN_MIXTRAL_7B.getName()) - .withTemperature(0.9) + .options(ChatOptions.builder() + .model(MistralAiApi.ChatModel.OPEN_MIXTRAL_7B.getName()) + .temperature(0.9) .build()) .call() .content(); diff --git a/models/chat/chat-mistral-ai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/models/chat/chat-mistral-ai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index f47463d..6e50812 100644 --- a/models/chat/chat-mistral-ai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/models/chat/chat-mistral-ai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -1,7 +1,7 @@ package com.thomasvitale.ai.spring.model; import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.mistralai.MistralAiChatOptions; import org.springframework.ai.mistralai.api.MistralAiApi; @@ -30,11 +30,11 @@ String chat(String question) { @GetMapping("/chat/generic-options") String chatGenericOptions(String question) { - return chatModel.call(new Prompt(question, ChatOptionsBuilder.builder() - .withModel(MistralAiApi.ChatModel.OPEN_MIXTRAL_7B.getName()) - .withTemperature(0.9) + return chatModel.call(new Prompt(question, ChatOptions.builder() + .model(MistralAiApi.ChatModel.OPEN_MIXTRAL_7B.getName()) + .temperature(0.9) .build())) - .getResult().getOutput().getContent(); + .getResult().getOutput().getText(); } @GetMapping("/chat/provider-options") @@ -42,7 +42,7 @@ String chatProviderOptions(String question) { return chatModel.call(new Prompt(question, MistralAiChatOptions.builder() .withSafePrompt(true) .build())) - .getResult().getOutput().getContent(); + .getResult().getOutput().getText(); } @GetMapping("/chat/stream") diff --git a/models/chat/chat-multiple-providers/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/models/chat/chat-multiple-providers/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index ed0b3ad..728c38b 100644 --- a/models/chat/chat-multiple-providers/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/models/chat/chat-multiple-providers/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -42,7 +42,7 @@ String chatMistralAiOptions(String question) { .withModel(MistralAiApi.ChatModel.OPEN_MIXTRAL_7B.getValue()) .withTemperature(1.0) .build())) - .getResult().getOutput().getContent(); + .getResult().getOutput().getText(); } @GetMapping("/chat/openai-options") @@ -51,7 +51,7 @@ String chatOpenAiOptions(String question) { .withModel(OpenAiApi.ChatModel.GPT_4_O_MINI.getValue()) .withTemperature(1.0) .build())) - .getResult().getOutput().getContent(); + .getResult().getOutput().getText(); } } diff --git a/models/chat/chat-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/models/chat/chat-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java index 4e1b170..de5d159 100644 --- a/models/chat/chat-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/models/chat/chat-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -1,7 +1,7 @@ package com.thomasvitale.ai.spring; import org.springframework.ai.chat.client.ChatClient; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.ollama.api.OllamaOptions; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -31,9 +31,9 @@ String chat(String question) { String chatGenericOptions(String question) { return chatClient .prompt(question) - .options(ChatOptionsBuilder.builder() - .withModel("llama3.2:1b") - .withTemperature(0.9) + .options(ChatOptions.builder() + .model("llama3.2:1b") + .temperature(0.9) .build()) .call() .content(); @@ -54,8 +54,8 @@ String chatProviderOptions(String question) { String chatHuggingFace(String question) { return chatClient .prompt(question) - .options(ChatOptionsBuilder.builder() - .withModel("hf.co/SanctumAI/Llama-3.2-1B-Instruct-GGUF") + .options(ChatOptions.builder() + .model("hf.co/SanctumAI/Llama-3.2-1B-Instruct-GGUF") .build()) .call() .content(); diff --git a/models/chat/chat-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/models/chat/chat-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index dadb533..5b7aee0 100644 --- a/models/chat/chat-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/models/chat/chat-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -1,7 +1,7 @@ package com.thomasvitale.ai.spring.model; import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.ollama.api.OllamaOptions; import org.springframework.web.bind.annotation.GetMapping; @@ -29,11 +29,11 @@ String chat(String question) { @GetMapping("/chat/generic-options") String chatGenericOptions(String question) { - return chatModel.call(new Prompt(question, ChatOptionsBuilder.builder() - .withModel("llama3.2:1b") - .withTemperature(0.9) + return chatModel.call(new Prompt(question, ChatOptions.builder() + .model("llama3.2:1b") + .temperature(0.9) .build())) - .getResult().getOutput().getContent(); + .getResult().getOutput().getText(); } @GetMapping("/chat/provider-options") @@ -41,15 +41,15 @@ String chatProviderOptions(String question) { return chatModel.call(new Prompt(question, OllamaOptions.builder() .withRepeatPenalty(1.5) .build())) - .getResult().getOutput().getContent(); + .getResult().getOutput().getText(); } @GetMapping("/chat/huggingface") String chatHuggingFace(String question) { - return chatModel.call(new Prompt(question, ChatOptionsBuilder.builder() - .withModel("hf.co/SanctumAI/Llama-3.2-1B-Instruct-GGUF") + return chatModel.call(new Prompt(question, ChatOptions.builder() + .model("hf.co/SanctumAI/Llama-3.2-1B-Instruct-GGUF") .build())) - .getResult().getOutput().getContent(); + .getResult().getOutput().getText(); } @GetMapping("/chat/stream") diff --git a/models/chat/chat-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/models/chat/chat-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java index 9b151b6..50abdf9 100644 --- a/models/chat/chat-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/models/chat/chat-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -1,7 +1,7 @@ package com.thomasvitale.ai.spring; import org.springframework.ai.chat.client.ChatClient; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.web.bind.annotation.GetMapping; @@ -32,9 +32,9 @@ String chat(String question) { String chatGenericOptions(String question) { return chatClient .prompt(question) - .options(ChatOptionsBuilder.builder() - .withModel(OpenAiApi.ChatModel.GPT_4_O_MINI.getValue()) - .withTemperature(0.9) + .options(ChatOptions.builder() + .model(OpenAiApi.ChatModel.GPT_4_O_MINI.getValue()) + .temperature(0.9) .build()) .call() .content(); diff --git a/models/chat/chat-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/models/chat/chat-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index 60df13d..4581ed5 100644 --- a/models/chat/chat-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/models/chat/chat-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -1,7 +1,7 @@ package com.thomasvitale.ai.spring.model; import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; @@ -30,11 +30,11 @@ String chat(String question) { @GetMapping("/chat/generic-options") String chatGenericOptions(String question) { - return chatModel.call(new Prompt(question, ChatOptionsBuilder.builder() - .withModel(OpenAiApi.ChatModel.GPT_4_O_MINI.getValue()) - .withTemperature(0.9) + return chatModel.call(new Prompt(question, ChatOptions.builder() + .model(OpenAiApi.ChatModel.GPT_4_O_MINI.getValue()) + .temperature(0.9) .build())) - .getResult().getOutput().getContent(); + .getResult().getOutput().getText(); } @GetMapping("/chat/provider-options") @@ -42,7 +42,7 @@ String chatProviderOptions(String question) { return chatModel.call(new Prompt(question, OpenAiChatOptions.builder() .withLogprobs(true) .build())) - .getResult().getOutput().getContent(); + .getResult().getOutput().getText(); } @GetMapping("/chat/stream") diff --git a/observability/models/observability-models-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/observability/models/observability-models-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java index 646fe21..2ef701d 100644 --- a/observability/models/observability-models-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/observability/models/observability-models-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -3,7 +3,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.chat.client.ChatClient; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.mistralai.MistralAiChatOptions; import org.springframework.ai.mistralai.api.MistralAiApi; import org.springframework.web.bind.annotation.GetMapping; @@ -18,7 +18,7 @@ class ChatController { private final ChatClient chatClient; ChatController(ChatClient.Builder chatClientBuilder) { - this.chatClient = chatClientBuilder.build(); + this.chatClient = chatClientBuilder.clone().build(); } @GetMapping("/chat") @@ -35,9 +35,9 @@ String chatGenericOptions(String question) { logger.info("Chatting with generic options: {}", question); return chatClient .prompt(question) - .options(ChatOptionsBuilder.builder() - .withModel(MistralAiApi.ChatModel.OPEN_MIXTRAL_7B.getName()) - .withTemperature(0.9) + .options(ChatOptions.builder() + .model(MistralAiApi.ChatModel.OPEN_MIXTRAL_7B.getName()) + .temperature(0.9) .build()) .call() .content(); diff --git a/observability/models/observability-models-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/observability/models/observability-models-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java index b219bf1..d5cb2de 100644 --- a/observability/models/observability-models-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/observability/models/observability-models-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -3,7 +3,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.chat.client.ChatClient; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.ollama.api.OllamaOptions; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -17,7 +17,7 @@ class ChatController { private final ChatClient chatClient; ChatController(ChatClient.Builder chatClientBuilder) { - this.chatClient = chatClientBuilder.build(); + this.chatClient = chatClientBuilder.clone().build(); } @GetMapping("/chat") @@ -34,9 +34,9 @@ String chatGenericOptions(String question) { logger.info("Chatting with generic options: {}", question); return chatClient .prompt(question) - .options(ChatOptionsBuilder.builder() - .withModel("llama3.2:1b") - .withTemperature(0.9) + .options(ChatOptions.builder() + .model("llama3.2:1b") + .temperature(0.9) .build()) .call() .content(); diff --git a/observability/models/observability-models-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/observability/models/observability-models-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java index 8f2ae48..60626de 100644 --- a/observability/models/observability-models-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/observability/models/observability-models-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -3,7 +3,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ai.chat.client.ChatClient; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.web.bind.annotation.GetMapping; @@ -18,7 +18,7 @@ class ChatController { private final ChatClient chatClient; ChatController(ChatClient.Builder chatClientBuilder) { - this.chatClient = chatClientBuilder.build(); + this.chatClient = chatClientBuilder.clone().build(); } @GetMapping("/chat") @@ -35,9 +35,9 @@ String chatGenericOptions(String question) { logger.info("Chatting with generic options: {}", question); return chatClient .prompt(question) - .options(ChatOptionsBuilder.builder() - .withModel(OpenAiApi.ChatModel.GPT_4_O_MINI.getValue()) - .withTemperature(0.9) + .options(ChatOptions.builder() + .model(OpenAiApi.ChatModel.GPT_4_O_MINI.getValue()) + .temperature(0.9) .build()) .call() .content(); diff --git a/observability/vector-stores/observability-vector-stores-pgvector/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/observability/vector-stores/observability-vector-stores-pgvector/src/main/java/com/thomasvitale/ai/spring/ChatController.java index 52c37e1..be513e7 100644 --- a/observability/vector-stores/observability-vector-stores-pgvector/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/observability/vector-stores/observability-vector-stores-pgvector/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -15,7 +15,7 @@ class ChatController { private final RetrievalAugmentationAdvisor retrievalAugmentationAdvisor; ChatController(ChatClient.Builder chatClientBuilder, VectorStore vectorStore) { - this.chatClient = chatClientBuilder.build(); + this.chatClient = chatClientBuilder.clone().build(); this.retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder() .documentRetriever(VectorStoreDocumentRetriever.builder() .vectorStore(vectorStore) diff --git a/patterns/function-calling/function-calling-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/patterns/function-calling/function-calling-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java index 2e1f6df..8e7d026 100644 --- a/patterns/function-calling/function-calling-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/patterns/function-calling/function-calling-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -42,10 +42,10 @@ String chatVariant(String authorName) { ) .functions( FunctionCallback.builder() - .description("Get the list of books written by the given author available in the library") - .responseConverter(Object::toString) .function("BooksByAuthor", bookService::getBooksByAuthor) + .description("Get the list of books written by the given author available in the library") .inputType(BookService.Author.class) + .responseConverter(Object::toString) .build() ) .call() diff --git a/patterns/function-calling/function-calling-mistral-ai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/function-calling/function-calling-mistral-ai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index 424117c..a4ed017 100644 --- a/patterns/function-calling/function-calling-mistral-ai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/patterns/function-calling/function-calling-mistral-ai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -3,8 +3,8 @@ import com.thomasvitale.ai.spring.BookService; import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.chat.prompt.PromptTemplate; -import org.springframework.ai.mistralai.MistralAiChatOptions; import org.springframework.ai.model.function.FunctionCallback; +import org.springframework.ai.model.function.FunctionCallingOptions; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -34,12 +34,12 @@ String chat(String authorName) { What books written by {author} are available in the library? """); Map model = Map.of("author", authorName); - var prompt = userPromptTemplate.create(model, MistralAiChatOptions.builder() + var prompt = userPromptTemplate.create(model, FunctionCallingOptions.builder() .withFunctions(Set.of("booksByAuthor")) .build()); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } @GetMapping("/chat/function/explicit") @@ -48,19 +48,19 @@ String chatVariant(String authorName) { What books written by {author} are available in the library? """); Map model = Map.of("author", authorName); - var prompt = userPromptTemplate.create(model, MistralAiChatOptions.builder() + var prompt = userPromptTemplate.create(model, FunctionCallingOptions.builder() .withFunctionCallbacks(List.of( FunctionCallback.builder() - .description("Get the list of books written by the given author available in the library") - .responseConverter(Object::toString) .function("BooksByAuthor", bookService::getBooksByAuthor) + .description("Get the list of books written by the given author available in the library") .inputType(BookService.Author.class) + .responseConverter(Object::toString) .build() )) .build()); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } } diff --git a/patterns/function-calling/function-calling-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/patterns/function-calling/function-calling-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java index 2e1f6df..8e7d026 100644 --- a/patterns/function-calling/function-calling-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/patterns/function-calling/function-calling-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -42,10 +42,10 @@ String chatVariant(String authorName) { ) .functions( FunctionCallback.builder() - .description("Get the list of books written by the given author available in the library") - .responseConverter(Object::toString) .function("BooksByAuthor", bookService::getBooksByAuthor) + .description("Get the list of books written by the given author available in the library") .inputType(BookService.Author.class) + .responseConverter(Object::toString) .build() ) .call() diff --git a/patterns/function-calling/function-calling-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/function-calling/function-calling-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index f68fd4c..a4ed017 100644 --- a/patterns/function-calling/function-calling-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/patterns/function-calling/function-calling-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -4,8 +4,7 @@ import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.chat.prompt.PromptTemplate; import org.springframework.ai.model.function.FunctionCallback; -import org.springframework.ai.model.function.FunctionCallbackWrapper; -import org.springframework.ai.ollama.api.OllamaOptions; +import org.springframework.ai.model.function.FunctionCallingOptions; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -35,12 +34,12 @@ String chat(String authorName) { What books written by {author} are available in the library? """); Map model = Map.of("author", authorName); - var prompt = userPromptTemplate.create(model, OllamaOptions.builder() + var prompt = userPromptTemplate.create(model, FunctionCallingOptions.builder() .withFunctions(Set.of("booksByAuthor")) .build()); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } @GetMapping("/chat/function/explicit") @@ -49,19 +48,19 @@ String chatVariant(String authorName) { What books written by {author} are available in the library? """); Map model = Map.of("author", authorName); - var prompt = userPromptTemplate.create(model, OllamaOptions.builder() + var prompt = userPromptTemplate.create(model, FunctionCallingOptions.builder() .withFunctionCallbacks(List.of( FunctionCallback.builder() - .description("Get the list of books written by the given author available in the library") - .responseConverter(Object::toString) .function("BooksByAuthor", bookService::getBooksByAuthor) + .description("Get the list of books written by the given author available in the library") .inputType(BookService.Author.class) + .responseConverter(Object::toString) .build() )) .build()); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } } diff --git a/patterns/function-calling/function-calling-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/patterns/function-calling/function-calling-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java index 2e1f6df..8e7d026 100644 --- a/patterns/function-calling/function-calling-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/patterns/function-calling/function-calling-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -42,10 +42,10 @@ String chatVariant(String authorName) { ) .functions( FunctionCallback.builder() - .description("Get the list of books written by the given author available in the library") - .responseConverter(Object::toString) .function("BooksByAuthor", bookService::getBooksByAuthor) + .description("Get the list of books written by the given author available in the library") .inputType(BookService.Author.class) + .responseConverter(Object::toString) .build() ) .call() diff --git a/patterns/function-calling/function-calling-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/function-calling/function-calling-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index e3f7985..a4ed017 100644 --- a/patterns/function-calling/function-calling-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/patterns/function-calling/function-calling-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -4,8 +4,7 @@ import org.springframework.ai.chat.model.ChatModel; import org.springframework.ai.chat.prompt.PromptTemplate; import org.springframework.ai.model.function.FunctionCallback; -import org.springframework.ai.model.function.FunctionCallbackWrapper; -import org.springframework.ai.openai.OpenAiChatOptions; +import org.springframework.ai.model.function.FunctionCallingOptions; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -35,12 +34,12 @@ String chat(String authorName) { What books written by {author} are available in the library? """); Map model = Map.of("author", authorName); - var prompt = userPromptTemplate.create(model, OpenAiChatOptions.builder() + var prompt = userPromptTemplate.create(model, FunctionCallingOptions.builder() .withFunctions(Set.of("booksByAuthor")) .build()); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } @GetMapping("/chat/function/explicit") @@ -49,19 +48,19 @@ String chatVariant(String authorName) { What books written by {author} are available in the library? """); Map model = Map.of("author", authorName); - var prompt = userPromptTemplate.create(model, OpenAiChatOptions.builder() + var prompt = userPromptTemplate.create(model, FunctionCallingOptions.builder() .withFunctionCallbacks(List.of( FunctionCallback.builder() - .description("Get the list of books written by the given author available in the library") - .responseConverter(Object::toString) .function("BooksByAuthor", bookService::getBooksByAuthor) + .description("Get the list of books written by the given author available in the library") .inputType(BookService.Author.class) + .responseConverter(Object::toString) .build() )) .build()); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } } diff --git a/patterns/multimodality/multimodality-mistral-ai/README.md b/patterns/multimodality/multimodality-mistral-ai/README.md new file mode 100644 index 0000000..a4cc92e --- /dev/null +++ b/patterns/multimodality/multimodality-mistral-ai/README.md @@ -0,0 +1,55 @@ +# Multimodality: Mistral AI + +Multimodality with LLMs via Mistral AI. + +## Mistral AI + +The application consumes models from the [Mistral AI](https://mistral.ai) platform. + +### Create an account + +Visit [console.mistral.ai](https://console.mistral.ai) and sign up for a new account. +You can choose the "Experiment" plan, which gives you access to the Mistral APIs for free. + +### Configure API Key + +In the Mistral AI console, navigate to _API Keys_ and generate a new API key. +Copy and securely store your API key on your machine as an environment variable. +The application will use it to access the Mistral AI API. + +```shell +export MISTRALAI_API_KEY= +``` + +## Running the application + +Run the application. + +```shell +./gradlew bootRun +``` + +## Calling the application + +> [!NOTE] +> These examples use the [httpie](https://httpie.io) CLI to send HTTP requests. + +### Image + +Call the application that will use a chat model to answer your question. + +```shell +http :8080/chat/image/file question=="What do you see in this picture? Give a short answer" -b +``` + +Try passing your custom prompt and check the result. + +```shell +http :8080/chat/image/file question=="Is there an animal in the picture?" -b +``` + +The image can also be fetched from a URL. + +```shell +http :8080/chat/image/url question=="What's in the picture? Answer in one sentence" -b +``` diff --git a/patterns/multimodality/multimodality-mistral-ai/build.gradle b/patterns/multimodality/multimodality-mistral-ai/build.gradle new file mode 100644 index 0000000..2876623 --- /dev/null +++ b/patterns/multimodality/multimodality-mistral-ai/build.gradle @@ -0,0 +1,37 @@ +plugins { + id 'java' + id 'org.springframework.boot' + id 'io.spring.dependency-management' + id 'org.graalvm.buildtools.native' +} + +group = 'com.thomasvitale' +version = '0.0.1-SNAPSHOT' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(23) + } +} + +repositories { + mavenCentral() + maven { url 'https://repo.spring.io/milestone' } + maven { url 'https://repo.spring.io/snapshot' } +} + +dependencies { + implementation platform("org.springframework.ai:spring-ai-bom:${springAiVersion}") + + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation "org.springframework.ai:spring-ai-mistral-ai-spring-boot-starter" + + developmentOnly 'org.springframework.boot:spring-boot-devtools' + + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/patterns/multimodality/multimodality-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/patterns/multimodality/multimodality-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java new file mode 100644 index 0000000..421d499 --- /dev/null +++ b/patterns/multimodality/multimodality-mistral-ai/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -0,0 +1,56 @@ +package com.thomasvitale.ai.spring; + +import org.springframework.ai.chat.client.ChatClient; +import org.springframework.ai.model.Media; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; +import org.springframework.util.MimeTypeUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.net.MalformedURLException; +import java.net.URI; + +/** + * Chat examples using the high-level ChatClient API. + */ +@RestController +class ChatController { + + private final ChatClient chatClient; + + @Value("classpath:speech.mp3") + private Resource audio; + + @Value("classpath:tabby-cat.png") + private Resource image; + + public ChatController(ChatClient.Builder chatClientBuilder) { + this.chatClient = chatClientBuilder.build(); + } + + @GetMapping("/chat/image/file") + String chatImageFile(String question) { + return chatClient.prompt() + .user(userSpec -> userSpec + .text(question) + .media(MimeTypeUtils.IMAGE_PNG, image) + ) + .call() + .content(); + } + + @GetMapping("/chat/image/url") + String chatImageUrl(String question) throws MalformedURLException { + var imageUrl = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"; + var url = URI.create(imageUrl).toURL(); + return chatClient.prompt() + .user(userSpec -> userSpec + .text(question) + .media(new Media(MimeTypeUtils.IMAGE_PNG, url)) + ) + .call() + .content(); + } + +} diff --git a/patterns/multimodality/multimodality-mistral-ai/src/main/java/com/thomasvitale/ai/spring/MultimodalityMistralAiApplication.java b/patterns/multimodality/multimodality-mistral-ai/src/main/java/com/thomasvitale/ai/spring/MultimodalityMistralAiApplication.java new file mode 100644 index 0000000..1953893 --- /dev/null +++ b/patterns/multimodality/multimodality-mistral-ai/src/main/java/com/thomasvitale/ai/spring/MultimodalityMistralAiApplication.java @@ -0,0 +1,13 @@ +package com.thomasvitale.ai.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MultimodalityMistralAiApplication { + + public static void main(String[] args) { + SpringApplication.run(MultimodalityMistralAiApplication.class, args); + } + +} diff --git a/patterns/multimodality/multimodality-mistral-ai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/multimodality/multimodality-mistral-ai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java new file mode 100644 index 0000000..f6575cd --- /dev/null +++ b/patterns/multimodality/multimodality-mistral-ai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -0,0 +1,55 @@ +package com.thomasvitale.ai.spring.model; + +import org.springframework.ai.chat.messages.UserMessage; +import org.springframework.ai.chat.model.ChatModel; +import org.springframework.ai.chat.prompt.Prompt; +import org.springframework.ai.model.Media; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; +import org.springframework.util.MimeTypeUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.net.MalformedURLException; +import java.net.URI; + +/** + * Chat examples using the low-level ChatModel API. + */ +@RestController +@RequestMapping("/model") +class ChatModelController { + + private final ChatModel chatModel; + + @Value("classpath:speech.mp3") + private Resource audio; + + @Value("classpath:tabby-cat.png") + private Resource image; + + ChatModelController(ChatModel chatModel) { + this.chatModel = chatModel; + } + + @GetMapping("/chat/image/file") + String chatImageFile(String question) { + var userMessage = new UserMessage(question, new Media(MimeTypeUtils.IMAGE_PNG, image)); + var prompt = new Prompt(userMessage); + var chatResponse = chatModel.call(prompt); + return chatResponse.getResult().getOutput().getText(); + } + + @GetMapping("/chat/image/url") + String chatImageUrl(String question) throws MalformedURLException { + var imageUrl = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"; + var url = URI.create(imageUrl).toURL(); + + var userMessage = new UserMessage(question, new Media(MimeTypeUtils.IMAGE_PNG, url)); + var prompt = new Prompt(userMessage); + var chatResponse = chatModel.call(prompt); + return chatResponse.getResult().getOutput().getText(); + } + +} diff --git a/patterns/multimodality/multimodality-mistral-ai/src/main/resources/application.yml b/patterns/multimodality/multimodality-mistral-ai/src/main/resources/application.yml new file mode 100644 index 0000000..b43156f --- /dev/null +++ b/patterns/multimodality/multimodality-mistral-ai/src/main/resources/application.yml @@ -0,0 +1,8 @@ +spring: + ai: + mistralai: + api-key: ${MISTRALAI_API_KEY} + chat: + options: + model: pixtral-large-latest + temperature: 0.7 diff --git a/patterns/multimodality/multimodality-mistral-ai/src/main/resources/tabby-cat.png b/patterns/multimodality/multimodality-mistral-ai/src/main/resources/tabby-cat.png new file mode 100644 index 0000000..4c564e4 Binary files /dev/null and b/patterns/multimodality/multimodality-mistral-ai/src/main/resources/tabby-cat.png differ diff --git a/patterns/multimodality/multimodality-mistral-ai/src/test/java/com/thomasvitale/ai/spring/MultimodalityMistralAiApplicationTests.java b/patterns/multimodality/multimodality-mistral-ai/src/test/java/com/thomasvitale/ai/spring/MultimodalityMistralAiApplicationTests.java new file mode 100644 index 0000000..c39fcc4 --- /dev/null +++ b/patterns/multimodality/multimodality-mistral-ai/src/test/java/com/thomasvitale/ai/spring/MultimodalityMistralAiApplicationTests.java @@ -0,0 +1,56 @@ +package com.thomasvitale.ai.spring; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.web.reactive.server.WebTestClient; + +import static org.assertj.core.api.Assertions.assertThat; + +@Disabled("Not implemented") +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureWebTestClient(timeout = "60s") +@EnabledIfEnvironmentVariable(named = "MISTRALAI_API_KEY", matches = ".*") +class MultimodalityMistralAiApplicationTests { + + @Autowired + WebTestClient webTestClient; + + @ParameterizedTest + @ValueSource(strings = {"/chat/image/file", "/model/chat/image/file"}) + void chatFromImageFile(String path) { + webTestClient + .get() + .uri(uriBuilder -> uriBuilder + .path(path) + .queryParam("question", "What do you see in this picture? Give a short answer") + .build()) + .exchange() + .expectStatus().isOk() + .expectBody(String.class).value(result -> { + assertThat(result).containsIgnoringCase("cat"); + }); + } + + @ParameterizedTest + @ValueSource(strings = {"/chat/image/url", "/model/chat/image/url"}) + void chatFromImageUrl(String path) { + webTestClient + .get() + .uri(uriBuilder -> uriBuilder + .path(path) + .queryParam("question", "What do you see in this picture? Give a short answer") + .build()) + .exchange() + .expectStatus().isOk() + .expectBody(String.class).value(result -> { + assertThat(result).containsIgnoringCase("dice"); + }); + } + +} + diff --git a/patterns/multimodality/multimodality-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/multimodality/multimodality-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index b9ac5de..54bb74a 100644 --- a/patterns/multimodality/multimodality-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/patterns/multimodality/multimodality-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -32,7 +32,7 @@ String chatImageFile(String question) { var userMessage = new UserMessage(question, new Media(MimeTypeUtils.IMAGE_PNG, image)); var prompt = new Prompt(userMessage); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } } diff --git a/patterns/multimodality/multimodality-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/multimodality/multimodality-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index 74bd757..bf8976f 100644 --- a/patterns/multimodality/multimodality-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/patterns/multimodality/multimodality-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -40,7 +40,7 @@ String chatImageFile(String question) { var userMessage = new UserMessage(question, new Media(MimeTypeUtils.IMAGE_PNG, image)); var prompt = new Prompt(userMessage); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } @GetMapping("/chat/image/url") @@ -51,7 +51,7 @@ String chatImageUrl(String question) throws MalformedURLException { var userMessage = new UserMessage(question, new Media(MimeTypeUtils.IMAGE_PNG, url)); var prompt = new Prompt(userMessage); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } @GetMapping("/chat/audio/file") @@ -61,7 +61,7 @@ String chatAudioFile(String question) { .withModel(OpenAiApi.ChatModel.GPT_4_O_AUDIO_PREVIEW.getValue()) .build()); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } } diff --git a/patterns/prompts/prompts-basics-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/patterns/prompts/prompts-basics-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java index 7dddacb..3c485a3 100644 --- a/patterns/prompts/prompts-basics-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/patterns/prompts/prompts-basics-ollama/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -33,7 +33,7 @@ String chatPrompt(@RequestBody String question) { .prompt(new Prompt(question)) .call() .chatResponse(); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } @PostMapping("/chat/full") diff --git a/patterns/prompts/prompts-basics-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/prompts/prompts-basics-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index 512100c..7ecba88 100644 --- a/patterns/prompts/prompts-basics-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/patterns/prompts/prompts-basics-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -28,7 +28,7 @@ String chatText(@RequestBody String question) { @PostMapping("/chat/prompt") String chatPrompt(@RequestBody String question) { - return chatModel.call(new Prompt(question)).getResult().getOutput().getContent(); + return chatModel.call(new Prompt(question)).getResult().getOutput().getText(); } @PostMapping("/chat/full") diff --git a/patterns/prompts/prompts-basics-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/patterns/prompts/prompts-basics-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java index 80aec13..3c485a3 100644 --- a/patterns/prompts/prompts-basics-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/patterns/prompts/prompts-basics-openai/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -2,9 +2,7 @@ import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @@ -35,16 +33,13 @@ String chatPrompt(@RequestBody String question) { .prompt(new Prompt(question)) .call() .chatResponse(); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } @PostMapping("/chat/full") ChatResponse chatFullResponse(@RequestBody String question) { return chatClient .prompt(question) - .options(ChatOptionsBuilder.builder() - .withModel(OpenAiApi.ChatModel.O1_PREVIEW.getValue()) - .build()) .call() .chatResponse(); } diff --git a/patterns/prompts/prompts-basics-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/prompts/prompts-basics-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index 512100c..7ecba88 100644 --- a/patterns/prompts/prompts-basics-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/patterns/prompts/prompts-basics-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -28,7 +28,7 @@ String chatText(@RequestBody String question) { @PostMapping("/chat/prompt") String chatPrompt(@RequestBody String question) { - return chatModel.call(new Prompt(question)).getResult().getOutput().getContent(); + return chatModel.call(new Prompt(question)).getResult().getOutput().getText(); } @PostMapping("/chat/full") diff --git a/patterns/prompts/prompts-templates-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/prompts/prompts-templates-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index a4113a8..272e0cc 100644 --- a/patterns/prompts/prompts-templates-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/patterns/prompts/prompts-templates-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -46,7 +46,7 @@ String chatUserMessageTemplate(@RequestBody MusicQuestion question) { var prompt = userPromptTemplate.create(model); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } @PostMapping("/chat/system") @@ -61,7 +61,7 @@ String chatSystemMessageTemplate(@RequestBody String question) { var prompt = new Prompt(List.of(systemMessage, userMessage)); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } @PostMapping("/chat/external") @@ -74,7 +74,7 @@ String chatSystemMessageTemplateExternal(@RequestBody String question) { var prompt = new Prompt(List.of(systemMessage, userMessage)); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } private String randomGreeting() { diff --git a/patterns/prompts/prompts-templates-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/prompts/prompts-templates-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index a4113a8..272e0cc 100644 --- a/patterns/prompts/prompts-templates-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/patterns/prompts/prompts-templates-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -46,7 +46,7 @@ String chatUserMessageTemplate(@RequestBody MusicQuestion question) { var prompt = userPromptTemplate.create(model); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } @PostMapping("/chat/system") @@ -61,7 +61,7 @@ String chatSystemMessageTemplate(@RequestBody String question) { var prompt = new Prompt(List.of(systemMessage, userMessage)); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } @PostMapping("/chat/external") @@ -74,7 +74,7 @@ String chatSystemMessageTemplateExternal(@RequestBody String question) { var prompt = new Prompt(List.of(systemMessage, userMessage)); var chatResponse = chatModel.call(prompt); - return chatResponse.getResult().getOutput().getContent(); + return chatResponse.getResult().getOutput().getText(); } private String randomGreeting() { diff --git a/patterns/structured-output/structured-output-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/structured-output/structured-output-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index 637dcee..a8c3078 100644 --- a/patterns/structured-output/structured-output-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/patterns/structured-output/structured-output-ollama/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -46,7 +46,7 @@ ArtistInfo chatBeanOutput(@RequestBody MusicQuestion question) { .build()); var chatResponse = chatModel.call(prompt); - return outputConverter.convert(chatResponse.getResult().getOutput().getContent()); + return outputConverter.convert(chatResponse.getResult().getOutput().getText()); } @PostMapping("/chat/map") @@ -61,7 +61,7 @@ Map chatMapOutput() { var prompt = userPromptTemplate.create(model); var chatResponse = chatModel.call(prompt); - return outputConverter.convert(chatResponse.getResult().getOutput().getContent()); + return outputConverter.convert(chatResponse.getResult().getOutput().getText()); } @PostMapping("/chat/list") @@ -78,7 +78,7 @@ List chatListOutput(@RequestBody MusicQuestion question) { var prompt = userPromptTemplate.create(model); var chatResponse = chatModel.call(prompt); - return outputConverter.convert(chatResponse.getResult().getOutput().getContent()); + return outputConverter.convert(chatResponse.getResult().getOutput().getText()); } } diff --git a/patterns/structured-output/structured-output-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java b/patterns/structured-output/structured-output-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java index dd81978..9cb41ce 100644 --- a/patterns/structured-output/structured-output-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java +++ b/patterns/structured-output/structured-output-openai/src/main/java/com/thomasvitale/ai/spring/model/ChatModelController.java @@ -49,7 +49,7 @@ ArtistInfo chatBeanOutput(@RequestBody MusicQuestion question) { .build()); var chatResponse = chatModel.call(prompt); - return outputConverter.convert(chatResponse.getResult().getOutput().getContent()); + return outputConverter.convert(chatResponse.getResult().getOutput().getText()); } @PostMapping("/chat/map") @@ -64,7 +64,7 @@ Map chatMapOutput() { var prompt = userPromptTemplate.create(model); var chatResponse = chatModel.call(prompt); - return outputConverter.convert(chatResponse.getResult().getOutput().getContent()); + return outputConverter.convert(chatResponse.getResult().getOutput().getText()); } @PostMapping("/chat/list") @@ -81,7 +81,7 @@ List chatListOutput(@RequestBody MusicQuestion question) { var prompt = userPromptTemplate.create(model); var chatResponse = chatModel.call(prompt); - return outputConverter.convert(chatResponse.getResult().getOutput().getContent()); + return outputConverter.convert(chatResponse.getResult().getOutput().getText()); } @PostMapping("/chat/json") @@ -97,7 +97,7 @@ ArtistInfoVariant chatJsonOutput(@RequestBody MusicQuestion question) { .build()); var chatResponse = chatModel.call(prompt); - return outputConverter.convert(chatResponse.getResult().getOutput().getContent()); + return outputConverter.convert(chatResponse.getResult().getOutput().getText()); } } diff --git a/settings.gradle b/settings.gradle index e9ce066..ede1cd5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -44,6 +44,7 @@ include 'patterns:prompts:prompts-templates-openai' include 'patterns:structured-output:structured-output-ollama' include 'patterns:structured-output:structured-output-openai' +include 'patterns:multimodality:multimodality-mistral-ai' include 'patterns:multimodality:multimodality-ollama' include 'patterns:multimodality:multimodality-openai' diff --git a/use-cases/chatbot/src/main/java/com/thomasvitale/ai/spring/ChatbotController.java b/use-cases/chatbot/src/main/java/com/thomasvitale/ai/spring/ChatbotController.java index 0df334c..53d4d63 100644 --- a/use-cases/chatbot/src/main/java/com/thomasvitale/ai/spring/ChatbotController.java +++ b/use-cases/chatbot/src/main/java/com/thomasvitale/ai/spring/ChatbotController.java @@ -16,7 +16,7 @@ class ChatbotController { private final ChatClient chatClient; ChatbotController(ChatClient.Builder chatClientBuilder, ChatMemory chatMemory) { - this.chatClient = chatClientBuilder + this.chatClient = chatClientBuilder.clone() .defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory)) .build(); } diff --git a/use-cases/question-answering/src/main/java/com/thomasvitale/ai/spring/ChatController.java b/use-cases/question-answering/src/main/java/com/thomasvitale/ai/spring/ChatController.java index 52c37e1..be513e7 100644 --- a/use-cases/question-answering/src/main/java/com/thomasvitale/ai/spring/ChatController.java +++ b/use-cases/question-answering/src/main/java/com/thomasvitale/ai/spring/ChatController.java @@ -15,7 +15,7 @@ class ChatController { private final RetrievalAugmentationAdvisor retrievalAugmentationAdvisor; ChatController(ChatClient.Builder chatClientBuilder, VectorStore vectorStore) { - this.chatClient = chatClientBuilder.build(); + this.chatClient = chatClientBuilder.clone().build(); this.retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder() .documentRetriever(VectorStoreDocumentRetriever.builder() .vectorStore(vectorStore) diff --git a/use-cases/semantic-search/src/main/java/com/thomasvitale/ai/spring/SemanticSearchController.java b/use-cases/semantic-search/src/main/java/com/thomasvitale/ai/spring/SemanticSearchController.java index 19a8027..4e04bb7 100644 --- a/use-cases/semantic-search/src/main/java/com/thomasvitale/ai/spring/SemanticSearchController.java +++ b/use-cases/semantic-search/src/main/java/com/thomasvitale/ai/spring/SemanticSearchController.java @@ -21,7 +21,7 @@ class SemanticSearchController { List semanticSearch(@RequestBody String query) { return vectorStore.similaritySearch(SearchRequest.query(query).withTopK(3)) .stream() - .map(document -> new InstrumentNote(document.getContent())) + .map(document -> new InstrumentNote(document.getText())) .toList(); } diff --git a/use-cases/structured-data-extraction/src/main/java/com/thomasvitale/ai/spring/StructuredDataExtractionController.java b/use-cases/structured-data-extraction/src/main/java/com/thomasvitale/ai/spring/StructuredDataExtractionController.java index bb9a181..3f92392 100644 --- a/use-cases/structured-data-extraction/src/main/java/com/thomasvitale/ai/spring/StructuredDataExtractionController.java +++ b/use-cases/structured-data-extraction/src/main/java/com/thomasvitale/ai/spring/StructuredDataExtractionController.java @@ -1,7 +1,7 @@ package com.thomasvitale.ai.spring; import org.springframework.ai.chat.client.ChatClient; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @@ -12,9 +12,9 @@ class StructuredDataExtractionController { private final ChatClient chatClient; StructuredDataExtractionController(ChatClient.Builder chatClientBuilder) { - this.chatClient = chatClientBuilder - .defaultOptions(ChatOptionsBuilder.builder() - .withTemperature(0.0) + this.chatClient = chatClientBuilder.clone() + .defaultOptions(ChatOptions.builder() + .temperature(0.0) .build()) .build(); } diff --git a/use-cases/text-classification/src/main/java/com/thomasvitale/ai/spring/ClassificationController.java b/use-cases/text-classification/src/main/java/com/thomasvitale/ai/spring/ClassificationController.java index 07451ea..5db8d06 100644 --- a/use-cases/text-classification/src/main/java/com/thomasvitale/ai/spring/ClassificationController.java +++ b/use-cases/text-classification/src/main/java/com/thomasvitale/ai/spring/ClassificationController.java @@ -5,7 +5,7 @@ import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.UserMessage; -import org.springframework.ai.chat.prompt.ChatOptionsBuilder; +import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @@ -19,8 +19,8 @@ class ClassificationController { ClassificationController(ChatClient.Builder chatClientBuilder) { this.chatClient = chatClientBuilder - .defaultOptions(ChatOptionsBuilder.builder() - .withTemperature(0.0) + .defaultOptions(ChatOptions.builder() + .temperature(0.0) .build()) .build(); }