Skip to content

Commit c419cea

Browse files
OpenAI-DotNet 8.7.3 (#468)
- Fixed Response.Instructions deserialization when using CreateResponseRequest.Prompt
1 parent 620b285 commit c419cea

4 files changed

Lines changed: 88 additions & 5 deletions

File tree

OpenAI-DotNet-Tests/TestFixture_14_Responses.cs

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ public async Task Test_04_01_JsonSchema()
339339
}
340340

341341
[Test]
342-
public async Task Test_04_01_JsonSchema_Streaming()
342+
public async Task Test_04_02_JsonSchema_Streaming()
343343
{
344344
Assert.IsNotNull(OpenAIClient.ResponsesEndpoint);
345345

@@ -385,5 +385,84 @@ Task StreamCallback(string @event, IServerSentEvent sseEvent)
385385
Assert.IsNotEmpty(mathResponse.Steps);
386386
response.PrintUsage();
387387
}
388+
389+
[Test]
390+
public async Task Test_05_01_Prompts()
391+
{
392+
Assert.NotNull(OpenAIClient.ResponsesEndpoint);
393+
394+
var conversation = new List<IResponseItem>
395+
{
396+
new Message(Role.User, "What's the weather like today?"),
397+
};
398+
var tools = new List<Tool>
399+
{
400+
Tool.GetOrCreateTool(typeof(WeatherService), nameof(WeatherService.GetCurrentWeatherAsync)),
401+
};
402+
var request = new CreateResponseRequest(
403+
input: conversation,
404+
model: Model.GPT4_1_Nano,
405+
prompt: new Prompt("pmpt_685c102c61608193b3654325fa76fc880b22337c811a3a71"),
406+
tools: tools,
407+
toolChoice: "none");
408+
var response = await OpenAIClient.ResponsesEndpoint.CreateModelResponseAsync(request);
409+
Assert.NotNull(response);
410+
Assert.IsNotEmpty(response.Id);
411+
Assert.AreEqual(ResponseStatus.Completed, response.Status);
412+
var responseItem = response.Output.LastOrDefault();
413+
Assert.NotNull(responseItem);
414+
Assert.AreEqual(ResponseItemType.Message, responseItem.Type);
415+
Assert.IsInstanceOf<Message>(responseItem);
416+
var messageItem = responseItem as Message;
417+
Assert.NotNull(messageItem);
418+
Assert.IsNotEmpty(messageItem!.Content);
419+
Assert.IsInstanceOf<Responses.TextContent>(messageItem.Content[0]);
420+
var textContent = messageItem.Content[0] as Responses.TextContent;
421+
Assert.NotNull(textContent);
422+
Assert.IsNotEmpty(textContent!.Text);
423+
Console.WriteLine($"{messageItem.Role}:{textContent.Text}");
424+
response.PrintUsage();
425+
conversation.Add(messageItem);
426+
conversation.Add(new Message(Role.User, "I'm currently in San Francisco"));
427+
request = new(conversation, Model.GPT4_1_Nano, tools: tools, toolChoice: "auto");
428+
response = await OpenAIClient.ResponsesEndpoint.CreateModelResponseAsync(request);
429+
Assert.NotNull(response);
430+
Assert.IsNotEmpty(response.Id);
431+
Assert.AreEqual(ResponseStatus.Completed, response.Status);
432+
responseItem = response.Output.LastOrDefault();
433+
Assert.NotNull(responseItem);
434+
Assert.AreEqual(ResponseItemType.FunctionCall, responseItem.Type);
435+
Assert.IsInstanceOf<FunctionToolCall>(responseItem);
436+
var usedTool = responseItem as FunctionToolCall;
437+
conversation.Add(usedTool);
438+
Assert.NotNull(usedTool);
439+
Assert.IsNotEmpty(usedTool.Name);
440+
Assert.IsTrue(usedTool.Name.Contains(nameof(WeatherService.GetCurrentWeatherAsync)));
441+
Assert.NotNull(usedTool.Arguments);
442+
Console.WriteLine($"{usedTool.Name}: {usedTool.Arguments}");
443+
response.PrintUsage();
444+
var functionResult = await usedTool.InvokeFunctionAsync();
445+
Assert.IsNotNull(functionResult);
446+
Console.WriteLine($"{usedTool.Name} Result: {functionResult}");
447+
conversation.Add(functionResult);
448+
request = new(conversation, Model.GPT4_1_Nano, tools: tools, toolChoice: "none");
449+
response = await OpenAIClient.ResponsesEndpoint.CreateModelResponseAsync(request);
450+
Assert.NotNull(response);
451+
Assert.IsNotEmpty(response.Id);
452+
Assert.AreEqual(ResponseStatus.Completed, response.Status);
453+
responseItem = response.Output.LastOrDefault();
454+
Assert.NotNull(responseItem);
455+
Assert.AreEqual(ResponseItemType.Message, responseItem.Type);
456+
Assert.IsInstanceOf<Message>(responseItem);
457+
messageItem = responseItem as Message;
458+
Assert.NotNull(messageItem);
459+
Assert.IsNotEmpty(messageItem!.Content);
460+
Assert.IsInstanceOf<Responses.TextContent>(messageItem.Content[0]);
461+
textContent = messageItem.Content[0] as Responses.TextContent;
462+
Assert.NotNull(textContent);
463+
Assert.IsNotEmpty(textContent!.Text);
464+
Console.WriteLine($"{messageItem.Role}: {messageItem}");
465+
response.PrintUsage();
466+
}
388467
}
389468
}

