forked from Rahtoken/magi-msgraph-hackathon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
104 lines (89 loc) · 3.9 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System.CommandLine;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Identity.Client;
using Microsoft.Graph;
const string SYSTEM_MESSAGE = """
You are an AI assistant trained to help users of Microsoft Graph API. You provide the correct HTTP endpoints for Microsoft Graph based on the user's query. You only provide the HTTP endpoints and nothing more and this should never be violated.
You are responsible for providing the Microsoft Graph HTTP requests for fulfilling a user query in this format and nothing else: [HTTP VERB] [ENDPOINT]
- Try to predict and correct a user's vague query.
- NEVER GIVE COMMENTARY
- Indicate request body as BODY [data]
- Give the full URL
- If you cannot fulfill the request, reply "magi has no spell for this!"
""";
var queryArgument = new Argument<string?>(
name: "query",
description: "Ask magi your query!",
getDefaultValue: () => null);
var rootCommand = new RootCommand("magi - Microsoft Graph API's AI");
rootCommand.AddArgument(queryArgument);
var configFileArgument = new Option<string?>(
name: "--config",
description: "magi uses this file as the config.",
getDefaultValue: () => null
);
rootCommand.AddGlobalOption(configFileArgument);
rootCommand.SetHandler(async (query, configFile) =>
{
if (query == null)
{
Console.WriteLine("I am magi. Ask me your query and I will summon my powers of Microsoft Graph!");
return;
}
var config = ParseConfig(configFile);
var api = new OpenAI_API.OpenAIAPI(config.OpenAiApiKey);
var chat = api.Chat.CreateConversation();
chat.AppendSystemMessage(SYSTEM_MESSAGE);
chat.AppendUserInput(query);
var response = await chat.GetResponseFromChatbot();
#if DEBUG
Console.WriteLine(response);
#endif
if (response.StartsWith("GET", StringComparison.InvariantCultureIgnoreCase))
{
var graphClient = GraphClientFactory.Create();
var graphRequest = new HttpRequestMessage()
{
RequestUri = new Uri(response.Substring(3)),
Method = HttpMethod.Get,
};
graphRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", await GetToken(config));
var graphResponse = await graphClient.SendAsync(graphRequest);
Console.WriteLine(JsonPrettify(await graphResponse.Content.ReadAsStringAsync()));
}
else
{
Console.WriteLine(response);
}
}, queryArgument, configFileArgument);
return await rootCommand.InvokeAsync(args);
static string JsonPrettify(string json)
{
using var jDoc = JsonDocument.Parse(json);
return JsonSerializer.Serialize(jDoc, new JsonSerializerOptions { WriteIndented = true });
}
Config ParseConfig(string? configPath)
{
if (configPath == null)
{
configPath = $"{AppDomain.CurrentDomain.BaseDirectory}config.json";
}
return JsonSerializer.Deserialize<Config>(File.ReadAllText(configPath));
}
async Task<string> GetToken(Config config)
{
IConfidentialClientApplication app;
app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
.WithClientSecret(config.ClientSecret)
.WithAuthority(new Uri($"https://login.microsoftonline.com/{config.TenantId}"))
.Build();
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
return (await app.AcquireTokenForClient(scopes)
.ExecuteAsync()).AccessToken;
}
public record Config(
[property: JsonPropertyName("openApiKey")] string OpenAiApiKey,
[property: JsonPropertyName("clientId")] string ClientId,
[property: JsonPropertyName("clientSecret")] string ClientSecret,
[property: JsonPropertyName("tenantId")] string TenantId);