Skip to content

Commit e001e97

Browse files
.Net: Ignore unknown response item types rather than throw (#12596)
### Motivation and Context Closes #12511 ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [ ] The code builds clean without any errors or warnings - [ ] The PR follows the [SK Contribution Guidelines](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) and the [pre-submission formatting script](https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md#development-scripts) raises no violations - [ ] All unit tests pass, and I have added new tests where possible - [ ] I didn't break anyone 😄
1 parent c8b4e1b commit e001e97

File tree

6 files changed

+60
-9
lines changed

6 files changed

+60
-9
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
using Microsoft.SemanticKernel;
3+
using Microsoft.SemanticKernel.Agents.OpenAI;
4+
5+
namespace GettingStarted.OpenAIResponseAgents;
6+
7+
/// <summary>
8+
/// This example demonstrates using <see cref="OpenAIResponseAgent"/>.
9+
/// </summary>
10+
public class Step03_OpenAIResponseAgent_ReasoningModel(ITestOutputHelper output) : BaseResponsesAgentTest(output, "o4-mini")
11+
{
12+
[Fact]
13+
public async Task UseOpenAIResponseAgentWithAReasoningModelAsync()
14+
{
15+
// Define the agent
16+
OpenAIResponseAgent agent = new(this.Client)
17+
{
18+
Name = "ResponseAgent",
19+
Instructions = "Answer all queries with a detailed response.",
20+
};
21+
22+
// Invoke the agent and output the response
23+
var responseItems = agent.InvokeAsync("Which of the last four Olympic host cities has the highest average temperature?");
24+
await foreach (ChatMessageContent responseItem in responseItems)
25+
{
26+
WriteAgentChatMessage(responseItem);
27+
}
28+
}
29+
}

dotnet/src/Agents/OpenAI/Extensions/OpenAIResponseExtensions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public static ChatMessageContent ToChatMessageContent(this OpenAIResponse respon
4343
/// </summary>
4444
/// <param name="item">The response item to convert.</param>
4545
/// <returns>A <see cref="ChatMessageContent"/> instance.</returns>
46-
public static ChatMessageContent ToChatMessageContent(this ResponseItem item)
46+
public static ChatMessageContent? ToChatMessageContent(this ResponseItem item)
4747
{
4848
if (item is MessageResponseItem messageResponseItem)
4949
{
@@ -54,7 +54,7 @@ public static ChatMessageContent ToChatMessageContent(this ResponseItem item)
5454
{
5555
return new ChatMessageContent(AuthorRole.Assistant, item.ToChatMessageContentItemCollection(), innerContent: functionCallResponseItem);
5656
}
57-
throw new NotSupportedException($"Unsupported response item: {item.GetType()}");
57+
return null;
5858
}
5959

6060
/// <summary>
@@ -92,7 +92,7 @@ public static ChatMessageContentItemCollection ToChatMessageContentItemCollectio
9292
};
9393
return [functionCallContent];
9494
}
95-
throw new NotImplementedException($"Unsupported response item: {item.GetType()}");
95+
return [];
9696
}
9797

9898
/// <summary>

dotnet/src/Agents/OpenAI/OpenAIResponseAgentThread.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,11 @@ public async IAsyncEnumerable<ChatMessageContent> GetMessagesAsync([EnumeratorCa
111111
var collectionResult = this._client.GetResponseInputItemsAsync(this.ResponseId, default, cancellationToken).ConfigureAwait(false);
112112
await foreach (var responseItem in collectionResult)
113113
{
114-
yield return responseItem.ToChatMessageContent();
114+
var messageContent = responseItem.ToChatMessageContent();
115+
if (messageContent is not null)
116+
{
117+
yield return messageContent;
118+
}
115119
}
116120
}
117121
}

