diff --git a/src/Custom/Assistants/MessageCreationAttachment.cs b/src/Custom/Assistants/MessageCreationAttachment.cs index 521de9c11..d0de2c392 100644 --- a/src/Custom/Assistants/MessageCreationAttachment.cs +++ b/src/Custom/Assistants/MessageCreationAttachment.cs @@ -26,7 +26,47 @@ public partial class MessageCreationAttachment public IReadOnlyList Tools { get; } private void SerializeTools(Utf8JsonWriter writer, ModelReaderWriterOptions options) - => writer.WriteObjectValue(Tools, options); + { + if (Tools is null) + { + writer.WriteNullValue(); + return; + } + + writer.WriteStartArray(); + foreach (ToolDefinition tool in Tools) + { + using var ms = new System.IO.MemoryStream(); + using (var tempWriter = new Utf8JsonWriter(ms)) + { + tempWriter.WriteObjectValue(tool, options); + tempWriter.Flush(); + } + + using (JsonDocument doc = JsonDocument.Parse(ms.ToArray())) + { + JsonElement root = doc.RootElement; + if (root.ValueKind == JsonValueKind.Object) + { + writer.WriteStartObject(); + foreach (var prop in root.EnumerateObject()) + { + if (prop.NameEquals("file_search"u8)) + { + continue; + } + prop.WriteTo(writer); + } + writer.WriteEndObject(); + } + else + { + root.WriteTo(writer); + } + } + } + writer.WriteEndArray(); + } private static void DeserializeTools(JsonProperty property, ref IReadOnlyList tools) { diff --git a/tests/Assistants/AssistantsTests.cs b/tests/Assistants/AssistantsTests.cs index eee6fe503..e90a7b6aa 100644 --- a/tests/Assistants/AssistantsTests.cs +++ b/tests/Assistants/AssistantsTests.cs @@ -1,10 +1,3 @@ -using Microsoft.ClientModel.TestFramework; -using NUnit.Framework; -using NUnit.Framework.Internal; -using OpenAI.Assistants; -using OpenAI.Files; -using OpenAI.Tests.Utility; -using OpenAI.VectorStores; using System; using System.ClientModel; using System.ClientModel.Primitives; @@ -14,6 +7,19 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Microsoft.ClientModel.TestFramework; +using NUnit.Framework; +using NUnit.Framework; +using NUnit.Framework.Internal; +using NUnit.Framework.Internal; +using OpenAI.Assistants; +using OpenAI.Assistants; +using OpenAI.Files; +using OpenAI.Files; +using OpenAI.Tests.Utility; +using OpenAI.Tests.Utility; +using OpenAI.VectorStores; +using OpenAI.VectorStores; using static OpenAI.Tests.TestHelpers; namespace OpenAI.Tests.Assistants; @@ -30,7 +36,6 @@ public class AssistantsTests : OpenAIRecordedTestBase private readonly List _vectorStoreIdsToDelete = []; private static readonly DateTimeOffset s_2024 = new(2024, 1, 1, 0, 0, 0, TimeSpan.Zero); - private static readonly string s_testAssistantName = $".NET SDK Test Assistant - Please Delete Me"; private static readonly string s_cleanupMetadataKey = $"test_metadata_cleanup_eligible"; private AssistantClient GetTestClient() => GetProxiedOpenAIClient(TestScenario.Assistants); @@ -847,6 +852,45 @@ This file describes the favorite foods of several people. }); } + [Test] + public async Task FileOnMessageWorks() + { + // First, we need to upload a simple test file. + OpenAIFileClient fileClient = GetTestClient(TestScenario.Files); + OpenAIFile testFile = fileClient.UploadFile( + BinaryData.FromString(""" + This file describes the favorite foods of several people. + + Summanus Ferdinand: tacos + Tekakwitha Effie: pizza + Filip Carola: cake + """).ToStream(), + "favorite_foods.txt", + FileUploadPurpose.Assistants); + Validate(testFile); + + AssistantClient client = GetTestClient(); + + var thread = client.CreateThread(); + var assistant = client.CreateAssistant("gpt-4o-mini"); + + var message = await client.CreateMessageAsync( + thread.Value.Id, + MessageRole.User, + new[] { + MessageContent.FromText("What is this file?"), + }, + new MessageCreationOptions() + { + Attachments = [ + new MessageCreationAttachment(testFile.Id, new List() { ToolDefinition.CreateFileSearch() }), + new MessageCreationAttachment(testFile.Id, new List() { ToolDefinition.CreateCodeInterpreter() }) + ] + }); + + var result = client.CreateRunStreamingAsync(thread.Value.Id, assistant.Value.Id); + } + [Test] public async Task FileSearchStreamingWorks() {