Skip to content

Commit b6fcfd1

Browse files
artl93jeffhandley
authored andcommitted
Adding reference to an unsupported built-in tool on OpenAI Chat API no longer throws (#6276)
1 parent fcf0097 commit b6fcfd1

File tree

2 files changed

+103
-15
lines changed

2 files changed

+103
-15
lines changed

src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIChatClient.cs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -582,22 +582,25 @@ private static ChatCompletionOptions ToOpenAIOptions(ChatOptions? options)
582582
}
583583
}
584584

585-
switch (options.ToolMode)
585+
if (result.Tools.Count > 0)
586586
{
587-
case NoneChatToolMode:
588-
result.ToolChoice = ChatToolChoice.CreateNoneChoice();
589-
break;
590-
591-
case AutoChatToolMode:
592-
case null:
593-
result.ToolChoice = ChatToolChoice.CreateAutoChoice();
594-
break;
595-
596-
case RequiredChatToolMode required:
597-
result.ToolChoice = required.RequiredFunctionName is null ?
598-
ChatToolChoice.CreateRequiredChoice() :
599-
ChatToolChoice.CreateFunctionChoice(required.RequiredFunctionName);
600-
break;
587+
switch (options.ToolMode)
588+
{
589+
case NoneChatToolMode:
590+
result.ToolChoice = ChatToolChoice.CreateNoneChoice();
591+
break;
592+
593+
case AutoChatToolMode:
594+
case null:
595+
result.ToolChoice = ChatToolChoice.CreateAutoChoice();
596+
break;
597+
598+
case RequiredChatToolMode required:
599+
result.ToolChoice = required.RequiredFunctionName is null ?
600+
ChatToolChoice.CreateRequiredChoice() :
601+
ChatToolChoice.CreateFunctionChoice(required.RequiredFunctionName);
602+
break;
603+
}
601604
}
602605
}
603606

test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIChatClientTests.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,91 @@ public async Task FunctionCallContent_NonStreaming()
773773
Assert.Equal("fp_f85bea6784", response.AdditionalProperties[nameof(ChatCompletion.SystemFingerprint)]);
774774
}
775775

776+
[Fact]
777+
public async Task UnavailableBuiltInFunctionCall_NonStreaming()
778+
{
779+
const string Input = """
780+
{
781+
"messages": [
782+
{
783+
"role": "user",
784+
"content": "What day is it?"
785+
}
786+
],
787+
"model": "gpt-4o-mini"
788+
}
789+
""";
790+
791+
const string Output = """
792+
{
793+
"id": "chatcmpl-ADydKhrSKEBWJ8gy0KCIU74rN3Hmk",
794+
"object": "chat.completion",
795+
"created": 1727894702,
796+
"model": "gpt-4o-mini-2024-07-18",
797+
"choices": [
798+
{
799+
"index": 0,
800+
"message": {
801+
"role": "assistant",
802+
"content": "December 31, 2023",
803+
"refusal": null
804+
},
805+
"logprobs": null,
806+
"finish_reason": "stop"
807+
}
808+
],
809+
"usage": {
810+
"prompt_tokens": 61,
811+
"completion_tokens": 16,
812+
"total_tokens": 77,
813+
"prompt_tokens_details": {
814+
"cached_tokens": 13
815+
},
816+
"completion_tokens_details": {
817+
"reasoning_tokens": 90
818+
}
819+
},
820+
"system_fingerprint": "fp_f85bea6784"
821+
}
822+
""";
823+
824+
using VerbatimHttpHandler handler = new(Input, Output);
825+
using HttpClient httpClient = new(handler);
826+
using IChatClient client = CreateChatClient(httpClient, "gpt-4o-mini");
827+
828+
var response = await client.GetResponseAsync("What day is it?", new()
829+
{
830+
Tools = [new HostedWebSearchTool()],
831+
});
832+
Assert.NotNull(response);
833+
834+
Assert.Equal("December 31, 2023", response.Text);
835+
Assert.Equal("gpt-4o-mini-2024-07-18", response.ModelId);
836+
Assert.Equal(ChatRole.Assistant, response.Messages.Single().Role);
837+
Assert.Equal(DateTimeOffset.FromUnixTimeSeconds(1_727_894_702), response.CreatedAt);
838+
Assert.Equal(ChatFinishReason.Stop, response.FinishReason);
839+
Assert.NotNull(response.Usage);
840+
Assert.Equal(61, response.Usage.InputTokenCount);
841+
Assert.Equal(16, response.Usage.OutputTokenCount);
842+
Assert.Equal(77, response.Usage.TotalTokenCount);
843+
844+
Assert.Equal(new Dictionary<string, long>
845+
{
846+
{ "InputTokenDetails.AudioTokenCount", 0 },
847+
{ "InputTokenDetails.CachedTokenCount", 13 },
848+
{ "OutputTokenDetails.ReasoningTokenCount", 90 },
849+
{ "OutputTokenDetails.AudioTokenCount", 0 },
850+
{ "OutputTokenDetails.AcceptedPredictionTokenCount", 0 },
851+
{ "OutputTokenDetails.RejectedPredictionTokenCount", 0 },
852+
}, response.Usage.AdditionalCounts);
853+
854+
Assert.Single(response.Messages.Single().Contents);
855+
TextContent fcc = Assert.IsType<TextContent>(response.Messages.Single().Contents[0]);
856+
857+
Assert.NotNull(response.AdditionalProperties);
858+
Assert.Equal("fp_f85bea6784", response.AdditionalProperties[nameof(ChatCompletion.SystemFingerprint)]);
859+
}
860+
776861
[Fact]
777862
public async Task FunctionCallContent_Streaming()
778863
{

0 commit comments

Comments
 (0)