dotnet/src/Agents/UnitTests/Extensions/ResponseItemExtensionsTests.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public void VerifyToChatMessageContentFromInputText(string creationMethod, strin
3535
// Act
3636
var messageContent = responseItem.ToChatMessageContent();
3737

38-
// Assert
38+
// Assert
39+
Assert.NotNull(messageContent);
3940
Assert.Equal(new AuthorRole(roleLabel), messageContent.Role);
4041
Assert.Single(messageContent.Items);
4142
Assert.IsType<TextContent>(messageContent.Items[0]);
@@ -53,6 +54,7 @@ public void VerifyToChatMessageContentFromInputImage()
5354
var messageContent = responseItem.ToChatMessageContent();
5455

5556
// Assert
57+
Assert.NotNull(messageContent);
5658
Assert.Equal(AuthorRole.User, messageContent.Role);
5759
Assert.Single(messageContent.Items);
5860
Assert.IsType<FileReferenceContent>(messageContent.Items[0]);
@@ -71,6 +73,7 @@ public void VerifyToChatMessageContentFromInputFile()
7173
var messageContent = responseItem.ToChatMessageContent();
7274

7375
// Assert
76+
Assert.NotNull(messageContent);
7477
Assert.Equal(AuthorRole.User, messageContent.Role);
7578
Assert.Single(messageContent.Items);
7679
Assert.IsType<BinaryContent>(messageContent.Items[0]);
@@ -88,9 +91,24 @@ public void VerifyToChatMessageContentFromRefusal()
8891
var messageContent = responseItem.ToChatMessageContent();
8992

9093
// Assert
94+
Assert.NotNull(messageContent);
9195
Assert.Equal(AuthorRole.User, messageContent.Role);
9296
Assert.Single(messageContent.Items);
9397
Assert.IsType<TextContent>(messageContent.Items[0]);
9498
Assert.Equal("refusal", ((TextContent)messageContent.Items[0]).Text);
9599
}
100+
101+
[Fact]
102+
public void VerifyToChatMessageContentFromReasoning()
103+
{
104+
// Arrange
105+
IEnumerable<string> summaryParts = ["Foo"];
106+
ReasoningResponseItem responseItem = ResponseItem.CreateReasoningItem(summaryParts);
107+
108+
// Act
109+
var messageContent = responseItem.ToChatMessageContent();
110+
111+
// Assert
112+
Assert.Null(messageContent);
113+
}
96114
}

dotnet/src/Agents/UnitTests/OpenAI/Extensions/OpenAIResponseExtensionsTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public void VerifyToChatMessageContentWithResponseItem()
5050
ResponseItem functionCall = ResponseItem.CreateFunctionCallItem("callId", "functionName", new BinaryData("{}"));
5151

5252
// Act
53-
ChatMessageContent userMessageContent = userMessage.ToChatMessageContent();
54-
ChatMessageContent functionCallContent = functionCall.ToChatMessageContent();
53+
ChatMessageContent? userMessageContent = userMessage.ToChatMessageContent();
54+
ChatMessageContent? functionCallContent = functionCall.ToChatMessageContent();
5555

5656
// Assert
5757
Assert.NotNull(userMessageContent);

dotnet/src/InternalUtilities/samples/AgentUtilities/BaseResponsesAgentTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
/// </summary>
1212
public abstract class BaseResponsesAgentTest : BaseAgentsTest<OpenAIResponseClient>
1313
{
14-
protected BaseResponsesAgentTest(ITestOutputHelper output) : base(output)
14+
protected BaseResponsesAgentTest(ITestOutputHelper output, string? model = null) : base(output)
1515
{
1616
var options = new OpenAIClientOptions();
1717
if (this.EnableLogging)
@@ -25,7 +25,7 @@ protected BaseResponsesAgentTest(ITestOutputHelper output) : base(output)
2525
});
2626
}
2727

28-
this.Client = new(model: TestConfiguration.OpenAI.ModelId, credential: new ApiKeyCredential(TestConfiguration.OpenAI.ApiKey), options: options);
28+
this.Client = new(model: model ?? TestConfiguration.OpenAI.ModelId, credential: new ApiKeyCredential(TestConfiguration.OpenAI.ApiKey), options: options);
2929
}
3030

3131
protected bool EnableLogging { get; set; } = false;

0 commit comments

Comments
 (0)