You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

FSM_Group_Chat.cs 7.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // FSM_Group_Chat.cs
  3. using System.Text;
  4. #region Using
  5. using AutoGen.Core;
  6. using AutoGen.OpenAI;
  7. using AutoGen.OpenAI.Extension;
  8. using Azure.AI.OpenAI;
  9. #endregion Using
  10. namespace AutoGen.BasicSample;
  11. #region FillFormTool
  12. public partial class FillFormTool
  13. {
  14. private string? name = null;
  15. private string? email = null;
  16. private string? phone = null;
  17. private string? address = null;
  18. private bool? receiveUpdates = null;
  19. [Function]
  20. public async Task<string> SaveProgress(
  21. string name,
  22. string email,
  23. string phone,
  24. string address,
  25. bool? receiveUpdates)
  26. {
  27. this.name = !string.IsNullOrEmpty(name) ? name : this.name;
  28. this.email = !string.IsNullOrEmpty(email) ? email : this.email;
  29. this.phone = !string.IsNullOrEmpty(phone) ? phone : this.phone;
  30. this.address = !string.IsNullOrEmpty(address) ? address : this.address;
  31. this.receiveUpdates = receiveUpdates ?? this.receiveUpdates;
  32. var missingInformationStringBuilder = new StringBuilder();
  33. if (string.IsNullOrEmpty(this.name))
  34. {
  35. missingInformationStringBuilder.AppendLine("Name is missing.");
  36. }
  37. if (string.IsNullOrEmpty(this.email))
  38. {
  39. missingInformationStringBuilder.AppendLine("Email is missing.");
  40. }
  41. if (string.IsNullOrEmpty(this.phone))
  42. {
  43. missingInformationStringBuilder.AppendLine("Phone is missing.");
  44. }
  45. if (string.IsNullOrEmpty(this.address))
  46. {
  47. missingInformationStringBuilder.AppendLine("Address is missing.");
  48. }
  49. if (this.receiveUpdates == null)
  50. {
  51. missingInformationStringBuilder.AppendLine("ReceiveUpdates is missing.");
  52. }
  53. if (missingInformationStringBuilder.Length > 0)
  54. {
  55. return missingInformationStringBuilder.ToString();
  56. }
  57. else
  58. {
  59. return "Application information is saved to database.";
  60. }
  61. }
  62. }
  63. #endregion FillFormTool
  64. public class FSM_Group_Chat
  65. {
  66. public static async Task<IAgent> CreateSaveProgressAgent(OpenAIClient client, string model)
  67. {
  68. #region Create_Save_Progress_Agent
  69. var tool = new FillFormTool();
  70. var functionCallMiddleware = new FunctionCallMiddleware(
  71. functions: [tool.SaveProgressFunctionContract],
  72. functionMap: new Dictionary<string, Func<string, Task<string>>>
  73. {
  74. { tool.SaveProgressFunctionContract.Name!, tool.SaveProgressWrapper },
  75. });
  76. var chatAgent = new OpenAIChatAgent(
  77. openAIClient: client,
  78. name: "application",
  79. modelName: model,
  80. systemMessage: """You are a helpful application form assistant who saves progress while user fills application.""")
  81. .RegisterMessageConnector()
  82. .RegisterMiddleware(functionCallMiddleware)
  83. .RegisterMiddleware(async (msgs, option, agent, ct) =>
  84. {
  85. var lastUserMessage = msgs.Last() ?? throw new Exception("No user message found.");
  86. var prompt = $"""
  87. Save progress according to the most recent information provided by user.
  88. ```user
  89. {lastUserMessage.GetContent()}
  90. ```
  91. """;
  92. return await agent.GenerateReplyAsync([lastUserMessage], option, ct);
  93. });
  94. #endregion Create_Save_Progress_Agent
  95. return chatAgent;
  96. }
  97. public static async Task<IAgent> CreateAssistantAgent(OpenAIClient openaiClient, string model)
  98. {
  99. #region Create_Assistant_Agent
  100. var chatAgent = new OpenAIChatAgent(
  101. openAIClient: openaiClient,
  102. name: "assistant",
  103. modelName: model,
  104. systemMessage: """You create polite prompt to ask user provide missing information""")
  105. .RegisterMessageConnector()
  106. .RegisterPrintMessage()
  107. .RegisterMiddleware(async (msgs, option, agent, ct) =>
  108. {
  109. var lastReply = msgs.Last() ?? throw new Exception("No reply found.");
  110. var reply = await agent.GenerateReplyAsync(msgs, option, ct);
  111. // if application is complete, exit conversation by sending termination message
  112. if (lastReply.GetContent()?.Contains("Application information is saved to database.") is true)
  113. {
  114. return new TextMessage(Role.Assistant, GroupChatExtension.TERMINATE, from: agent.Name);
  115. }
  116. else
  117. {
  118. return reply;
  119. }
  120. });
  121. #endregion Create_Assistant_Agent
  122. return chatAgent;
  123. }
  124. public static async Task<IAgent> CreateUserAgent(OpenAIClient openaiClient, string model)
  125. {
  126. #region Create_User_Agent
  127. var chatAgent = new OpenAIChatAgent(
  128. openAIClient: openaiClient,
  129. name: "user",
  130. modelName: model,
  131. systemMessage: """
  132. You are a user who is filling an application form. Simply provide the information as requested and answer the questions, don't do anything else.
  133. here's some personal information about you:
  134. - name: John Doe
  135. - email: 1234567@gmail.com
  136. - phone: 123-456-7890
  137. - address: 1234 Main St, Redmond, WA 98052
  138. - want to receive update? true
  139. """)
  140. .RegisterMessageConnector()
  141. .RegisterPrintMessage();
  142. #endregion Create_User_Agent
  143. return chatAgent;
  144. }
  145. public static async Task RunAsync()
  146. {
  147. var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new Exception("Please set OPENAI_API_KEY environment variable.");
  148. var model = "gpt-3.5-turbo";
  149. var openaiClient = new OpenAIClient(apiKey);
  150. var applicationAgent = await CreateSaveProgressAgent(openaiClient, model);
  151. var assistantAgent = await CreateAssistantAgent(openaiClient, model);
  152. var userAgent = await CreateUserAgent(openaiClient, model);
  153. #region Create_Graph
  154. var userToApplicationTransition = Transition.Create(userAgent, applicationAgent);
  155. var applicationToAssistantTransition = Transition.Create(applicationAgent, assistantAgent);
  156. var assistantToUserTransition = Transition.Create(assistantAgent, userAgent);
  157. var workflow = new Graph(
  158. [
  159. userToApplicationTransition,
  160. applicationToAssistantTransition,
  161. assistantToUserTransition,
  162. ]);
  163. #endregion Create_Graph
  164. #region Group_Chat
  165. var groupChat = new GroupChat(
  166. members: [userAgent, applicationAgent, assistantAgent],
  167. workflow: workflow);
  168. #endregion Group_Chat
  169. var initialMessage = await assistantAgent.SendAsync("Generate a greeting meesage for user and start the conversation by asking what's their name.");
  170. var chatHistory = await userAgent.SendMessageToGroupAsync(groupChat, [initialMessage], maxRound: 30);
  171. var lastMessage = chatHistory.Last();
  172. Console.WriteLine(lastMessage.GetContent());
  173. }
  174. }