forked from microsoft/Generative-AI-for-beginners-dotnet
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
133 lines (109 loc) · 5.22 KB
/
Copy pathProgram.cs
File metadata and controls
133 lines (109 loc) · 5.22 KB
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using MAF_BackgroundResponses_01_Simple;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI;
using System.Text.Json;
// Persisting Conversation — Menu Sample
//1) Provides an interactive menu to create, resume, and persist AgentThreads.
//2) Demonstrates running questions on new threads or resumed threads and persisting state between runs.
//3) Centralizes console I/O and printing helpers to make the sample easier to extend.
// More information: https://learn.microsoft.com/en-us/agent-framework/tutorials/agents/persisted-conversation?pivots=programming-language-csharp
await BackgroundResponsesDemo.RunAsync();
internal static class BackgroundResponsesDemo
{
private static readonly string SavedThreadFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "agent_thread.json");
public static async Task RunAsync()
{
// get chat response client
var client = ChatClientProvider.GetChatClient();
// create a simple agent with basic instructions
var agent = client.AsAIAgent(
name: "agent",
instructions: "You are a helpful assistant");
while (true)
{
PersistingUI.Clear();
StreamConsoleHelper.PrintHeader("MAF - Background Responses (Persisting Demo)");
PersistingUI.PrintMenu();
var sel = PersistingUI.ReadSelection();
if (sel == "0") break;
switch (sel)
{
case "1":
await OptionStartNewThread(agent);
break;
case "2":
await OptionSimpleSession(agent);
break;
case "3":
await OptionLoadAndContinue(agent);
break;
default:
PersistingUI.PrintMessage("Invalid selection. Press any key to continue...");
PersistingUI.WaitForKey();
break;
}
}
}
private static async Task OptionStartNewThread(AIAgent agent)
{
// create a brand new thread, pass it to the unified handler, persist after
var thread = await agent.CreateSessionAsync();
await RunQuestionWithThread(agent, thread, persistAfter: true);
PersistingUI.PrintMessage(string.Empty);
PersistingUI.PrintMessage("[press a key to go back to main menu]");
PersistingUI.WaitForKey();
}
private static async Task OptionSimpleSession(AIAgent agent)
{
// create a temporary thread, do not persist after
var tempThread = await agent.CreateSessionAsync();
await RunQuestionWithThread(agent, tempThread, persistAfter: false);
PersistingUI.PrintMessage(string.Empty);
PersistingUI.PrintMessage("[press a key to go back to main menu]");
PersistingUI.WaitForKey();
}
private static async Task OptionLoadAndContinue(AIAgent agent)
{
if (!File.Exists(SavedThreadFilePath))
{
StreamConsoleHelper.PrintError($"No saved thread found at: {SavedThreadFilePath}");
PersistingUI.PrintMessage("[press a key to go back to main menu]");
PersistingUI.WaitForKey();
return;
}
var loadedJson = await File.ReadAllTextAsync(SavedThreadFilePath);
JsonElement reloaded = JsonSerializer.Deserialize<JsonElement>(loadedJson, JsonSerializerOptions.Web);
// Rehydrate the thread for this agent
var resumedThread = await agent.DeserializeSessionAsync(reloaded, JsonSerializerOptions.Web);
// Use the unified handler and persist after execution
await RunQuestionWithThread(agent, resumedThread, persistAfter: true);
PersistingUI.PrintMessage(string.Empty);
PersistingUI.PrintMessage("[press a key to go back to main menu]");
PersistingUI.WaitForKey();
}
/// <summary>
/// Unified interaction function: prompts the user for a question, runs the agent using the provided thread,
/// prints the response using StreamConsoleHelper, and optionally persists the thread to disk.
/// The function returns the (possibly updated) AgentSession so callers can continue working with it.
/// </summary>
private static async Task<AgentSession> RunQuestionWithThread(AIAgent agent, AgentSession thread, bool persistAfter)
{
var question = PersistingUI.PromptInput("Enter your question: ");
StreamConsoleHelper.PrintSection("Start answering your question");
StreamConsoleHelper.StartAccumulatedStream();
// Use the RunAsync convenience method to get a single response object tied to the thread
var response = await agent.RunAsync(question, thread);
// Print assembled text from the response
StreamConsoleHelper.AccumulateAndPrint(response.Text);
StreamConsoleHelper.FlushAccumulated();
if (persistAfter)
{
// Serialize thread state and write to file
var threadRaw = (await agent.SerializeSessionAsync(thread, JsonSerializerOptions.Web)).GetRawText();
await File.WriteAllTextAsync(SavedThreadFilePath, threadRaw);
StreamConsoleHelper.PrintLabeled("Saved thread to", SavedThreadFilePath);
}
return thread;
}
}