Skip to content

Commit 234c61e

Browse files
author
Gunpal Jain
committed
feat: Added M.E.A.I AIFunction generation
1 parent 8071875 commit 234c61e

18 files changed

+634
-4
lines changed

CSharpToJsonSchema.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpToJsonSchema.Integrat
4242
EndProject
4343
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpToJsonSchema.AotTests", "src\tests\CSharpToJsonSchema.AotTests\CSharpToJsonSchema.AotTests.csproj", "{6167F915-83EB-42F9-929B-AD4719A55811}"
4444
EndProject
45+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSharpToJsonSchema.MeaiTests", "src\tests\CSharpToJsonSchema.MeaiTests\CSharpToJsonSchema.MeaiTests.csproj", "{DC07C90E-A58C-44B3-82D2-E2EB8F777B92}"
46+
EndProject
4547
Global
4648
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4749
Debug|Any CPU = Debug|Any CPU
@@ -76,6 +78,10 @@ Global
7678
{6167F915-83EB-42F9-929B-AD4719A55811}.Debug|Any CPU.Build.0 = Debug|Any CPU
7779
{6167F915-83EB-42F9-929B-AD4719A55811}.Release|Any CPU.ActiveCfg = Release|Any CPU
7880
{6167F915-83EB-42F9-929B-AD4719A55811}.Release|Any CPU.Build.0 = Release|Any CPU
81+
{DC07C90E-A58C-44B3-82D2-E2EB8F777B92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
82+
{DC07C90E-A58C-44B3-82D2-E2EB8F777B92}.Debug|Any CPU.Build.0 = Debug|Any CPU
83+
{DC07C90E-A58C-44B3-82D2-E2EB8F777B92}.Release|Any CPU.ActiveCfg = Release|Any CPU
84+
{DC07C90E-A58C-44B3-82D2-E2EB8F777B92}.Release|Any CPU.Build.0 = Release|Any CPU
7985
EndGlobalSection
8086
GlobalSection(SolutionProperties) = preSolution
8187
HideSolutionNode = FALSE
@@ -89,6 +95,7 @@ Global
8995
{8AFCC30C-C59D-498D-BE68-9A328B3E5599} = {AAA11B78-2764-4520-A97E-46AA7089A588}
9096
{247C813A-9072-4DF3-B403-B35E3688DB4B} = {AAA11B78-2764-4520-A97E-46AA7089A588}
9197
{6167F915-83EB-42F9-929B-AD4719A55811} = {AAA11B78-2764-4520-A97E-46AA7089A588}
98+
{DC07C90E-A58C-44B3-82D2-E2EB8F777B92} = {AAA11B78-2764-4520-A97E-46AA7089A588}
9299
EndGlobalSection
93100
GlobalSection(ExtensibilityGlobals) = postSolution
94101
SolutionGuid = {CED9A020-DBA5-4BE6-8096-75E528648EC1}

src/libs/CSharpToJsonSchema.Generators/Conversion/ToModels.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public static InterfaceData PrepareData(
1818
strict;
1919
var generateGoogleFunctionTool = attributeData.NamedArguments.FirstOrDefault(x => x.Key == "GoogleFunctionTool").Value.Value is bool googleFunctionTool &&
2020
googleFunctionTool;
21+
var meaiFunctionTool= attributeData.NamedArguments.FirstOrDefault(x => x.Key == "MeaiFunctionTool").Value.Value is bool meaift &&
22+
meaift;
2123
var methods = interfaceSymbol
2224
.GetMembers()
2325
.OfType<IMethodSymbol>()
@@ -46,6 +48,7 @@ public static InterfaceData PrepareData(
4648
Namespace: interfaceSymbol.ContainingNamespace.ToDisplayString(),
4749
Name: interfaceSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat),
4850
GoogleFunctionTool:generateGoogleFunctionTool,
51+
MeaiFunctionTool:meaiFunctionTool,
4952
Methods: methods);
5053
}
5154

