|
| 1 | +using Azure.AI.Projects; |
| 2 | +using Azure.Identity; |
| 3 | +using Microsoft.SemanticKernel; |
| 4 | +using Microsoft.SemanticKernel.Agents; |
| 5 | +using Microsoft.SemanticKernel.Agents.AzureAI; |
| 6 | +using Microsoft.SemanticKernel.Agents.Chat; |
| 7 | +using Microsoft.SemanticKernel.ChatCompletion; |
| 8 | +using Microsoft.SemanticKernel.PromptTemplates.Liquid; |
| 9 | +using Microsoft.SemanticKernel.Prompty; |
| 10 | + |
| 11 | +namespace SemanticKernel.Agents.Scenarios |
| 12 | +{ |
| 13 | + public class CreatorWriterScenario : BaseScenario |
| 14 | + { |
| 15 | + public override async Task InitializeScenarioAsync(bool useAzureOpenAI) |
| 16 | + { |
| 17 | + //AzureEventSourceListener listener = new AzureEventSourceListener( |
| 18 | + // (args, text) => Console.WriteLine(text), |
| 19 | + // level: System.Diagnostics.Tracing.EventLevel.Verbose); |
| 20 | + |
| 21 | + AIProjectClient client = new AIProjectClient("swedencentral.api.azureml.ms;bc06be43-f36c-449a-b690-4fea320f3e73;ai-agents;ai-agents-project", new DefaultAzureCredential(new DefaultAzureCredentialOptions |
| 22 | + { |
| 23 | + ExcludeVisualStudioCredential = true, |
| 24 | + ExcludeEnvironmentCredential = true, |
| 25 | + ExcludeManagedIdentityCredential = true |
| 26 | + })); |
| 27 | + var agentsClient = client.GetAgentsClient(); |
| 28 | + var agent = await agentsClient.GetAgentAsync("asst_XlORPWTtq4FSyMItEw2lbT2a"); |
| 29 | + |
| 30 | + string researcherAgentName = "ResearcherAgent"; |
| 31 | + |
| 32 | + AzureAIAgent researcherAgent = new(agent, agentsClient) |
| 33 | + { |
| 34 | + Name = researcherAgentName, |
| 35 | + Kernel = KernelCreator.CreateKernel(useAzureOpenAI) |
| 36 | + }; |
| 37 | + |
| 38 | + string writerAgentName = "WriterAgent"; |
| 39 | + string promptyTemplate = await File.ReadAllTextAsync("Prompts/writerAgent.prompty"); |
| 40 | + var promptTemplate = KernelFunctionPrompty.ToPromptTemplateConfig(promptyTemplate); |
| 41 | + |
| 42 | + ChatCompletionAgent writerAgent = new ChatCompletionAgent(promptTemplate, new LiquidPromptTemplateFactory()) |
| 43 | + { |
| 44 | + Name = writerAgentName, |
| 45 | + Kernel = KernelCreator.CreateKernel(useAzureOpenAI) |
| 46 | + }; |
| 47 | + |
| 48 | + string reviewerAgentName = "WriterFeedback"; |
| 49 | + string reviewerAgentInstructions = """ |
| 50 | + You are an expert agent specialized in reviewing and providing detailed feedback on texts. Your task is to carefully analyze the provided text and offer actionable suggestions to enhance its quality and effectiveness. |
| 51 | +
|
| 52 | + When providing feedback, always clearly address the following points: |
| 53 | +
|
| 54 | + 1) Clarity and Readability: |
| 55 | + - Evaluate if the ideas and explanations are clearly presented and easily understandable. |
| 56 | + - Suggest ways to simplify complex or unclear sentences. |
| 57 | +
|
| 58 | + 2) Grammar and Style: |
| 59 | + - Identify and correct grammatical, spelling, or punctuation errors. |
| 60 | + - Suggest improvements in sentence structure and overall writing style to enhance readability. |
| 61 | + - Terminology and Accuracy: |
| 62 | +
|
| 63 | + Ensure the text correctly uses terminology appropriate to the topic. |
| 64 | +
|
| 65 | + Provide corrections or suggest better terminology choices if inaccuracies or inconsistencies are found. |
| 66 | +
|
| 67 | + Present your feedback clearly, organizing your suggestions into the three points listed above. Include examples from the original text where relevant, and suggest revised formulations when providing corrections. |
| 68 | +
|
| 69 | + Once you have provided the feedback, you must approve the work saying "I approve". |
| 70 | + """; |
| 71 | + |
| 72 | + ChatCompletionAgent reviewerAgent = new ChatCompletionAgent |
| 73 | + { |
| 74 | + Name = reviewerAgentName, |
| 75 | + Instructions = reviewerAgentInstructions, |
| 76 | + Kernel = KernelCreator.CreateKernel(useAzureOpenAI) |
| 77 | + }; |
| 78 | + |
| 79 | + KernelFunction selectionFunction = |
| 80 | + AgentGroupChat.CreatePromptFunctionForStrategy( |
| 81 | + $$$""" |
| 82 | + Determine which participant takes the next turn in a conversation based on the the most recent participant. |
| 83 | + State only the name of the participant to take the next turn. |
| 84 | + No participant should take more than one turn in a row. |
| 85 | +
|
| 86 | + Choose only from these participants: |
| 87 | + - {{{researcherAgentName}}} |
| 88 | + - {{{writerAgentName}}} |
| 89 | + - {{{reviewerAgentName}}} |
| 90 | +
|
| 91 | + Always follow these rules when selecting the next participant: |
| 92 | + - The user will share a topic to research |
| 93 | + - After the user, it's {{{researcherAgentName}}}'s turn to research the given topic. |
| 94 | + - After {{{researcherAgentName}}}, it is {{{writerAgentName}}}'s turn to write the text. |
| 95 | + - After {{{writerAgentName}}}, it is {{{reviewerAgentName}}}'s turn to review the text. |
| 96 | +
|
| 97 | + History: |
| 98 | + {{$history}} |
| 99 | + """, |
| 100 | + safeParameterNames: "history"); |
| 101 | + |
| 102 | + // Define the selection strategy |
| 103 | + KernelFunctionSelectionStrategy selectionStrategy = |
| 104 | + new(selectionFunction, KernelCreator.CreateKernel(useAzureOpenAI)) |
| 105 | + { |
| 106 | + // Always start with the writer agent. |
| 107 | + InitialAgent = researcherAgent, |
| 108 | + // Parse the function response. |
| 109 | + ResultParser = (result) => result.GetValue<string>() ?? researcherAgentName, |
| 110 | + // The prompt variable name for the history argument. |
| 111 | + HistoryVariableName = "history", |
| 112 | + // Save tokens by not including the entire history in the prompt |
| 113 | + HistoryReducer = new ChatHistoryTruncationReducer(3), |
| 114 | + }; |
| 115 | + |
| 116 | + KernelFunction terminationFunction = |
| 117 | + AgentGroupChat.CreatePromptFunctionForStrategy( |
| 118 | + $$$""" |
| 119 | + Determine if the reviewer has approved. If so, respond with a single word: yes |
| 120 | +
|
| 121 | + History: |
| 122 | + {{$history}} |
| 123 | + """, |
| 124 | + safeParameterNames: "history"); |
| 125 | + |
| 126 | + // Define the termination strategy |
| 127 | + KernelFunctionTerminationStrategy terminationStrategy = |
| 128 | + new(terminationFunction, KernelCreator.CreateKernel(useAzureOpenAI)) |
| 129 | + { |
| 130 | + // Only the reviewer may give approval. |
| 131 | + Agents = [reviewerAgent], |
| 132 | + // Parse the function response. |
| 133 | + ResultParser = (result) => |
| 134 | + result.GetValue<string>()?.Contains("yes", StringComparison.OrdinalIgnoreCase) ?? false, |
| 135 | + // The prompt variable name for the history argument. |
| 136 | + HistoryVariableName = "history", |
| 137 | + // Save tokens by not including the entire history in the prompt |
| 138 | + HistoryReducer = new ChatHistoryTruncationReducer(1), |
| 139 | + // Limit total number of turns no matter what |
| 140 | + MaximumIterations = 10, |
| 141 | + }; |
| 142 | + |
| 143 | + chat = new(researcherAgent, writerAgent, reviewerAgent) |
| 144 | + { |
| 145 | + ExecutionSettings = new() |
| 146 | + { |
| 147 | + SelectionStrategy = selectionStrategy, |
| 148 | + TerminationStrategy = terminationStrategy |
| 149 | + } |
| 150 | + }; |
| 151 | + } |
| 152 | + } |
| 153 | +} |
0 commit comments