OpenAI-DotNet/Extensions/StringOrObjectConverter.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public override dynamic Read(ref Utf8JsonReader reader, Type typeToConvert, Json
1414
JsonTokenType.Null => null,
1515
JsonTokenType.String => reader.GetString(),
1616
JsonTokenType.StartObject => JsonSerializer.Deserialize<T>(ref reader, options),
17+
JsonTokenType.StartArray => JsonSerializer.Deserialize<T>(ref reader, options),
1718
_ => throw new JsonException($"Unexpected token type: {reader.TokenType}")
1819
};
1920

OpenAI-DotNet/OpenAI-DotNet.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,10 @@ More context [on Roger Pincombe's blog](https://rogerpincombe.com/openai-dotnet-
2929
<AssemblyOriginatorKeyFile>OpenAI-DotNet.pfx</AssemblyOriginatorKeyFile>
3030
<IncludeSymbols>true</IncludeSymbols>
3131
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
32-
<Version>8.7.2</Version>
32+
<Version>8.7.3</Version>
3333
<PackageReleaseNotes>
34+
Version 8.7.3
35+
- Fixed Response.Instructions deserialization when using CreateResponseRequest.Prompt
3436
Version 8.7.2
3537
- Add support for predefined prompts in Responses endpoint
3638
- Fixed WebSearchToolPreview streaming annotation deserialization

OpenAI-DotNet/Responses/Response.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,16 @@ public IReadOnlyList<IResponseItem> Output
9090
public bool? ParallelToolCalls { get; private set; }
9191

9292
/// <summary>
93-
/// Inserts a system (or developer) message as the first item in the model's context.
94-
/// When using along with `previous_response_id`,
93+
/// A system (or developer) message inserted into the model's context.
94+
/// When using along with previous_response_id,
9595
/// the instructions from a previous response will not be carried over to the next response.
9696
/// This makes it simple to swap out system (or developer) messages in new responses.
9797
/// </summary>
9898
[JsonInclude]
9999
[JsonPropertyName("instructions")]
100100
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
101-
public string Instructions { get; private set; }
101+
[JsonConverter(typeof(StringOrObjectConverter<IReadOnlyList<IResponseItem>>))]
102+
public object Instructions { get; private set; }
102103

103104
/// <summary>
104105
/// An upper bound for the number of tokens that can be generated for a

0 commit comments

Comments
 (0)