using AIStudio.Assistants.BeyondFactsLab; using AIStudio.Chat; namespace AIStudio.Tests.BeyondFactsLab; /// /// Checks how the images of the material go along with a request of the BeyondFacts Lab. /// /// /// The images belong to the request only: the stored chat must never hold a path to them, the answer streams into /// the chat while the request runs, and the tokens a provider reports belong to a chat with as many messages. /// [TestFixture] public sealed class BflRequestImageTests { [Test] public void TheImagesGoAlongWithTheFirstMessage() { var thread = Conversation(); var image = new FileAttachmentImage("Poster.png", "/data/beyondFactsLab/p/materials/m.png", 1_024); var request = BflConversationService.WithImages(thread, [image]); var firstMessage = (ContentText)request.Blocks[0].Content!; using (Assert.EnterMultipleScope()) { Assert.That(firstMessage.FileAttachments, Is.EqualTo(new FileAttachment[] { image })); Assert.That(firstMessage.Text, Is.EqualTo("Eröffnung")); Assert.That(request.Blocks[0].HideFromUser, Is.True, "The opening request stays hidden."); Assert.That(request.ChatId, Is.EqualTo(thread.ChatId)); } } [Test] public void TheStoredChatHoldsNoImage() { var thread = Conversation(); BflConversationService.WithImages(thread, [new FileAttachmentImage("Poster.png", "/data/m.png", 1_024)]); Assert.That(thread.Blocks.Select(block => (block.Content as ContentText)?.FileAttachments.Count ?? 0), Is.All.Zero); } [Test] public void EveryOtherMessageStaysTheSame() { var thread = Conversation(); var request = BflConversationService.WithImages(thread, [new FileAttachmentImage("Poster.png", "/data/m.png", 1_024)]); using (Assert.EnterMultipleScope()) { Assert.That(request.Blocks, Has.Count.EqualTo(thread.Blocks.Count), "The tokens a provider reports would no longer belong to the chat."); Assert.That(request.Blocks[0], Is.Not.SameAs(thread.Blocks[0])); for (var index = 1; index < thread.Blocks.Count; index++) Assert.That(request.Blocks[index], Is.SameAs(thread.Blocks[index]), "The answer must stream into the chat itself."); } } [Test] public void WithoutImagesTheRequestIsTheChat() { var thread = Conversation(); Assert.That(BflConversationService.WithImages(thread, []), Is.SameAs(thread)); } /// /// A conversation of a step: the hidden opening request, an answer, a message of the person, and the answer which /// streams in. /// private static ChatThread Conversation() => new() { ChatId = Guid.NewGuid(), Blocks = [ new() { Role = ChatRole.USER, ContentType = ContentType.TEXT, Content = new ContentText { Text = "Eröffnung" }, HideFromUser = true }, new() { Role = ChatRole.AI, ContentType = ContentType.TEXT, Content = new ContentText { Text = "Worum geht es?" } }, new() { Role = ChatRole.USER, ContentType = ContentType.TEXT, Content = new ContentText { Text = "Ein Podium." } }, new() { Role = ChatRole.AI, ContentType = ContentType.TEXT, Content = new ContentText { InitialRemoteWait = true } }, ], }; }