From 7b41735ffb50c1aa1a535c07102ef0970b8ad9a0 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Date: Fri, 21 Mar 2025 16:14:57 +0000 Subject: [PATCH 1/5] Added Vision sample with default BaseAddress definition if not provided in the client --- .../Ollama_ChatCompletionWithVision.cs | 35 +++++++++++++++++++ .../OllamaServiceCollectionExtensions.cs | 6 ++++ 2 files changed, 41 insertions(+) create mode 100644 dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs diff --git a/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs b/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs new file mode 100644 index 000000000000..3e7fa71011dc --- /dev/null +++ b/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.SemanticKernel; +using Microsoft.SemanticKernel.ChatCompletion; +using Resources; + +namespace ChatCompletion; + +// This example shows how to use GPT Vision model with different content types (text and image). +public class Ollama_ChatCompletionWithVision(ITestOutputHelper output) : BaseTest(output) +{ + [Fact] + public async Task LocalImageAsync() + { + var imageBytes = await EmbeddedResource.ReadAllAsync("sample_image.jpg"); + + var kernel = Kernel.CreateBuilder() + .AddOllamaChatCompletion("llama3.2-vision") + .Build(); + + var chatCompletionService = kernel.GetRequiredService(); + + var chatHistory = new ChatHistory("You are a friendly assistant."); + + chatHistory.AddUserMessage( + [ + new TextContent("What’s in this image?"), + new ImageContent(imageBytes, "image/jpg") + ]); + + var reply = await chatCompletionService.GetChatMessageContentAsync(chatHistory); + + Console.WriteLine(reply.Content); + } +} diff --git a/dotnet/src/Connectors/Connectors.Ollama/Extensions/OllamaServiceCollectionExtensions.cs b/dotnet/src/Connectors/Connectors.Ollama/Extensions/OllamaServiceCollectionExtensions.cs index 220737be2749..84d63ff6506b 100644 --- a/dotnet/src/Connectors/Connectors.Ollama/Extensions/OllamaServiceCollectionExtensions.cs +++ b/dotnet/src/Connectors/Connectors.Ollama/Extensions/OllamaServiceCollectionExtensions.cs @@ -190,6 +190,9 @@ public static IServiceCollection AddOllamaChatCompletion( var loggerFactory = serviceProvider.GetService(); + // Set default base address if not already set + httpClient.BaseAddress ??= new Uri("http://localhost:11434"); + var builder = ((IChatClient)new OllamaApiClient(httpClient, modelId)) .AsBuilder() .UseFunctionInvocation(loggerFactory, config => config.MaximumIterationsPerRequest = MaxInflightAutoInvokes); @@ -299,6 +302,9 @@ public static IServiceCollection AddOllamaTextEmbeddingGeneration( { httpClient ??= HttpClientProvider.GetHttpClient(httpClient, serviceProvider); + // Set default base address if not already set + httpClient.BaseAddress ??= new Uri("http://localhost:11434"); + var loggerFactory = serviceProvider.GetService(); var builder = ((IEmbeddingGenerator>)new OllamaApiClient(httpClient, modelId)) From 5304bb8548cac4e6500c3a93292b1db120cf60c1 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Date: Fri, 21 Mar 2025 16:19:12 +0000 Subject: [PATCH 2/5] Add descriptions and updates to sample --- .../Ollama_ChatCompletionWithVision.cs | 12 ++++++++++-- dotnet/samples/Concepts/README.md | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs b/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs index 3e7fa71011dc..0c9b5199bb3c 100644 --- a/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs +++ b/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs @@ -6,12 +6,20 @@ namespace ChatCompletion; -// This example shows how to use GPT Vision model with different content types (text and image). +/// +/// This sample shows how to use llama3.2-vision model with different content types (text and image). +/// public class Ollama_ChatCompletionWithVision(ITestOutputHelper output) : BaseTest(output) { + /// + /// This sample uses a local image file and sends it to the model along + /// with a text message the get the description of the image. + /// [Fact] - public async Task LocalImageAsync() + public async Task GetLocalImageDescription() { + Console.WriteLine($"======== Ollama - {nameof(GetLocalImageDescription)} ========"); + var imageBytes = await EmbeddedResource.ReadAllAsync("sample_image.jpg"); var kernel = Kernel.CreateBuilder() diff --git a/dotnet/samples/Concepts/README.md b/dotnet/samples/Concepts/README.md index e59ec178c9ce..be69c5112761 100644 --- a/dotnet/samples/Concepts/README.md +++ b/dotnet/samples/Concepts/README.md @@ -72,6 +72,7 @@ dotnet test -l "console;verbosity=detailed" --filter "FullyQualifiedName=ChatCom - [MultipleProviders_ChatHistoryReducer](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/ChatCompletion/MultipleProviders_ChatHistoryReducer.cs) - [Ollama_ChatCompletion](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletion.cs) - [Ollama_ChatCompletionStreaming](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionStreaming.cs) +- [Ollama_ChatCompletionWithVision](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs) - [Onnx_ChatCompletion](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/ChatCompletion/Onnx_ChatCompletion.cs) - [Onnx_ChatCompletionStreaming](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/ChatCompletion/Onnx_ChatCompletionStreaming.cs) - [OpenAI_ChatCompletion](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/ChatCompletion/OpenAI_ChatCompletion.cs) From 3af13ba8e4dba3ac2dcda74496ee3a42e9fd1474 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Date: Fri, 21 Mar 2025 16:28:23 +0000 Subject: [PATCH 3/5] Add UT to ensure expected behavior --- .../Services/OllamaChatCompletionTests.cs | 8 ++++++++ .../Services/OllamaTextEmbeddingGenerationTests.cs | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaChatCompletionTests.cs b/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaChatCompletionTests.cs index a1b2e4f64d1d..9ee6b52610e0 100644 --- a/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaChatCompletionTests.cs +++ b/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaChatCompletionTests.cs @@ -39,6 +39,14 @@ public OllamaChatCompletionTests() this._httpClient = new HttpClient(this._multiMessageHandlerStub, false) { BaseAddress = new Uri("http://localhost:11434") }; } + [Fact] + public void AddOllamaChatCompletionShouldWorkOnlyForModelId() + { + // Arrange + var kernel = Kernel.CreateBuilder().AddOllamaChatCompletion("model-id").Build(); + var service = kernel.GetRequiredService(); + } + [Fact] public async Task ShouldSendPromptToServiceAsync() { diff --git a/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs b/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs index fde471a85679..ee73c9558165 100644 --- a/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs +++ b/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs @@ -5,6 +5,7 @@ using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; +using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Embeddings; using OllamaSharp; using OllamaSharp.Models; @@ -24,6 +25,14 @@ public OllamaTextEmbeddingGenerationTests() this._httpClient = new HttpClient(this._messageHandlerStub, false) { BaseAddress = new Uri("http://localhost:11434") }; } + [Fact] + public void AddOllamaTextEmbeddingGenerationShouldWorkOnlyForModelId() + { + // Arrange + var kernel = Kernel.CreateBuilder().AddOllamaTextEmbeddingGeneration("model-id").Build(); + var service = kernel.GetRequiredService(); + } + [Fact] public async Task ShouldSendPromptToServiceAsync() { From e1d64e0e84a9b21c1c66ed7df0745dc7b4d9a26f Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Date: Mon, 24 Mar 2025 09:12:10 +0000 Subject: [PATCH 4/5] Revert default uri --- .../ChatCompletion/Ollama_ChatCompletionWithVision.cs | 2 +- .../Services/OllamaChatCompletionTests.cs | 8 -------- .../Services/OllamaTextEmbeddingGenerationTests.cs | 8 -------- .../Extensions/OllamaServiceCollectionExtensions.cs | 6 ------ 4 files changed, 1 insertion(+), 23 deletions(-) diff --git a/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs b/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs index 0c9b5199bb3c..0e979733cd1f 100644 --- a/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs +++ b/dotnet/samples/Concepts/ChatCompletion/Ollama_ChatCompletionWithVision.cs @@ -23,7 +23,7 @@ public async Task GetLocalImageDescription() var imageBytes = await EmbeddedResource.ReadAllAsync("sample_image.jpg"); var kernel = Kernel.CreateBuilder() - .AddOllamaChatCompletion("llama3.2-vision") + .AddOllamaChatCompletion(modelId: "llama3.2-vision", endpoint: new Uri(TestConfiguration.Ollama.Endpoint)) .Build(); var chatCompletionService = kernel.GetRequiredService(); diff --git a/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaChatCompletionTests.cs b/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaChatCompletionTests.cs index 9ee6b52610e0..a1b2e4f64d1d 100644 --- a/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaChatCompletionTests.cs +++ b/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaChatCompletionTests.cs @@ -39,14 +39,6 @@ public OllamaChatCompletionTests() this._httpClient = new HttpClient(this._multiMessageHandlerStub, false) { BaseAddress = new Uri("http://localhost:11434") }; } - [Fact] - public void AddOllamaChatCompletionShouldWorkOnlyForModelId() - { - // Arrange - var kernel = Kernel.CreateBuilder().AddOllamaChatCompletion("model-id").Build(); - var service = kernel.GetRequiredService(); - } - [Fact] public async Task ShouldSendPromptToServiceAsync() { diff --git a/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs b/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs index ee73c9558165..085a9d2dcc6d 100644 --- a/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs +++ b/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs @@ -25,14 +25,6 @@ public OllamaTextEmbeddingGenerationTests() this._httpClient = new HttpClient(this._messageHandlerStub, false) { BaseAddress = new Uri("http://localhost:11434") }; } - [Fact] - public void AddOllamaTextEmbeddingGenerationShouldWorkOnlyForModelId() - { - // Arrange - var kernel = Kernel.CreateBuilder().AddOllamaTextEmbeddingGeneration("model-id").Build(); - var service = kernel.GetRequiredService(); - } - [Fact] public async Task ShouldSendPromptToServiceAsync() { diff --git a/dotnet/src/Connectors/Connectors.Ollama/Extensions/OllamaServiceCollectionExtensions.cs b/dotnet/src/Connectors/Connectors.Ollama/Extensions/OllamaServiceCollectionExtensions.cs index 84d63ff6506b..220737be2749 100644 --- a/dotnet/src/Connectors/Connectors.Ollama/Extensions/OllamaServiceCollectionExtensions.cs +++ b/dotnet/src/Connectors/Connectors.Ollama/Extensions/OllamaServiceCollectionExtensions.cs @@ -190,9 +190,6 @@ public static IServiceCollection AddOllamaChatCompletion( var loggerFactory = serviceProvider.GetService(); - // Set default base address if not already set - httpClient.BaseAddress ??= new Uri("http://localhost:11434"); - var builder = ((IChatClient)new OllamaApiClient(httpClient, modelId)) .AsBuilder() .UseFunctionInvocation(loggerFactory, config => config.MaximumIterationsPerRequest = MaxInflightAutoInvokes); @@ -302,9 +299,6 @@ public static IServiceCollection AddOllamaTextEmbeddingGeneration( { httpClient ??= HttpClientProvider.GetHttpClient(httpClient, serviceProvider); - // Set default base address if not already set - httpClient.BaseAddress ??= new Uri("http://localhost:11434"); - var loggerFactory = serviceProvider.GetService(); var builder = ((IEmbeddingGenerator>)new OllamaApiClient(httpClient, modelId)) From 3da76fb3d1aa02fedc5101b78d84b13ed890aa69 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Date: Mon, 24 Mar 2025 09:12:57 +0000 Subject: [PATCH 5/5] remove using --- .../Services/OllamaTextEmbeddingGenerationTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs b/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs index 085a9d2dcc6d..fde471a85679 100644 --- a/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs +++ b/dotnet/src/Connectors/Connectors.Ollama.UnitTests/Services/OllamaTextEmbeddingGenerationTests.cs @@ -5,7 +5,6 @@ using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; -using Microsoft.SemanticKernel; using Microsoft.SemanticKernel.Embeddings; using OllamaSharp; using OllamaSharp.Models;