Skip to content

Commit a69ff7f

Browse files
added conversions from AIFunction to various OpenAI tools
1 parent 3d2ddda commit a69ff7f

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Text.Json;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using OpenAI.Chat;
9+
using OpenAI.RealtimeConversation;
10+
using OpenAI.Responses;
11+
using Xunit;
12+
13+
#pragma warning disable S103 // Lines should not be too long
14+
15+
namespace Microsoft.Extensions.AI;
16+
17+
public class OpenAIAIFunctionConversionTests
18+
{
19+
// Test implementation of AIFunction
20+
private class TestAIFunction : AIFunction
21+
{
22+
public TestAIFunction(string name, string description, Dictionary<string, object> jsonSchema)
23+
{
24+
Name = name;
25+
Description = description;
26+
JsonSchema = System.Text.Json.JsonSerializer.SerializeToElement(jsonSchema);
27+
}
28+
29+
public override string Name { get; }
30+
public override string Description { get; }
31+
public override JsonElement JsonSchema { get; }
32+
protected override async ValueTask<object?> InvokeCoreAsync(AIFunctionArguments arguments, CancellationToken cancellationToken) => await Task.FromResult<object?>(null);
33+
}
34+
35+
// Shared schema for all tests
36+
private static readonly Dictionary<string, object> _testFunctionSchema = new()
37+
{
38+
["type"] = "object",
39+
["properties"] = new Dictionary<string, object>
40+
{
41+
["name"] = new Dictionary<string, object>
42+
{
43+
["type"] = "string",
44+
["description"] = "The name parameter"
45+
}
46+
},
47+
["required"] = new[] { "name" }
48+
};
49+
50+
// Helper method to validate function parameters match our schema
51+
private static void ValidateSchemaParameters(BinaryData parameters)
52+
{
53+
Assert.NotNull(parameters);
54+
55+
using var jsonDoc = JsonDocument.Parse(parameters);
56+
var root = jsonDoc.RootElement;
57+
58+
Assert.Equal("object", root.GetProperty("type").GetString());
59+
Assert.True(root.TryGetProperty("properties", out var properties));
60+
Assert.True(properties.TryGetProperty("name", out var nameProperty));
61+
Assert.Equal("string", nameProperty.GetProperty("type").GetString());
62+
Assert.Equal("The name parameter", nameProperty.GetProperty("description").GetString());
63+
}
64+
65+
[Fact]
66+
public void AIFunctionToChatToolConversionWorks()
67+
{
68+
AIFunction aiFunction = new TestAIFunction(
69+
"test_function",
70+
"A test function for conversion",
71+
_testFunctionSchema);
72+
73+
ChatTool chatTool = aiFunction.AsOpenAIChatTool();
74+
75+
Assert.NotNull(chatTool);
76+
Assert.Equal("test_function", chatTool.FunctionName);
77+
Assert.Equal("A test function for conversion", chatTool.FunctionDescription);
78+
ValidateSchemaParameters(chatTool.FunctionParameters);
79+
}
80+
81+
[Fact]
82+
public void AIFunctionToResponseToolConversionWorks()
83+
{
84+
AIFunction aiFunction = new TestAIFunction(
85+
"test_function",
86+
"A test function for conversion",
87+
_testFunctionSchema);
88+
89+
ResponseTool responseTool = aiFunction.AsOpenAIResponseTool();
90+
91+
Assert.NotNull(responseTool);
92+
}
93+
94+
[Fact]
95+
public void AIFunctionToConversationFunctionToolConversionWorks()
96+
{
97+
AIFunction aiFunction = new TestAIFunction(
98+
"test_function",
99+
"A test function for conversion",
100+
_testFunctionSchema);
101+
102+
ConversationFunctionTool conversationTool = aiFunction.AsOpenAIConversationFunctionTool();
103+
104+
Assert.NotNull(conversationTool);
105+
Assert.Equal("test_function", conversationTool.Name);
106+
Assert.Equal("A test function for conversion", conversationTool.Description);
107+
ValidateSchemaParameters(conversationTool.Parameters);
108+
}
109+
}

0 commit comments

Comments
 (0)