microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
5a1c731828fac7c70d50499cc4a9a1e83e934551

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

Libraries/Microsoft.Teams.AI/Function.cs

116lines · modecode

1using System.Reflection;
2using System.Text.Json;
3using System.Text.Json.Nodes;
4using System.Text.Json.Serialization;
5
6using Json.Schema;
7
8using Microsoft.Teams.AI.Annotations;
9using Microsoft.Teams.AI.Messages;
10using Microsoft.Teams.Common.Extensions;
11using Microsoft.Teams.Common.Json;
12
13namespace Microsoft.Teams.AI;
14
15/// <summary>
16/// defines a block of code that
17/// can be called by a model
18/// </summary>
19[JsonConverter(typeof(TrueTypeJsonConverter<IFunction>))]
20public interface IFunction
21{
22 /// <summary>
23 /// the unique name
24 /// </summary>
25 public string Name { get; }
26
27 /// <summary>
28 /// a description of what the function
29 /// should be used for
30 /// </summary>
31 public string? Description { get; }
32
33 /// <summary>
34 /// the Json Schema representing what
35 /// parameters the function accepts
36 /// </summary>
37 public JsonSchema? Parameters { get; }
38}
39
40/// <summary>
41/// defines a block of code that
42/// can be called by a model
43/// </summary>
44public class Function : IFunction
45{
46 [JsonPropertyName("name")]
47 [JsonPropertyOrder(0)]
48 public string Name { get; set; }
49
50 [JsonPropertyName("description")]
51 [JsonPropertyOrder(1)]
52 public string? Description { get; set; }
53
54 [JsonPropertyName("parameters")]
55 [JsonPropertyOrder(2)]
56 public JsonSchema? Parameters { get; set; }
57
58 [JsonIgnore]
59 public Delegate Handler { get; set; }
60
61 public Function(string name, string? description, Delegate handler)
62 {
63 Name = name;
64 Description = description;
65 Handler = handler;
66 }
67
68 public Function(string name, string? description, JsonSchema? parameters, Delegate handler)
69 {
70 Name = name;
71 Description = description;
72 Parameters = parameters;
73 Handler = handler;
74 }
75
76 internal Task<object?> Invoke(FunctionCall call)
77 {
78 if (call.Arguments is not null && Parameters is not null)
79 {
80 var valid = Parameters.Evaluate(JsonNode.Parse(call.Arguments), new() { EvaluateAs = SpecVersion.DraftNext });
81
82 if (!valid.IsValid)
83 {
84 Console.WriteLine(JsonSerializer.Serialize(valid));
85 throw new ArgumentException(
86 string.Join("\n", valid.Errors?.Select(e => $"{e.Key} => {e.Value}") ?? [])
87 );
88 }
89 }
90
91 var args = call.Parse() ?? new Dictionary<string, object?>();
92 var method = Handler.GetMethodInfo();
93 var parameters = method.GetParameters().Select(param =>
94 {
95 var name = param.GetCustomAttribute<ParamAttribute>()?.Name ?? param.Name ?? param.Position.ToString();
96 args.TryGetValue(name, out var value);
97
98 if (value is JsonElement element)
99 {
100 return element.Deserialize(param.ParameterType);
101 }
102
103 return value;
104 }).ToArray();
105
106 return method.InvokeAsync(Handler.Target, parameters);
107 }
108
109 public override string ToString()
110 {
111 return JsonSerializer.Serialize(this, new JsonSerializerOptions()
112 {
113 WriteIndented = true
114 });
115 }
116}