Skip to content

Commit 678e067

Browse files
authored
Merge pull request #208 from awaescher/feature/add-test-for-tools-streaming
Add a test for the tool calls when streaming
2 parents d3641c5 + 21d8181 commit 678e067

File tree

2 files changed

+119
-63
lines changed

2 files changed

+119
-63
lines changed

src/OllamaSharp/MicrosoftAi/AbstractionMapper.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,7 @@ private static Microsoft.Extensions.AI.ChatRole ToAbstractionRole(ChatRole? role
309309
/// <returns>A <see cref="ChatResponseUpdate"/> object containing the latest chat completion chunk.</returns>
310310
public static ChatResponseUpdate ToChatResponseUpdate(ChatResponseStream? response, string responseId)
311311
{
312-
// TODO: Check if "Message" can ever actually be null.
313-
List<AIContent> contents = response?.Message is null ?
314-
[new TextContent(string.Empty)] : GetAIContentsFromMessage(response.Message);
312+
var contents = response?.Message is null ? [new TextContent(string.Empty)] : GetAIContentsFromMessage(response.Message);
315313

316314
return new ChatResponseUpdate(ToAbstractionRole(response?.Message.Role), contents)
317315
{
@@ -338,6 +336,9 @@ private static List<AIContent> GetAIContentsFromMessage(Message message)
338336
{
339337
var contents = new List<AIContent>();
340338

339+
if (message is null)
340+
return contents;
341+
341342
if (message.ToolCalls?.Any() ?? false)
342343
{
343344
foreach (var toolCall in message.ToolCalls)

test/AbstractionMapperTests.cs

+115-60
Original file line numberDiff line numberDiff line change
@@ -737,13 +737,12 @@ public void Maps_Known_Properties()
737737
streamingChatCompletion.Role.ShouldBe(Microsoft.Extensions.AI.ChatRole.Assistant);
738738
streamingChatCompletion.Text.ShouldBe("Hi.");
739739
}
740-
}
741740

742-
public class ToChatMessageMethod : AbstractionMapperTests
743-
{
744741
[Test]
745742
public void Maps_ToolCalls()
746743
{
744+
var ollamaCreated = new DateTimeOffset(2023, 08, 04, 08, 52, 19, 385, 406, TimeSpan.FromHours(-7));
745+
747746
var message = new Message
748747
{
749748
Role = OllamaSharp.Models.Chat.ChatRole.Assistant,
@@ -765,7 +764,15 @@ public void Maps_ToolCalls()
765764
]
766765
};
767766

768-
var chatMessage = AbstractionMapper.ToChatMessage(message);
767+
var stream = new ChatResponseStream
768+
{
769+
CreatedAt = ollamaCreated,
770+
Done = true,
771+
Message = message,
772+
Model = "llama3.1:8b"
773+
};
774+
775+
var chatMessage = AbstractionMapper.ToChatResponseUpdate(stream, "12345");
769776

770777
chatMessage.AdditionalProperties.ShouldBeNull();
771778
chatMessage.AuthorName.ShouldBeNull();
@@ -781,81 +788,129 @@ public void Maps_ToolCalls()
781788
toolCall.Exception.ShouldBeNull();
782789
toolCall.Name.ShouldBe("get_weather");
783790
toolCall.RawRepresentation.ShouldBe(message.ToolCalls.Single());
784-
chatMessage.RawRepresentation.ShouldBe(message);
791+
chatMessage.RawRepresentation.ShouldBe(stream);
785792
chatMessage.Role.ShouldBe(Microsoft.Extensions.AI.ChatRole.Assistant);
786793
chatMessage.Text.ShouldBe("It seems the sun will be out all day.");
787794
}
788795
}
796+
}
789797

790-
public class ToOllamaEmbedRequestMethod : AbstractionMapperTests
798+
public class ToChatMessageMethod : AbstractionMapperTests
799+
{
800+
[Test]
801+
public void Maps_ToolCalls()
791802
{
792-
[Test]
793-
public void Maps_Request()
803+
var message = new Message
794804
{
795-
var values = new string[] { "Teenage ", " Dirtbag." };
805+
Role = OllamaSharp.Models.Chat.ChatRole.Assistant,
806+
Content = "It seems the sun will be out all day.",
807+
ToolCalls =
808+
[
809+
new Message.ToolCall
810+
{
811+
Function = new Message.Function
812+
{
813+
Arguments = new Dictionary<string, object?>
814+
{
815+
["city"] = "Honululu",
816+
["unit"] = "celsius"
817+
},
818+
Name = "get_weather"
819+
}
820+
}
821+
]
822+
};
823+
824+
var chatMessage = AbstractionMapper.ToChatMessage(message);
825+
826+
chatMessage.AdditionalProperties.ShouldBeNull();
827+
chatMessage.AuthorName.ShouldBeNull();
828+
chatMessage.Contents.Count.ShouldBe(2);
829+
chatMessage.Contents.First().ShouldBeOfType<TextContent>();
830+
((TextContent)chatMessage.Contents.First()).Text.ShouldBe("It seems the sun will be out all day.");
831+
var toolCall = chatMessage.Contents.Last() as FunctionCallContent;
832+
toolCall.AdditionalProperties.ShouldBeNull();
833+
toolCall.Arguments.Count.ShouldBe(2);
834+
toolCall.Arguments["city"].ShouldBe("Honululu");
835+
toolCall.Arguments["unit"].ShouldBe("celsius");
836+
toolCall.CallId.Length.ShouldBe(8); // random guid
837+
toolCall.Exception.ShouldBeNull();
838+
toolCall.Name.ShouldBe("get_weather");
839+
toolCall.RawRepresentation.ShouldBe(message.ToolCalls.Single());
840+
chatMessage.RawRepresentation.ShouldBe(message);
841+
chatMessage.Role.ShouldBe(Microsoft.Extensions.AI.ChatRole.Assistant);
842+
chatMessage.Text.ShouldBe("It seems the sun will be out all day.");
843+
}
844+
}
796845

797-
var options = new EmbeddingGenerationOptions
798-
{
799-
Dimensions = 8,
800-
ModelId = "nomic_embed"
801-
};
846+
public class ToOllamaEmbedRequestMethod : AbstractionMapperTests
847+
{
848+
[Test]
849+
public void Maps_Request()
850+
{
851+
var values = new string[] { "Teenage ", " Dirtbag." };
802852

803-
var request = AbstractionMapper.ToOllamaEmbedRequest(values, options);
853+
var options = new EmbeddingGenerationOptions
854+
{
855+
Dimensions = 8,
856+
ModelId = "nomic_embed"
857+
};
804858

805-
request.Input.ShouldBe(["Teenage ", " Dirtbag."], ignoreOrder: true);
806-
request.KeepAlive.ShouldBeNull();
807-
request.Model.ShouldBe("nomic_embed");
808-
request.Options.ShouldBeNull();
809-
request.Truncate.ShouldBeNull();
810-
}
859+
var request = AbstractionMapper.ToOllamaEmbedRequest(values, options);
811860

812-
[Test]
813-
public void Maps_KeepAlive_And_Truncate_From_AdditionalProperties()
861+
request.Input.ShouldBe(["Teenage ", " Dirtbag."], ignoreOrder: true);
862+
request.KeepAlive.ShouldBeNull();
863+
request.Model.ShouldBe("nomic_embed");
864+
request.Options.ShouldBeNull();
865+
request.Truncate.ShouldBeNull();
866+
}
867+
868+
[Test]
869+
public void Maps_KeepAlive_And_Truncate_From_AdditionalProperties()
870+
{
871+
var options = new EmbeddingGenerationOptions
814872
{
815-
var options = new EmbeddingGenerationOptions
816-
{
817-
AdditionalProperties = []
818-
};
819-
options.AdditionalProperties["keep_alive"] = 123456789;
820-
options.AdditionalProperties["truncate"] = true;
873+
AdditionalProperties = []
874+
};
875+
options.AdditionalProperties["keep_alive"] = 123456789;
876+
options.AdditionalProperties["truncate"] = true;
821877

822-
var request = AbstractionMapper.ToOllamaEmbedRequest([], options);
878+
var request = AbstractionMapper.ToOllamaEmbedRequest([], options);
823879

824-
request.KeepAlive.ShouldBe(123456789);
825-
request.Truncate.ShouldBe(true);
826-
}
880+
request.KeepAlive.ShouldBe(123456789);
881+
request.Truncate.ShouldBe(true);
827882
}
883+
}
828884

