@@ -30,11 +30,10 @@ internal static class AbstractionMapper
30
30
{
31
31
FinishReason = ToFinishReason ( stream . DoneReason ) ,
32
32
AdditionalProperties = ParseOllamaChatResponseProps ( stream ) ,
33
- Choices = [ chatMessage ] ,
34
33
CreatedAt = stream . CreatedAt ,
35
34
ModelId = usedModel ?? stream . Model ,
36
35
RawRepresentation = stream ,
37
- ResponseId = stream . CreatedAtString ,
36
+ ResponseId = stream . CreatedAtString ?? Guid . NewGuid ( ) . ToString ( "N" ) ,
38
37
Usage = ParseOllamaChatResponseUsage ( stream )
39
38
} ;
40
39
}
@@ -43,12 +42,12 @@ internal static class AbstractionMapper
43
42
/// Converts Microsoft.Extensions.AI <see cref="ChatMessage"/> objects and
44
43
/// an option <see cref="ChatOptions"/> instance to an OllamaSharp <see cref="ChatRequest"/>.
45
44
/// </summary>
46
- /// <param name="chatMessages ">A list of chat messages.</param>
45
+ /// <param name="messages ">A list of chat messages.</param>
47
46
/// <param name="options">Optional chat options to configure the request.</param>
48
47
/// <param name="stream">Indicates if the request should be streamed.</param>
49
48
/// <param name="serializerOptions">Serializer options</param>
50
49
/// <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 )
52
51
{
53
52
object ? format = null ;
54
53
@@ -59,7 +58,7 @@ public static ChatRequest ToOllamaSharpChatRequest(IList<ChatMessage> chatMessag
59
58
{
60
59
Format = format ,
61
60
KeepAlive = null ,
62
- Messages = ToOllamaSharpMessages ( chatMessages , serializerOptions ) ,
61
+ Messages = ToOllamaSharpMessages ( messages , serializerOptions ) ,
63
62
Model = options ? . ModelId ?? string . Empty , // will be set OllamaApiClient.SelectedModel if not set
64
63
Options = new RequestOptions
65
64
{
@@ -198,18 +197,18 @@ private static string ToFunctionTypeString(JsonObject? schema)
198
197
/// <summary>
199
198
/// Converts a list of Microsoft.Extensions.AI.<see cref="ChatMessage"/> to a list of Ollama <see cref="Message"/>.
200
199
/// </summary>
201
- /// <param name="chatMessages ">The chat messages to convert.</param>
200
+ /// <param name="messages ">The chat messages to convert.</param>
202
201
/// <param name="serializerOptions">Serializer options</param>
203
202
/// <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 )
205
204
{
206
- foreach ( var cm in chatMessages )
205
+ foreach ( var cm in messages )
207
206
{
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 ( ) ;
209
208
var toolCalls = cm . Contents . OfType < FunctionCallContent > ( ) . Select ( ToOllamaSharpToolCall ) . ToArray ( ) ;
210
209
211
210
// 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 )
213
212
{
214
213
yield return new Message
215
214
{
@@ -243,15 +242,9 @@ private static IEnumerable<Message> ToOllamaSharpMessages(IList<ChatMessage> cha
243
242
/// </summary>
244
243
/// <param name="content">The data content to convert.</param>
245
244
/// <returns>A string containing the base64 image data.</returns>
246
- private static string ToOllamaImage ( DataContent ? content )
245
+ private static string ToOllamaImage ( DataContent content )
247
246
{
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 ( ) ) ;
255
248
}
256
249
257
250
/// <summary>
@@ -312,20 +305,18 @@ private static Microsoft.Extensions.AI.ChatRole ToAbstractionRole(ChatRole? role
312
305
/// Converts a <see cref="ChatResponseStream"/> to a <see cref="ChatResponseUpdate"/>.
313
306
/// </summary>
314
307
/// <param name="response">The response stream to convert.</param>
308
+ /// <param name="responseId">The response ID to store onto the created update.</param>
315
309
/// <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 )
317
311
{
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 )
319
314
{
320
315
// no need to set "Contents" as we set the text
321
- ChoiceIndex = 0 , // should be left at 0 as Ollama does not support this
322
316
CreatedAt = response ? . CreatedAt ,
323
317
FinishReason = response ? . Done == true ? ChatFinishReason . Stop : null ,
324
318
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 ,
329
320
ModelId = response ? . Model
330
321
} ;
331
322
}
0 commit comments