From 7205ccc3b9d0c2990d30992c152c5b2b7a074dbf Mon Sep 17 00:00:00 2001 From: Xiaoyun Zhang Date: Mon, 15 Jul 2024 12:20:22 -0700 Subject: [PATCH] fix build and tests (#3134) --- .../CodeSnippet/CreateAnAgent.cs | 2 +- ...7_Dynamic_GroupChat_Calculate_Fibonacci.cs | 3 +- .../Example09_LMStudio_FunctionCall.cs | 9 +- .../Function/FunctionAttribute.cs | 2 +- .../Template/FunctionCallTemplate.cs | 488 +++++++++++------- .../Template/FunctionCallTemplate.tt | 5 - .../AutoGen.OpenAI.Tests/MathClassTest.cs | 2 +- ...ests.TestFunctionCallTemplate.approved.txt | 7 +- .../FunctionExample.test.cs | 9 +- dotnet/test/AutoGen.Tests/SingleAgentTest.cs | 7 +- dotnet/test/AutoGen.Tests/TwoAgentTest.cs | 2 +- 11 files changed, 326 insertions(+), 210 deletions(-) diff --git a/dotnet/sample/AutoGen.BasicSamples/CodeSnippet/CreateAnAgent.cs b/dotnet/sample/AutoGen.BasicSamples/CodeSnippet/CreateAnAgent.cs index 4833c6195c..a103f4ec2d 100644 --- a/dotnet/sample/AutoGen.BasicSamples/CodeSnippet/CreateAnAgent.cs +++ b/dotnet/sample/AutoGen.BasicSamples/CodeSnippet/CreateAnAgent.cs @@ -129,7 +129,7 @@ public partial class AssistantCodeSnippet }, functionMap: new Dictionary>> { - { this.UpperCaseFunction.Name, this.UpperCaseWrapper }, // The wrapper function for the UpperCase function + { this.UpperCaseFunctionContract.Name, this.UpperCaseWrapper }, // The wrapper function for the UpperCase function }); var response = await assistantAgent.SendAsync("hello"); diff --git a/dotnet/sample/AutoGen.BasicSamples/Example07_Dynamic_GroupChat_Calculate_Fibonacci.cs b/dotnet/sample/AutoGen.BasicSamples/Example07_Dynamic_GroupChat_Calculate_Fibonacci.cs index 6584baa5fa..72719c606b 100644 --- a/dotnet/sample/AutoGen.BasicSamples/Example07_Dynamic_GroupChat_Calculate_Fibonacci.cs +++ b/dotnet/sample/AutoGen.BasicSamples/Example07_Dynamic_GroupChat_Calculate_Fibonacci.cs @@ -8,6 +8,7 @@ using AutoGen.BasicSample; using AutoGen.Core; using AutoGen.DotnetInteractive; using AutoGen.OpenAI; +using AutoGen.OpenAI.Extension; using FluentAssertions; public partial class Example07_Dynamic_GroupChat_Calculate_Fibonacci @@ -138,7 +139,7 @@ public partial class Example07_Dynamic_GroupChat_Calculate_Fibonacci name: "code_reviewer", systemMessage: @"You review code block from coder", config: gpt3Config, - functions: [functions.ReviewCodeBlockFunction], + functions: [functions.ReviewCodeBlockFunctionContract.ToOpenAIFunctionDefinition()], functionMap: new Dictionary>>() { { nameof(ReviewCodeBlock), functions.ReviewCodeBlockWrapper }, diff --git a/dotnet/sample/AutoGen.BasicSamples/Example09_LMStudio_FunctionCall.cs b/dotnet/sample/AutoGen.BasicSamples/Example09_LMStudio_FunctionCall.cs index 9a62144df2..c9dda27d2e 100644 --- a/dotnet/sample/AutoGen.BasicSamples/Example09_LMStudio_FunctionCall.cs +++ b/dotnet/sample/AutoGen.BasicSamples/Example09_LMStudio_FunctionCall.cs @@ -5,6 +5,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using AutoGen.Core; using AutoGen.LMStudio; +using AutoGen.OpenAI.Extension; using Azure.AI.OpenAI; namespace AutoGen.BasicSample; @@ -69,8 +70,8 @@ public partial class Example09_LMStudio_FunctionCall // And ask agent to response in function call object format using few-shot example object[] functionList = [ - SerializeFunctionDefinition(instance.GetWeatherFunction), - SerializeFunctionDefinition(instance.GoogleSearchFunction) + SerializeFunctionDefinition(instance.GetWeatherFunctionContract.ToOpenAIFunctionDefinition()), + SerializeFunctionDefinition(instance.GetWeatherFunctionContract.ToOpenAIFunctionDefinition()) ]; var functionListString = JsonSerializer.Serialize(functionList, new JsonSerializerOptions { WriteIndented = true }); var lmAgent = new LMStudioAgent( @@ -98,12 +99,12 @@ You have access to the following functions. Use them if required: { var arguments = JsonSerializer.Serialize(functionCall.Arguments); // invoke function wrapper - if (functionCall.Name == instance.GetWeatherFunction.Name) + if (functionCall.Name == instance.GetWeatherFunctionContract.Name) { var result = await instance.GetWeatherWrapper(arguments); return new TextMessage(Role.Assistant, result); } - else if (functionCall.Name == instance.GoogleSearchFunction.Name) + else if (functionCall.Name == instance.GetWeatherFunctionContract.Name) { var result = await instance.GoogleSearchWrapper(arguments); return new TextMessage(Role.Assistant, result); diff --git a/dotnet/src/AutoGen.Core/Function/FunctionAttribute.cs b/dotnet/src/AutoGen.Core/Function/FunctionAttribute.cs index 2c828c26d8..556c16436c 100644 --- a/dotnet/src/AutoGen.Core/Function/FunctionAttribute.cs +++ b/dotnet/src/AutoGen.Core/Function/FunctionAttribute.cs @@ -35,7 +35,7 @@ public class FunctionContract /// /// The name of the function. /// - public string? Name { get; set; } + public string Name { get; set; } = null!; /// /// The description of the function. diff --git a/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.cs b/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.cs index cb3574a8b1..8eeb117141 100644 --- a/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.cs +++ b/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.cs @@ -1,30 +1,31 @@ -//------------------------------------------------------------------------------ +// ------------------------------------------------------------------------------ // // This code was generated by a tool. -// +// Runtime Version: 17.0.0.0 +// // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // -//------------------------------------------------------------------------------ - -namespace AutoGen.SourceGenerator.Template { +// ------------------------------------------------------------------------------ +namespace AutoGen.SourceGenerator.Template +{ using System.Linq; using System.Collections.Generic; using Microsoft.CodeAnalysis; using System; - - internal partial class FunctionCallTemplate : FunctionCallTemplateBase { - - -public string NameSpace {get; set;} -public string ClassName {get; set;} -public IEnumerable FunctionContracts {get; set;} -public bool IsStatic {get; set;} = false; - - - public virtual string TransformText() { - this.GenerationEnvironment = null; + /// + /// Class to produce the template output + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + internal partial class FunctionCallTemplate : FunctionCallTemplateBase + { + /// + /// Create the template output + /// + public virtual string TransformText() + { + this.Write(""); this.Write(@"//---------------------- // // This code was generated by a tool. @@ -41,281 +42,402 @@ using AutoGen.OpenAI.Extension; if (!String.IsNullOrEmpty(NameSpace)) { this.Write("namespace "); this.Write(this.ToStringHelper.ToStringWithCulture(NameSpace)); - this.Write("\n{\n"); + this.Write("\r\n{\r\n"); } this.Write(" public partial class "); this.Write(this.ToStringHelper.ToStringWithCulture(ClassName)); - this.Write("\n {\n"); + this.Write("\r\n {\r\n"); foreach (var functionContract in FunctionContracts) { - this.Write("\n private class "); + this.Write("\r\n private class "); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionSchemaClassName())); - this.Write("\n {\n"); + this.Write("\r\n {\r\n"); foreach (var parameter in functionContract.Parameters) { if (parameter.IsOptional) { this.Write(" [JsonPropertyName(@\""); this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - this.Write("\")]\n\t\t\tpublic "); + this.Write("\")]\r\n\t\t\tpublic "); this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type)); this.Write(" "); this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); this.Write(" {get; set;} = "); this.Write(this.ToStringHelper.ToStringWithCulture(parameter.DefaultValue)); - this.Write(";\n"); + this.Write(";\r\n"); } else { this.Write(" [JsonPropertyName(@\""); this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - this.Write("\")]\n\t\t\tpublic "); + this.Write("\")]\r\n\t\t\tpublic "); this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type)); this.Write(" "); this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - this.Write(" {get; set;}\n"); + this.Write(" {get; set;}\r\n"); } } - this.Write(" }\n\n public "); + this.Write(" }\r\n\r\n public "); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.ReturnType)); this.Write(" "); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionWrapperName())); - this.Write("(string arguments)\n {\n var schema = JsonSerializer.Deserialize<" + - ""); + this.Write("(string arguments)\r\n {\r\n var schema = JsonSerializer.Deserializ" + + "e<"); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionSchemaClassName())); - this.Write(">(\n arguments, \n new JsonSerializerOptions\n " + - " {\n PropertyNamingPolicy = JsonNamingPolicy.CamelCase," + - "\n });\n"); + this.Write(">(\r\n arguments, \r\n new JsonSerializerOptions\r\n " + + " {\r\n PropertyNamingPolicy = JsonNamingPolicy.CamelC" + + "ase,\r\n });\r\n"); var argumentLists = string.Join(", ", functionContract.Parameters.Select(p => $"schema.{p.Name}")); - this.Write("\n return "); + this.Write("\r\n return "); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.Name)); this.Write("("); this.Write(this.ToStringHelper.ToStringWithCulture(argumentLists)); - this.Write(");\n }\n\n public FunctionContract "); + this.Write(");\r\n }\r\n\r\n public FunctionContract "); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionContractName())); - this.Write("\n {\n get => new FunctionContract\n {\n"); + this.Write("\r\n {\r\n get => new FunctionContract\r\n {\r\n"); if (functionContract.Namespace != null) { this.Write(" Namespace = @\""); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.Namespace)); - this.Write("\",\n"); + this.Write("\",\r\n"); } if (functionContract.ClassName != null) { this.Write(" ClassName = @\""); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.ClassName)); - this.Write("\",\n"); + this.Write("\",\r\n"); } if (functionContract.Name != null) { this.Write(" Name = @\""); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.Name)); - this.Write("\",\n"); + this.Write("\",\r\n"); } if (functionContract.Description != null) { this.Write(" Description = @\""); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.Description.Replace("\"", "\"\""))); - this.Write("\",\n"); + this.Write("\",\r\n"); } if (functionContract.ReturnType != null) { this.Write(" ReturnType = typeof("); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.ReturnType)); - this.Write("),\n"); + this.Write("),\r\n"); } if (functionContract.ReturnDescription != null) { this.Write(" ReturnDescription = @\""); this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.ReturnDescription)); - this.Write("\",\n"); + this.Write("\",\r\n"); } if (functionContract.Parameters != null) { this.Write(" Parameters = new global::AutoGen.Core.FunctionParameterContract[]" + - "\n {\n"); + "\r\n {\r\n"); foreach (var parameter in functionContract.Parameters) { - this.Write(" new FunctionParameterContract\n {\n"); + this.Write(" new FunctionParameterContract\r\n {\r\n"); if (parameter.Name != null) { this.Write(" Name = @\""); this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Name)); - this.Write("\",\n"); + this.Write("\",\r\n"); } if (parameter.Description != null) { this.Write(" Description = @\""); - this.Write(this.ToStringHelper.ToStringWithCulture( parameter.Description.Replace("\"", "\"\"") )); - this.Write("\",\n"); + this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Description.Replace("\"", "\"\""))); + this.Write("\",\r\n"); } if (parameter.Type != null) { this.Write(" ParameterType = typeof("); this.Write(this.ToStringHelper.ToStringWithCulture(parameter.Type)); - this.Write("),\n"); + this.Write("),\r\n"); } this.Write(" IsRequired = "); this.Write(this.ToStringHelper.ToStringWithCulture(parameter.IsOptional ? "false" : "true")); - this.Write(",\n"); + this.Write(",\r\n"); if (parameter.DefaultValue != null) { this.Write(" DefaultValue = "); this.Write(this.ToStringHelper.ToStringWithCulture(parameter.DefaultValue)); - this.Write(",\n"); + this.Write(",\r\n"); } - this.Write(" },\n"); + this.Write(" },\r\n"); } - this.Write(" },\n"); + this.Write(" },\r\n"); } - this.Write(" };\n }\n\n public global::Azure.AI.OpenAI.FunctionDefiniti" + - "on "); - this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionDefinitionName())); - this.Write("\n {\n get => this."); - this.Write(this.ToStringHelper.ToStringWithCulture(functionContract.GetFunctionContractName())); - this.Write(".ToOpenAIFunctionDefinition();\n }\n"); + this.Write(" };\r\n }\r\n"); } - this.Write(" }\n"); + this.Write(" }\r\n"); if (!String.IsNullOrEmpty(NameSpace)) { - this.Write("}\n"); + this.Write("}\r\n"); } - this.Write("\n"); + this.Write("\r\n"); return this.GenerationEnvironment.ToString(); } - - public virtual void Initialize() { - } + +public string NameSpace {get; set;} +public string ClassName {get; set;} +public IEnumerable FunctionContracts {get; set;} +public bool IsStatic {get; set;} = false; + } - - public class FunctionCallTemplateBase { - - private global::System.Text.StringBuilder builder; - - private global::System.Collections.Generic.IDictionary session; - - private global::System.CodeDom.Compiler.CompilerErrorCollection errors; - - private string currentIndent = string.Empty; - - private global::System.Collections.Generic.Stack indents; - - private ToStringInstanceHelper _toStringHelper = new ToStringInstanceHelper(); - - public virtual global::System.Collections.Generic.IDictionary Session { - get { - return this.session; - } - set { - this.session = value; - } - } - - public global::System.Text.StringBuilder GenerationEnvironment { - get { - if ((this.builder == null)) { - this.builder = new global::System.Text.StringBuilder(); + #region Base class + /// + /// Base class for this transformation + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")] + internal class FunctionCallTemplateBase + { + #region Fields + private global::System.Text.StringBuilder generationEnvironmentField; + private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField; + private global::System.Collections.Generic.List indentLengthsField; + private string currentIndentField = ""; + private bool endsWithNewline; + private global::System.Collections.Generic.IDictionary sessionField; + #endregion + #region Properties + /// + /// The string builder that generation-time code is using to assemble generated output + /// + public System.Text.StringBuilder GenerationEnvironment + { + get + { + if ((this.generationEnvironmentField == null)) + { + this.generationEnvironmentField = new global::System.Text.StringBuilder(); } - return this.builder; + return this.generationEnvironmentField; } - set { - this.builder = value; + set + { + this.generationEnvironmentField = value; } } - - protected global::System.CodeDom.Compiler.CompilerErrorCollection Errors { - get { - if ((this.errors == null)) { - this.errors = new global::System.CodeDom.Compiler.CompilerErrorCollection(); + /// + /// The error collection for the generation process + /// + public System.CodeDom.Compiler.CompilerErrorCollection Errors + { + get + { + if ((this.errorsField == null)) + { + this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection(); } - return this.errors; + return this.errorsField; } } - - public string CurrentIndent { - get { - return this.currentIndent; - } - } - - private global::System.Collections.Generic.Stack Indents { - get { - if ((this.indents == null)) { - this.indents = new global::System.Collections.Generic.Stack(); + /// + /// A list of the lengths of each indent that was added with PushIndent + /// + private System.Collections.Generic.List indentLengths + { + get + { + if ((this.indentLengthsField == null)) + { + this.indentLengthsField = new global::System.Collections.Generic.List(); } - return this.indents; + return this.indentLengthsField; } } - - public ToStringInstanceHelper ToStringHelper { - get { - return this._toStringHelper; + /// + /// Gets the current indent we use when adding lines to the output + /// + public string CurrentIndent + { + get + { + return this.currentIndentField; } } - - public void Error(string message) { - this.Errors.Add(new global::System.CodeDom.Compiler.CompilerError(null, -1, -1, null, message)); - } - - public void Warning(string message) { - global::System.CodeDom.Compiler.CompilerError val = new global::System.CodeDom.Compiler.CompilerError(null, -1, -1, null, message); - val.IsWarning = true; - this.Errors.Add(val); - } - - public string PopIndent() { - if ((this.Indents.Count == 0)) { - return string.Empty; + /// + /// Current transformation session + /// + public virtual global::System.Collections.Generic.IDictionary Session + { + get + { + return this.sessionField; + } + set + { + this.sessionField = value; } - int lastPos = (this.currentIndent.Length - this.Indents.Pop()); - string last = this.currentIndent.Substring(lastPos); - this.currentIndent = this.currentIndent.Substring(0, lastPos); - return last; } - - public void PushIndent(string indent) { - this.Indents.Push(indent.Length); - this.currentIndent = (this.currentIndent + indent); + #endregion + #region Transform-time helpers + /// + /// Write text directly into the generated output + /// + public void Write(string textToAppend) + { + if (string.IsNullOrEmpty(textToAppend)) + { + return; + } + // If we're starting off, or if the previous text ended with a newline, + // we have to append the current indent first. + if (((this.GenerationEnvironment.Length == 0) + || this.endsWithNewline)) + { + this.GenerationEnvironment.Append(this.currentIndentField); + this.endsWithNewline = false; + } + // Check if the current text ends with a newline + if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture)) + { + this.endsWithNewline = true; + } + // This is an optimization. If the current indent is "", then we don't have to do any + // of the more complex stuff further down. + if ((this.currentIndentField.Length == 0)) + { + this.GenerationEnvironment.Append(textToAppend); + return; + } + // Everywhere there is a newline in the text, add an indent after it + textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField)); + // If the text ends with a newline, then we should strip off the indent added at the very end + // because the appropriate indent will be added when the next time Write() is called + if (this.endsWithNewline) + { + this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length)); + } + else + { + this.GenerationEnvironment.Append(textToAppend); + } } - - public void ClearIndent() { - this.currentIndent = string.Empty; - this.Indents.Clear(); - } - - public void Write(string textToAppend) { - this.GenerationEnvironment.Append(textToAppend); - } - - public void Write(string format, params object[] args) { - this.GenerationEnvironment.AppendFormat(format, args); - } - - public void WriteLine(string textToAppend) { - this.GenerationEnvironment.Append(this.currentIndent); - this.GenerationEnvironment.AppendLine(textToAppend); - } - - public void WriteLine(string format, params object[] args) { - this.GenerationEnvironment.Append(this.currentIndent); - this.GenerationEnvironment.AppendFormat(format, args); + /// + /// Write text directly into the generated output + /// + public void WriteLine(string textToAppend) + { + this.Write(textToAppend); this.GenerationEnvironment.AppendLine(); + this.endsWithNewline = true; } - - public class ToStringInstanceHelper { - - private global::System.IFormatProvider formatProvider = global::System.Globalization.CultureInfo.InvariantCulture; - - public global::System.IFormatProvider FormatProvider { - get { - return this.formatProvider; + /// + /// Write formatted text directly into the generated output + /// + public void Write(string format, params object[] args) + { + this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Write formatted text directly into the generated output + /// + public void WriteLine(string format, params object[] args) + { + this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args)); + } + /// + /// Raise an error + /// + public void Error(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + this.Errors.Add(error); + } + /// + /// Raise a warning + /// + public void Warning(string message) + { + System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError(); + error.ErrorText = message; + error.IsWarning = true; + this.Errors.Add(error); + } + /// + /// Increase the indent + /// + public void PushIndent(string indent) + { + if ((indent == null)) + { + throw new global::System.ArgumentNullException("indent"); + } + this.currentIndentField = (this.currentIndentField + indent); + this.indentLengths.Add(indent.Length); + } + /// + /// Remove the last indent that was added with PushIndent + /// + public string PopIndent() + { + string returnValue = ""; + if ((this.indentLengths.Count > 0)) + { + int indentLength = this.indentLengths[(this.indentLengths.Count - 1)]; + this.indentLengths.RemoveAt((this.indentLengths.Count - 1)); + if ((indentLength > 0)) + { + returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength)); + this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength)); } - set { - if ((value != null)) { - this.formatProvider = value; + } + return returnValue; + } + /// + /// Remove any indentation + /// + public void ClearIndent() + { + this.indentLengths.Clear(); + this.currentIndentField = ""; + } + #endregion + #region ToString Helpers + /// + /// Utility class to produce culture-oriented representation of an object as a string. + /// + public class ToStringInstanceHelper + { + private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture; + /// + /// Gets or sets format provider to be used by ToStringWithCulture method. + /// + public System.IFormatProvider FormatProvider + { + get + { + return this.formatProviderField ; + } + set + { + if ((value != null)) + { + this.formatProviderField = value; } } } - - public string ToStringWithCulture(object objectToConvert) { - if ((objectToConvert == null)) { + /// + /// This is called from the compile/run appdomain to convert objects within an expression block to a string + /// + public string ToStringWithCulture(object objectToConvert) + { + if ((objectToConvert == null)) + { throw new global::System.ArgumentNullException("objectToConvert"); } - global::System.Type type = objectToConvert.GetType(); - global::System.Type iConvertibleType = typeof(global::System.IConvertible); - if (iConvertibleType.IsAssignableFrom(type)) { - return ((global::System.IConvertible)(objectToConvert)).ToString(this.formatProvider); + System.Type t = objectToConvert.GetType(); + System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] { + typeof(System.IFormatProvider)}); + if ((method == null)) + { + return objectToConvert.ToString(); } - global::System.Reflection.MethodInfo methInfo = type.GetMethod("ToString", new global::System.Type[] { - iConvertibleType}); - if ((methInfo != null)) { - return ((string)(methInfo.Invoke(objectToConvert, new object[] { - this.formatProvider}))); + else + { + return ((string)(method.Invoke(objectToConvert, new object[] { + this.formatProviderField }))); } - return objectToConvert.ToString(); } } + private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper(); + /// + /// Helper to produce culture-oriented representation of an object as a string + /// + public ToStringInstanceHelper ToStringHelper + { + get + { + return this.toStringHelperField; + } + } + #endregion } + #endregion } diff --git a/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.tt b/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.tt index c7a13ce1fe..dc41f0af9d 100644 --- a/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.tt +++ b/dotnet/src/AutoGen.SourceGenerator/Template/FunctionCallTemplate.tt @@ -96,11 +96,6 @@ namespace <#=NameSpace#> <#}#> }; } - - public global::Azure.AI.OpenAI.FunctionDefinition <#=functionContract.GetFunctionDefinitionName()#> - { - get => this.<#=functionContract.GetFunctionContractName()#>.ToOpenAIFunctionDefinition(); - } <#}#> } <#if (!String.IsNullOrEmpty(NameSpace)) {#> diff --git a/dotnet/test/AutoGen.OpenAI.Tests/MathClassTest.cs b/dotnet/test/AutoGen.OpenAI.Tests/MathClassTest.cs index aae314ff77..01af3d4646 100644 --- a/dotnet/test/AutoGen.OpenAI.Tests/MathClassTest.cs +++ b/dotnet/test/AutoGen.OpenAI.Tests/MathClassTest.cs @@ -110,7 +110,7 @@ teacher, please create the next math question"; functions: [this.UpdateProgressFunctionContract], functionMap: new Dictionary>> { - { this.UpdateProgressFunction.Name!, this.UpdateProgressWrapper }, + { this.UpdateProgressFunctionContract.Name, this.UpdateProgressWrapper }, }); var admin = new OpenAIChatAgent( openAIClient: openaiClient, diff --git a/dotnet/test/AutoGen.SourceGenerator.Tests/ApprovalTests/FunctionCallTemplateTests.TestFunctionCallTemplate.approved.txt b/dotnet/test/AutoGen.SourceGenerator.Tests/ApprovalTests/FunctionCallTemplateTests.TestFunctionCallTemplate.approved.txt index a5ffa3c824..f223d3124d 100644 --- a/dotnet/test/AutoGen.SourceGenerator.Tests/ApprovalTests/FunctionCallTemplateTests.TestFunctionCallTemplate.approved.txt +++ b/dotnet/test/AutoGen.SourceGenerator.Tests/ApprovalTests/FunctionCallTemplateTests.TestFunctionCallTemplate.approved.txt @@ -1,4 +1,4 @@ -//---------------------- +//---------------------- // // This code was generated by a tool. // @@ -61,11 +61,6 @@ namespace AutoGen.SourceGenerator.Tests }, }; } - - public global::Azure.AI.OpenAI.FunctionDefinition AddAsyncFunction - { - get => this.AddAsyncFunctionContract.ToOpenAIFunctionDefinition(); - } } } diff --git a/dotnet/test/AutoGen.SourceGenerator.Tests/FunctionExample.test.cs b/dotnet/test/AutoGen.SourceGenerator.Tests/FunctionExample.test.cs index f7b90e0b96..0096f2c157 100644 --- a/dotnet/test/AutoGen.SourceGenerator.Tests/FunctionExample.test.cs +++ b/dotnet/test/AutoGen.SourceGenerator.Tests/FunctionExample.test.cs @@ -5,6 +5,7 @@ using System.Text.Json; using ApprovalTests; using ApprovalTests.Namers; using ApprovalTests.Reporters; +using AutoGen.OpenAI.Extension; using Azure.AI.OpenAI; using FluentAssertions; using Xunit; @@ -29,7 +30,7 @@ namespace AutoGen.SourceGenerator.Tests }; this.VerifyFunction(functionExamples.AddWrapper, args, 3); - this.VerifyFunctionDefinition(functionExamples.AddFunction); + this.VerifyFunctionDefinition(functionExamples.AddFunctionContract.ToOpenAIFunctionDefinition()); } [Fact] @@ -41,7 +42,7 @@ namespace AutoGen.SourceGenerator.Tests }; this.VerifyFunction(functionExamples.SumWrapper, args, 6.0); - this.VerifyFunctionDefinition(functionExamples.SumFunction); + this.VerifyFunctionDefinition(functionExamples.SumFunctionContract.ToOpenAIFunctionDefinition()); } [Fact] @@ -57,7 +58,7 @@ namespace AutoGen.SourceGenerator.Tests }; await this.VerifyAsyncFunction(functionExamples.DictionaryToStringAsyncWrapper, args, JsonSerializer.Serialize(args.xargs, jsonSerializerOptions)); - this.VerifyFunctionDefinition(functionExamples.DictionaryToStringAsyncFunction); + this.VerifyFunctionDefinition(functionExamples.DictionaryToStringAsyncFunctionContract.ToOpenAIFunctionDefinition()); } [Fact] @@ -96,7 +97,7 @@ namespace AutoGen.SourceGenerator.Tests }; this.VerifyFunction(functionExamples.QueryWrapper, args, new[] { "hello", "hello", "hello" }); - this.VerifyFunctionDefinition(functionExamples.QueryFunction); + this.VerifyFunctionDefinition(functionExamples.QueryFunctionContract.ToOpenAIFunctionDefinition()); } [UseReporter(typeof(DiffReporter))] diff --git a/dotnet/test/AutoGen.Tests/SingleAgentTest.cs b/dotnet/test/AutoGen.Tests/SingleAgentTest.cs index 64bdc062eb..b545bbdbe8 100644 --- a/dotnet/test/AutoGen.Tests/SingleAgentTest.cs +++ b/dotnet/test/AutoGen.Tests/SingleAgentTest.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading.Tasks; using AutoGen.LMStudio; using AutoGen.OpenAI; +using AutoGen.OpenAI.Extension; using Azure.AI.OpenAI; using FluentAssertions; using Xunit; @@ -64,7 +65,7 @@ namespace AutoGen.Tests systemMessage: "You are a helpful AI assistant, return highest label from conversation", config: gpt3Config, temperature: 0, - functions: new[] { this.GetHighestLabelFunction }, + functions: new[] { this.GetHighestLabelFunctionContract.ToOpenAIFunctionDefinition() }, functionMap: new Dictionary>> { { nameof(GetHighestLabel), this.GetHighestLabelWrapper }, @@ -116,7 +117,7 @@ namespace AutoGen.Tests public async Task GPTFunctionCallAgentTestAsync() { var config = this.CreateAzureOpenAIGPT35TurboConfig(); - var agentWithFunction = new GPTAgent("gpt", "You are a helpful AI assistant", config, 0, functions: new[] { this.EchoAsyncFunction }); + var agentWithFunction = new GPTAgent("gpt", "You are a helpful AI assistant", config, 0, functions: new[] { this.EchoAsyncFunctionContract.ToOpenAIFunctionDefinition() }); await EchoFunctionCallTestAsync(agentWithFunction); } @@ -233,7 +234,7 @@ namespace AutoGen.Tests systemMessage: "You are a helpful AI assistant", config: config, temperature: 0, - functions: new[] { this.EchoAsyncFunction }, + functions: new[] { this.EchoAsyncFunctionContract.ToOpenAIFunctionDefinition() }, functionMap: new Dictionary>> { { nameof(EchoAsync), this.EchoAsyncWrapper }, diff --git a/dotnet/test/AutoGen.Tests/TwoAgentTest.cs b/dotnet/test/AutoGen.Tests/TwoAgentTest.cs index 90c1bfa9a1..100a22c04a 100644 --- a/dotnet/test/AutoGen.Tests/TwoAgentTest.cs +++ b/dotnet/test/AutoGen.Tests/TwoAgentTest.cs @@ -56,7 +56,7 @@ public partial class TwoAgentTest name: "user", functionMap: new Dictionary>> { - { this.GetWeatherFunction.Name, this.GetWeatherWrapper }, + { this.GetWeatherFunctionContract.Name, this.GetWeatherWrapper }, }) .RegisterMiddleware(async (msgs, option, agent, ct) => {