@@ -60,6 +63,7 @@ public static InterfaceData PrepareMethodData(
6063
List<MethodData> methodList = new();
6164
List<string> namespaces = new();
6265
bool generateGoogleFunctionTools = false;
66+
bool meaiFunctionTools = false;
6367
foreach (var l in list)
6468
{
6569
var (interfaceSymbol, attributeData) = l;
@@ -70,6 +74,11 @@ public static InterfaceData PrepareMethodData(
7074
if(ggft)
7175
generateGoogleFunctionTools = true;
7276

77+
var meai = attributeData.NamedArguments.FirstOrDefault(x => x.Key == "MeaiFunctionTool").Value.Value is bool meaift &&
78+
meaift;
79+
if(meai)
80+
meaiFunctionTools = true;
81+
7382
var x = interfaceSymbol;
7483
var parameters = x.Parameters
7584
//.Where(static x => x.Type.MetadataName != "CancellationToken")
@@ -94,6 +103,7 @@ public static InterfaceData PrepareMethodData(
94103
Namespace: GetCommonRootNamespace(namespaces)??namespaceName,
95104
Name: className,
96105
GoogleFunctionTool: generateGoogleFunctionTools,
106+
MeaiFunctionTool:meaiFunctionTools,
97107
Methods: methodList.ToArray());
98108
}
99109
public static string? GetCommonRootNamespace(IEnumerable<string> namespaces)

src/libs/CSharpToJsonSchema.Generators/JsonSchemaGenerator.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ private void ProcessMethods(IncrementalGeneratorInitializationContext context)
5050
attributes
5151
.SelectAndReportExceptions(AsGoogleFunctionToolsForMethods, context, Id)
5252
.AddSource(context);
53+
attributes
54+
.SelectAndReportExceptions(AsMeaiFunctionToolsForMethods, context, Id)
55+
.AddSource(context);
5356

5457
var generator = new JsonSourceGenerator();
5558
generator.InitializeForFunctionTools(context);
@@ -73,6 +76,9 @@ private void ProcessInterfaces(IncrementalGeneratorInitializationContext context
7376
attributes
7477
.SelectAndReportExceptions(AsGoogleFunctionToolsForInterface, context, Id)
7578
.AddSource(context);
79+
attributes
80+
.SelectAndReportExceptions(AsMeaiFunctionToolsForInterface, context, Id)
81+
.AddSource(context);
7682

7783
var generator = new JsonSourceGenerator();
7884
generator.Initialize2(context);
@@ -119,14 +125,28 @@ private static FileWithName AsFunctionCalls(InterfaceData @interface)
119125
Name: $"{@interface.Name}.FunctionCalls.generated.cs",
120126
Text: Sources.GenerateFunctionCalls(@interface));
121127
}
122-
128+
123129
private static FileWithName AsGoogleFunctionToolsForMethods(InterfaceData @interface)
124130
{
125131
return new FileWithName(
126132
Name: $"{@interface.Name}.GoogleFunctionTools.generated.cs",
127133
Text: Sources.GenerateGoogleFunctionToolForMethods(@interface));
128134
}
129135

136+
private static FileWithName AsMeaiFunctionToolsForMethods(InterfaceData @interface)
137+
{
138+
return new FileWithName(
139+
Name: $"{@interface.Name}.MeaiTools.generated.cs",
140+
Text: Sources.GenerateMeaiFunctionToolForMethods(@interface));
141+
}
142+
143+
private static FileWithName AsMeaiFunctionToolsForInterface(InterfaceData @interface)
144+
{
145+
return new FileWithName(
146+
Name: $"{@interface.Name}.MeaiToolsExtensions.generated.cs",
147+
Text: Sources.GenerateMeaiFunctionToolForInterface(@interface));
148+
}
149+
130150
private static FileWithName AsGoogleFunctionToolsForInterface(InterfaceData @interface)
131151
{
132152
return new FileWithName(

src/libs/CSharpToJsonSchema.Generators/Models/InterfaceData.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ public readonly record struct InterfaceData(
44
string Namespace,
55
string Name,
66
bool GoogleFunctionTool,
7+
bool MeaiFunctionTool,
78
IReadOnlyCollection<MethodData> Methods);

src/libs/CSharpToJsonSchema.Generators/Sources.Method.Calls.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ public static string GenerateFunctionCalls(InterfaceData @interface)
1717
1818
namespace {@interface.Namespace}
1919
{{
20+
21+
22+
23+
24+
25+
26+
27+
2028
{@interface.Methods.Select(static method => $@"
2129
public class {method.Name}Args
2230
{{

src/libs/CSharpToJsonSchema.Generators/Sources.Method.GoogleFunctionTools.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ public static string GenerateGoogleFunctionToolForInterface(InterfaceData @inter
4242
4343
namespace {@interface.Namespace}
4444
{{
45-
public partial class {extensionsClassName}
45+
public static partial class {extensionsClassName}
4646
{{
47-
public global::GenerativeAI.Core.IFunctionTool AsGoogleFunctionTool(this {@interface.Name} service)
47+
public static global::GenerativeAI.Core.IFunctionTool AsGoogleFunctionTool(this {@interface.Name} service)
4848
{{
4949
return new global::GenerativeAI.Tools.GenericFunctionTool(service.AsTools(), service.AsCalls());
5050
}}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using CSharpToJsonSchema.Generators.Models;
2+
3+
namespace CSharpToJsonSchema.Generators;
4+
5+
internal static partial class Sources
6+
{
7+
public static string GenerateMeaiFunctionToolForMethods(InterfaceData @interface)
8+
{
9+
if(@interface.Methods.Count == 0 || !@interface.MeaiFunctionTool)
10+
return string.Empty;
11+
var extensionsClassName = @interface.Name;
12+
13+
return @$"
14+
#nullable enable
15+
16+
namespace {@interface.Namespace}
17+
{{
18+
public partial class {extensionsClassName}
19+
{{
20+
public static implicit operator global::System.Collections.Generic.List<global::Microsoft.Extensions.AI.AITool>? ({@interface.Namespace}.{extensionsClassName} tools)
21+
{{
22+
return tools.AsMeaiTools();
23+
}}
24+
25+
public global::System.Collections.Generic.List<global::Microsoft.Extensions.AI.AITool> AsMeaiTools()
26+
{{
27+
var lst = new global::System.Collections.Generic.List<global::Microsoft.Extensions.AI.AITool>();
28+
var tools = this.AsTools();
29+
var calls = this.AsCalls();
30+
foreach (var tool in tools)
31+
{{
32+
var call = calls[tool.Name];
33+
lst.Add(new global::CSharpToJsonSchema.MeaiFunction(tool, call));
34+
}}
35+
return lst;
36+
}}
37+
}}
38+
}}";
39+
}
40+
41+
public static string GenerateMeaiFunctionToolForInterface(InterfaceData @interface)
42+
{
43+
if(!@interface.MeaiFunctionTool)
44+
return string.Empty;
45+
var extensionsClassName = @interface.Name.Substring(startIndex: 1) + "Extensions";
46+
47+
return @$"
48+
#nullable enable
49+
50+
namespace {@interface.Namespace}
51+
{{
52+
public partial class {extensionsClassName}
53+
{{
54+
public static global::System.Collections.Generic.List<global::Microsoft.Extensions.AI.AITool> AsMeaiTools(this {@interface.Name} service)
55+
{{
56+
var lst = new global::System.Collections.Generic.List<global::Microsoft.Extensions.AI.AITool>();
57+
var tools = service.AsTools();
58+
var calls = service.AsCalls();
59+
foreach (var tool in tools)
60+
{{
61+
var call = calls[tool.Name];
62+
lst.Add(new global::CSharpToJsonSchema.MeaiFunction(tool, call));
63+
}}
64+
return lst;
65+
}}
66+
}}
67+
}}";
68+
}
69+
}

src/libs/CSharpToJsonSchema/CSharpToJsonSchema.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
</PropertyGroup>
1818

1919
<ItemGroup>
20+
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="9.3.0-preview.1.25114.11" />
2021
<PackageReference Include="System.Text.Json" Version="9.0.0" />
2122
</ItemGroup>
2223

src/libs/CSharpToJsonSchema/FunctionToolAttribute.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@ public sealed class FunctionToolAttribute : Attribute
1616
/// Generate Google Function Tools extensions for Google_GenerativeAI SDK
1717
/// </summary>
1818
public bool GoogleFunctionTool { get; set; }
19+
20+
/// <summary>
21+
/// Generate Microsoft.Extension.AI compatible function tools
22+
/// </summary>
23+
public bool MeaiFunctionTool { get; set; }
1924
}

src/libs/CSharpToJsonSchema/GenerateJsonSchemaAttribute.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,9 @@ public sealed class GenerateJsonSchemaAttribute : Attribute
1717
/// Generate Google Function Tools extensions for Google_GenerativeAI SDK
1818
/// </summary>
1919
public bool GoogleFunctionTool { get; set; }
20+
21+
/// <summary>
22+
/// Generate Microsoft.Extension.AI compatible function tools
23+
/// </summary>
24+
public bool MeaiFunctionTool { get; set; }
2025
}

0 commit comments

Comments
 (0)