829-
public class ToGeneratedEmbeddingsMethod : AbstractionMapperTests
885+
public class ToGeneratedEmbeddingsMethod : AbstractionMapperTests
886+
{
887+
[Test]
888+
public void Maps_Response()
830889
{
831-
[Test]
832-
public void Maps_Response()
890+
var request = new EmbedRequest();
891+
var response = new EmbedResponse
833892
{
834-
var request = new EmbedRequest();
835-
var response = new EmbedResponse
836-
{
837-
Embeddings =
838-
[
839-
[0.101f, 0.102f, 0.103f],
893+
Embeddings =
894+
[
895+
[0.101f, 0.102f, 0.103f],
840896
[0.201f, 0.202f, 0.203f]
841-
],
842-
LoadDuration = 1_100_000,
843-
PromptEvalCount = 18,
844-
TotalDuration = 3_200_000
845-
};
846-
847-
var mappedResponse = AbstractionMapper.ToGeneratedEmbeddings(request, response, usedModel: "model");
848-
849-
mappedResponse.AdditionalProperties.ShouldNotBeNull();
850-
mappedResponse.Count.ShouldBe(2);
851-
mappedResponse[0].ModelId.ShouldBe("model");
852-
mappedResponse[0].Vector.ToArray().ShouldBe([0.101f, 0.102f, 0.103f], ignoreOrder: true);
853-
mappedResponse[1].ModelId.ShouldBe("model");
854-
mappedResponse[1].Vector.ToArray().ShouldBe([0.201f, 0.202f, 0.203f], ignoreOrder: true);
855-
mappedResponse.Usage.InputTokenCount.ShouldBe(18);
856-
mappedResponse.Usage.OutputTokenCount.ShouldBeNull();
857-
mappedResponse.Usage.TotalTokenCount.ShouldBe(18);
858-
}
897+
],
898+
LoadDuration = 1_100_000,
899+
PromptEvalCount = 18,
900+
TotalDuration = 3_200_000
901+
};
902+
903+
var mappedResponse = AbstractionMapper.ToGeneratedEmbeddings(request, response, usedModel: "model");
904+
905+
mappedResponse.AdditionalProperties.ShouldNotBeNull();
906+
mappedResponse.Count.ShouldBe(2);
907+
mappedResponse[0].ModelId.ShouldBe("model");
908+
mappedResponse[0].Vector.ToArray().ShouldBe([0.101f, 0.102f, 0.103f], ignoreOrder: true);
909+
mappedResponse[1].ModelId.ShouldBe("model");
910+
mappedResponse[1].Vector.ToArray().ShouldBe([0.201f, 0.202f, 0.203f], ignoreOrder: true);
911+
mappedResponse.Usage.InputTokenCount.ShouldBe(18);
912+
mappedResponse.Usage.OutputTokenCount.ShouldBeNull();
913+
mappedResponse.Usage.TotalTokenCount.ShouldBe(18);
859914
}
860915
}
861916

0 commit comments

Comments
 (0)