Skip to content

Commit ed31cea

Browse files
authored
Merge pull request #200 from stephentoub/updatemeai
Update to M.E.AI 9.3.0-preview.1.25161.3
2 parents 64c27b5 + 0f08ca4 commit ed31cea

File tree

6 files changed

+62
-92
lines changed

6 files changed

+62
-92
lines changed

src/OllamaSharp/MicrosoftAi/AbstractionMapper.cs

+16-25
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,10 @@ internal static class AbstractionMapper
3030
{
3131
FinishReason = ToFinishReason(stream.DoneReason),
3232
AdditionalProperties = ParseOllamaChatResponseProps(stream),
33-
Choices = [chatMessage],
3433
CreatedAt = stream.CreatedAt,
3534
ModelId = usedModel ?? stream.Model,
3635
RawRepresentation = stream,
37-
ResponseId = stream.CreatedAtString,
36+
ResponseId = stream.CreatedAtString ?? Guid.NewGuid().ToString("N"),
3837
Usage = ParseOllamaChatResponseUsage(stream)
3938
};
4039
}
@@ -43,12 +42,12 @@ internal static class AbstractionMapper
4342
/// Converts Microsoft.Extensions.AI <see cref="ChatMessage"/> objects and
4443
/// an option <see cref="ChatOptions"/> instance to an OllamaSharp <see cref="ChatRequest"/>.
4544
/// </summary>
46-
/// <param name="chatMessages">A list of chat messages.</param>
45+
/// <param name="messages">A list of chat messages.</param>
4746
/// <param name="options">Optional chat options to configure the request.</param>
4847
/// <param name="stream">Indicates if the request should be streamed.</param>
4948
/// <param name="serializerOptions">Serializer options</param>
5049
/// <returns>A <see cref="ChatRequest"/> object containing the converted data.</returns>
51-
public static ChatRequest ToOllamaSharpChatRequest(IList<ChatMessage> chatMessages, ChatOptions? options, bool stream, JsonSerializerOptions serializerOptions)
50+
public static ChatRequest ToOllamaSharpChatRequest(IEnumerable<ChatMessage> messages, ChatOptions? options, bool stream, JsonSerializerOptions serializerOptions)
5251
{
5352
object? format = null;
5453

@@ -59,7 +58,7 @@ public static ChatRequest ToOllamaSharpChatRequest(IList<ChatMessage> chatMessag
5958
{
6059
Format = format,
6160
KeepAlive = null,
62-
Messages = ToOllamaSharpMessages(chatMessages, serializerOptions),
61+
Messages = ToOllamaSharpMessages(messages, serializerOptions),
6362
Model = options?.ModelId ?? string.Empty, // will be set OllamaApiClient.SelectedModel if not set
6463
Options = new RequestOptions
6564
{
@@ -198,18 +197,18 @@ private static string ToFunctionTypeString(JsonObject? schema)
198197
/// <summary>
199198
/// Converts a list of Microsoft.Extensions.AI.<see cref="ChatMessage"/> to a list of Ollama <see cref="Message"/>.
200199
/// </summary>
201-
/// <param name="chatMessages">The chat messages to convert.</param>
200+
/// <param name="messages">The chat messages to convert.</param>
202201
/// <param name="serializerOptions">Serializer options</param>
203202
/// <returns>An enumeration of <see cref="Message"/> objects containing the converted data.</returns>
204-
private static IEnumerable<Message> ToOllamaSharpMessages(IList<ChatMessage> chatMessages, JsonSerializerOptions serializerOptions)
203+
private static IEnumerable<Message> ToOllamaSharpMessages(IEnumerable<ChatMessage> messages, JsonSerializerOptions serializerOptions)
205204
{
206-
foreach (var cm in chatMessages)
205+
foreach (var cm in messages)
207206
{
208-
var images = cm.Contents.OfType<DataContent>().Where(dc => dc.MediaType is null || dc.MediaTypeStartsWith("image/")).Select(ToOllamaImage).Where(s => !string.IsNullOrEmpty(s)).ToArray();
207+
var images = cm.Contents.OfType<DataContent>().Where(dc => dc.HasTopLevelMediaType("image")).Select(ToOllamaImage).ToArray();
209208
var toolCalls = cm.Contents.OfType<FunctionCallContent>().Select(ToOllamaSharpToolCall).ToArray();
210209

211210
// Only generates a message if there is text/content, images or tool calls
212-
if (cm.Text is not null || images.Length > 0 || toolCalls.Length > 0)
211+
if (cm.Text is { Length: > 0 } || images.Length > 0 || toolCalls.Length > 0)
213212
{
214213
yield return new Message
215214
{
@@ -243,15 +242,9 @@ private static IEnumerable<Message> ToOllamaSharpMessages(IList<ChatMessage> cha
243242
/// </summary>
244243
/// <param name="content">The data content to convert.</param>
245244
/// <returns>A string containing the base64 image data.</returns>
246-
private static string ToOllamaImage(DataContent? content)
245+
private static string ToOllamaImage(DataContent content)
247246
{
248-
if (content is null)
249-
return string.Empty;
250-
251-
if (content.Data.HasValue)
252-
return Convert.ToBase64String(content.Data.Value.ToArray());
253-
254-
throw new NotSupportedException("Images have to be provided as content (byte-Array or base64-string) for Ollama to be used. Other image sources like links are not supported.");
247+
return Convert.ToBase64String(content.Data.ToArray());
255248
}
256249

257250
/// <summary>
@@ -312,20 +305,18 @@ private static Microsoft.Extensions.AI.ChatRole ToAbstractionRole(ChatRole? role
312305
/// Converts a <see cref="ChatResponseStream"/> to a <see cref="ChatResponseUpdate"/>.
313306
/// </summary>
314307
/// <param name="response">The response stream to convert.</param>
308+
/// <param name="responseId">The response ID to store onto the created update.</param>
315309
/// <returns>A <see cref="ChatResponseUpdate"/> object containing the latest chat completion chunk.</returns>
316-
public static ChatResponseUpdate ToChatResponseUpdate(ChatResponseStream? response)
310+
public static ChatResponseUpdate ToChatResponseUpdate(ChatResponseStream? response, string responseId)
317311
{
318-
return new ChatResponseUpdate
312+
// TODO: Check if "Message" can ever actually be null. If not, remove the null-coalescing operator
313+
return new(ToAbstractionRole(response?.Message?.Role), response?.Message?.Content ?? string.Empty)
319314
{
320315
// no need to set "Contents" as we set the text
321-
ChoiceIndex = 0, // should be left at 0 as Ollama does not support this
322316
CreatedAt = response?.CreatedAt,
323317
FinishReason = response?.Done == true ? ChatFinishReason.Stop : null,
324318
RawRepresentation = response,
325-
ResponseId = response?.CreatedAtString,
326-
// TODO: Check if "Message" can ever actually be null. If not, remove the null-coalescing operator
327-
Text = response?.Message?.Content ?? string.Empty,
328-
Role = ToAbstractionRole(response?.Message?.Role),
319+
ResponseId = responseId,
329320
ModelId = response?.Model
330321
};
331322
}

src/OllamaSharp/MicrosoftAi/ChatResponseUpdateBuilder.cs

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
using System.Text;
21
using Microsoft.Extensions.AI;
32

43
namespace OllamaSharp.MicrosoftAi;
@@ -8,7 +7,6 @@ namespace OllamaSharp.MicrosoftAi;
87
/// </summary>
98
internal class ChatResponseUpdateBuilder
109
{
11-
private readonly StringBuilder _contentBuilder = new();
1210
private ChatResponseUpdate? _first;
1311

1412
/// <summary>
@@ -20,19 +18,16 @@ public void Append(ChatResponseUpdate? update)
2018
if (update is null)
2119
return;
2220

23-
_contentBuilder.Append(update.Text ?? "");
24-
2521
_first ??= update;
2622

2723
_first.AdditionalProperties = update.AdditionalProperties;
2824
_first.AuthorName = update.AuthorName;
29-
_first.ChoiceIndex = update.ChoiceIndex;
3025
_first.CreatedAt = update.CreatedAt;
3126
_first.FinishReason = update.FinishReason;
3227
_first.ResponseId = update.ResponseId;
3328
_first.Role = update.Role;
3429

35-
//_first.Contents and .Text will be set in Complete() with values collected from each update
30+
//_first.Contents will be set in Complete() with values collected from each update
3631
//_first.RawRepresentation makes no sense
3732

3833
// TODO: Check if this can ever be null. The docs imply not.
@@ -50,7 +45,6 @@ public void Append(ChatResponseUpdate? update)
5045
if (_first is null)
5146
return null;
5247

53-
_first.Text = _contentBuilder.ToString();
5448
_first.Contents = Contents;
5549

5650
return _first;

src/OllamaSharp/OllamaApiClient.cs

+8-6
Original file line numberDiff line numberDiff line change
@@ -399,19 +399,21 @@ private async Task EnsureSuccessStatusCodeAsync(HttpResponseMessage response)
399399
private EmbeddingGeneratorMetadata? _embeddingGeneratorMetadata;
400400

401401
/// <inheritdoc/>
402-
async Task<ChatResponse> IChatClient.GetResponseAsync(IList<ChatMessage> chatMessages, ChatOptions? options, CancellationToken cancellationToken)
402+
async Task<ChatResponse> IChatClient.GetResponseAsync(IEnumerable<ChatMessage> messages, ChatOptions? options, CancellationToken cancellationToken)
403403
{
404-
var request = AbstractionMapper.ToOllamaSharpChatRequest(chatMessages, options, stream: false, OutgoingJsonSerializerOptions);
404+
var request = AbstractionMapper.ToOllamaSharpChatRequest(messages, options, stream: false, OutgoingJsonSerializerOptions);
405405
var response = await ChatAsync(request, cancellationToken).StreamToEndAsync().ConfigureAwait(false);
406406
return AbstractionMapper.ToChatResponse(response, response?.Model ?? request.Model ?? SelectedModel) ?? new ChatResponse([]);
407407
}
408408

409409
/// <inheritdoc/>
410-
async IAsyncEnumerable<ChatResponseUpdate> IChatClient.GetStreamingResponseAsync(IList<ChatMessage> chatMessages, ChatOptions? options, [EnumeratorCancellation] CancellationToken cancellationToken)
410+
async IAsyncEnumerable<ChatResponseUpdate> IChatClient.GetStreamingResponseAsync(IEnumerable<ChatMessage> messages, ChatOptions? options, [EnumeratorCancellation] CancellationToken cancellationToken)
411411
{
412-
var request = AbstractionMapper.ToOllamaSharpChatRequest(chatMessages, options, stream: true, OutgoingJsonSerializerOptions);
412+
var request = AbstractionMapper.ToOllamaSharpChatRequest(messages, options, stream: true, OutgoingJsonSerializerOptions);
413+
414+
string responseId = Guid.NewGuid().ToString("N");
413415
await foreach (var response in ChatAsync(request, cancellationToken).ConfigureAwait(false))
414-
yield return AbstractionMapper.ToChatResponseUpdate(response);
416+
yield return AbstractionMapper.ToChatResponseUpdate(response, responseId);
415417
}
416418

417419
/// <inheritdoc/>
@@ -430,7 +432,7 @@ async Task<GeneratedEmbeddings<Embedding<float>>> IEmbeddingGenerator<string, Em
430432
null;
431433

432434
/// <inheritdoc />
433-
object? IEmbeddingGenerator<string, Embedding<float>>.GetService(Type serviceKey, object? key) =>
435+
object? IEmbeddingGenerator.GetService(Type serviceKey, object? key) =>
434436
key is not null ? null :
435437
serviceKey == typeof(EmbeddingGeneratorMetadata) ? (_embeddingGeneratorMetadata = new(Application.Ollama, Uri, SelectedModel)) :
436438
serviceKey?.IsInstanceOfType(this) is true ? this :

src/OllamaSharp/OllamaSharp.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343

4444
<ItemGroup>
4545
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.0" />
46-
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="9.3.0-preview.1.25114.11" />
46+
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="9.3.0-preview.1.25161.3" />
4747
</ItemGroup>
4848

4949
<ItemGroup>

0 commit comments

Comments
 (0)