Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ public static IEnumerable<ThreadInitializationMessage> ToThreadInitializationMes
public static ResponseItem ToResponseItem(this ChatMessageContent message)
{
var items = message.Items;
IEnumerable<ResponseContentPart> contentParts = items.Select(item => item.ToResponseContentPart());
return message.Role.Label.ToUpperInvariant() switch
var roleLabel = message.Role.Label.ToUpperInvariant();

IEnumerable<ResponseContentPart> contentParts = items.Select(item => item.ToResponseContentPart(roleLabel == "ASSISTANT"));
return roleLabel switch
{
"SYSTEM" => ResponseItem.CreateSystemMessageItem(contentParts),
"USER" => ResponseItem.CreateUserMessageItem(contentParts),
Expand Down
10 changes: 6 additions & 4 deletions dotnet/src/Agents/OpenAI/Extensions/KernelContentExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,23 @@ namespace Microsoft.SemanticKernel.Agents.OpenAI;
/// </summary>
internal static class KernelContentExtensions
{
internal static ResponseContentPart ToResponseContentPart(this KernelContent content)
internal static ResponseContentPart ToResponseContentPart(this KernelContent content, bool isOutput = false)
{
return content switch
{
TextContent textContent => textContent.ToResponseContentPart(),
TextContent textContent => textContent.ToResponseContentPart(isOutput),
ImageContent imageContent => imageContent.ToResponseContentPart(),
BinaryContent binaryContent => binaryContent.ToResponseContentPart(),
FileReferenceContent fileReferenceContent => fileReferenceContent.ToResponseContentPart(),
_ => throw new NotSupportedException($"Unsupported content type {content.GetType().Name}. Cannot convert to {nameof(ResponseContentPart)}.")
};
}

internal static ResponseContentPart ToResponseContentPart(this TextContent content)
internal static ResponseContentPart ToResponseContentPart(this TextContent content, bool isOutput)
{
return ResponseContentPart.CreateInputTextPart(content.Text);
return isOutput ?
ResponseContentPart.CreateOutputTextPart(content.Text, []) :
ResponseContentPart.CreateInputTextPart(content.Text);
}

internal static ResponseContentPart ToResponseContentPart(this ImageContent content)
Expand Down
45 changes: 45 additions & 0 deletions dotnet/src/IntegrationTests/Agents/OpenAIResponseAgentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,51 @@ public async Task OpenAIResponseAgentInvokeStreamingWithThreadAsync(bool isOpenA
Assert.Contains("Computer says no", responseText);
}


/// <summary>
/// Integration test for <see cref="OpenAIResponseAgent"/> with existing chat history.
/// </summary>
[RetryTheory(typeof(HttpOperationException))]
[InlineData(false, false)]
[InlineData(false, true)]
[InlineData(true, false)]
[InlineData(true, true)]
public async Task OpenAIResponseAgentInvokeStreamingWithChatHistoryAsync(bool isOpenAI, bool storeEnabled)
{
// Arrange
OpenAIResponseClient client = this.CreateClient(isOpenAI);
OpenAIResponseAgent agent = new(client)
{
StoreEnabled = storeEnabled,
Instructions = "Answer all queries in English and French."
};

var chatHistory = new ChatHistory();
chatHistory.AddUserMessage("Hello my name is John");
chatHistory.AddAssistantMessage("Hello John, how can I help you today?");
chatHistory.AddUserMessage("What is my Name?");

AgentThread agentThread = storeEnabled ? new OpenAIResponseAgentThread(client) : new ChatHistoryAgentThread();

// Act
string? responseText = null;
try
{
var responseMessages = await agent.InvokeStreamingAsync(chatHistory, agentThread).ToArrayAsync();
responseText = string.Join(string.Empty, responseMessages.Select(ri => ri.Message.Content));
}
finally
{
if (agentThread.Id is not null)
{
await agentThread.DeleteAsync();
}
}

// Assert
Assert.NotNull(responseText);
}

/// <summary>
/// Integration test for <see cref="OpenAIResponseAgent"/> adding override instructions to a thread on invocation via custom options.
/// </summary>
Expand Down