chore: import upstream snapshot with attribution
This commit is contained in:
+26
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA1812;CA2007;RCS1102;VSTHRD111;VSTHRD200</NoWarn>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Orchestration\Agents.Orchestration.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Runtime\InProcess\Runtime.InProcess.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration.Concurrent;
|
||||
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
var agentInstructions = "You are a translation assistant who only responds in {0}. Respond to any input by outputting the name of the input language and then translating the input to {0}.";
|
||||
|
||||
// This sample compares running concurrent orchestrations using
|
||||
// Semantic Kernel and the Agent Framework.
|
||||
Console.WriteLine("=== Semantic Kernel Concurrent Orchestration ===");
|
||||
await SKConcurrentOrchestration();
|
||||
|
||||
Console.WriteLine("\n=== Agent Framework Concurrent Agent Workflow ===");
|
||||
await AFConcurrentAgentWorkflow();
|
||||
|
||||
# region SKConcurrentOrchestration
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
async Task SKConcurrentOrchestration()
|
||||
{
|
||||
ConcurrentOrchestration orchestration = new([
|
||||
GetSKTranslationAgent("French"),
|
||||
GetSKTranslationAgent("Spanish")])
|
||||
{
|
||||
StreamingResponseCallback = StreamingResultCallback,
|
||||
};
|
||||
|
||||
InProcessRuntime runtime = new();
|
||||
await runtime.StartAsync();
|
||||
|
||||
// Run the orchestration
|
||||
OrchestrationResult<string[]> result = await orchestration.InvokeAsync("Hello, world!", runtime);
|
||||
string[] texts = await result.GetValueAsync(TimeSpan.FromSeconds(20));
|
||||
|
||||
await runtime.RunUntilIdleAsync();
|
||||
}
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
ChatCompletionAgent GetSKTranslationAgent(string targetLanguage)
|
||||
{
|
||||
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(deploymentName, endpoint, new AzureCliCredential()).Build();
|
||||
return new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = kernel,
|
||||
Instructions = string.Format(agentInstructions, targetLanguage),
|
||||
Description = $"Agent that translates texts to {targetLanguage}",
|
||||
Name = $"SKTranslationAgent_{targetLanguage}"
|
||||
};
|
||||
}
|
||||
|
||||
ValueTask StreamingResultCallback(StreamingChatMessageContent streamedResponse, bool isFinal)
|
||||
{
|
||||
Console.Write(streamedResponse.Content);
|
||||
|
||||
if (isFinal)
|
||||
{
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
# endregion
|
||||
|
||||
# region AFConcurrentAgentWorkflow
|
||||
async Task AFConcurrentAgentWorkflow()
|
||||
{
|
||||
var client = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
|
||||
var frenchAgent = GetAFTranslationAgent("French", client);
|
||||
var spanishAgent = GetAFTranslationAgent("Spanish", client);
|
||||
var concurrentAgentWorkflow = AgentWorkflowBuilder.BuildConcurrent([frenchAgent, spanishAgent]);
|
||||
|
||||
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(concurrentAgentWorkflow, "Hello, world!");
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
string? lastExecutorId = null;
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.ExecutorId != lastExecutorId)
|
||||
{
|
||||
lastExecutorId = e.ExecutorId;
|
||||
Console.WriteLine();
|
||||
Console.Write($"{e.Update.AuthorName}: ");
|
||||
}
|
||||
|
||||
Console.Write(e.Update.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChatClientAgent GetAFTranslationAgent(string targetLanguage, IChatClient chatClient) =>
|
||||
new(chatClient, string.Format(agentInstructions, targetLanguage), name: $"AFTranslationAgent_{targetLanguage}");
|
||||
# endregion
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA1812;CA2007;RCS1102;VSTHRD111;VSTHRD200</NoWarn>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Orchestration\Agents.Orchestration.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Runtime\InProcess\Runtime.InProcess.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration.Sequential;
|
||||
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
var agentInstructions = "You are a translation assistant who only responds in {0}. Respond to any input by outputting the name of the input language and then translating the input to {0}.";
|
||||
|
||||
// This sample compares running sequential orchestrations using
|
||||
// Semantic Kernel and the Agent Framework.
|
||||
Console.WriteLine("=== Semantic Kernel Sequential Orchestration ===");
|
||||
await SKSequentialOrchestration();
|
||||
|
||||
Console.WriteLine("\n=== Agent Framework Sequential Agent Workflow ===");
|
||||
await AFSequentialAgentWorkflow();
|
||||
|
||||
# region SKSequentialOrchestration
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
async Task SKSequentialOrchestration()
|
||||
{
|
||||
SequentialOrchestration orchestration = new([
|
||||
GetSKTranslationAgent("French"),
|
||||
GetSKTranslationAgent("Spanish"),
|
||||
GetSKTranslationAgent("English")])
|
||||
{
|
||||
StreamingResponseCallback = StreamingResultCallback,
|
||||
};
|
||||
|
||||
InProcessRuntime runtime = new();
|
||||
await runtime.StartAsync();
|
||||
|
||||
// Run the orchestration
|
||||
OrchestrationResult<string> result = await orchestration.InvokeAsync("Hello, world!", runtime);
|
||||
string text = await result.GetValueAsync(TimeSpan.FromSeconds(20));
|
||||
|
||||
await runtime.RunUntilIdleAsync();
|
||||
}
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
ChatCompletionAgent GetSKTranslationAgent(string targetLanguage)
|
||||
{
|
||||
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(deploymentName, endpoint, new AzureCliCredential()).Build();
|
||||
return new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = kernel,
|
||||
Instructions = string.Format(agentInstructions, targetLanguage),
|
||||
Description = $"Agent that translates texts to {targetLanguage}",
|
||||
Name = $"SKTranslationAgent_{targetLanguage}"
|
||||
};
|
||||
}
|
||||
|
||||
ValueTask StreamingResultCallback(StreamingChatMessageContent streamedResponse, bool isFinal)
|
||||
{
|
||||
Console.Write(streamedResponse.Content);
|
||||
|
||||
if (isFinal)
|
||||
{
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
# endregion
|
||||
|
||||
# region AFSequentialAgentWorkflow
|
||||
async Task AFSequentialAgentWorkflow()
|
||||
{
|
||||
var client = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
|
||||
var frenchAgent = GetAFTranslationAgent("French", client);
|
||||
var spanishAgent = GetAFTranslationAgent("Spanish", client);
|
||||
var englishAgent = GetAFTranslationAgent("English", client);
|
||||
var sequentialAgentWorkflow = AgentWorkflowBuilder.BuildSequential(
|
||||
[frenchAgent, spanishAgent, englishAgent]);
|
||||
|
||||
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(sequentialAgentWorkflow, "Hello, world!");
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
string? lastExecutorId = null;
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.ExecutorId != lastExecutorId)
|
||||
{
|
||||
lastExecutorId = e.ExecutorId;
|
||||
Console.WriteLine();
|
||||
Console.Write($"{e.Update.AuthorName}: ");
|
||||
}
|
||||
|
||||
Console.Write(e.Update.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChatClientAgent GetAFTranslationAgent(string targetLanguage, IChatClient chatClient) =>
|
||||
new(chatClient, string.Format(agentInstructions, targetLanguage), name: $"AFTranslationAgent_{targetLanguage}");
|
||||
# endregion
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA1812;CA2007;RCS1102;VSTHRD111;VSTHRD200</NoWarn>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Orchestration\Agents.Orchestration.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Runtime\InProcess\Runtime.InProcess.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,249 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
#pragma warning disable MAAIW001 // Experimental: HandoffWorkflowBuilder
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.Workflows;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration;
|
||||
using Microsoft.SemanticKernel.Agents.Orchestration.Handoff;
|
||||
using Microsoft.SemanticKernel.Agents.Runtime.InProcess;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// Queries to simulate user input during the interactive orchestration
|
||||
List<string> Queries = [
|
||||
"I'd like to track the status of my first order 123.",
|
||||
"I want to return another order of mine whose ID is 456 because it arrived damaged.",
|
||||
];
|
||||
|
||||
// This sample compares running handoff orchestrations using
|
||||
// Semantic Kernel and the Agent Framework.
|
||||
Console.WriteLine("=== Semantic Kernel Handoff Orchestration ===");
|
||||
// State to help format the streaming output
|
||||
bool newAgentTurn = true;
|
||||
string previousFunctionCallId = string.Empty;
|
||||
await SKHandoffOrchestration();
|
||||
|
||||
Console.WriteLine("\n=== Agent Framework Handoff Agent Workflow ===");
|
||||
await AFHandoffAgentWorkflow();
|
||||
|
||||
# region SKHandoffOrchestration
|
||||
[KernelFunction]
|
||||
string SKCheckOrderStatus(string orderId) => $"Order {orderId} is shipped and will arrive in 2-3 days.";
|
||||
|
||||
[KernelFunction]
|
||||
string SKProcessReturn(string orderId, string reason) => $"Return for order {orderId} has been processed successfully.";
|
||||
|
||||
[KernelFunction]
|
||||
string SKProcessRefund(string orderId, string reason) => $"Refund for order {orderId} has been processed successfully.";
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
async Task SKHandoffOrchestration()
|
||||
{
|
||||
// Create agents
|
||||
var triageAgent = GetSKAgent(
|
||||
instructions: "You are a customer support agent that triages issues.",
|
||||
name: "TriageAgent",
|
||||
description: "Handle customer requests.");
|
||||
var statusAgent = GetSKAgent(
|
||||
instructions: "You are a customer support agent that checks order status.",
|
||||
name: "OrderStatusAgent",
|
||||
description: "Handle order status requests.");
|
||||
statusAgent.Kernel.Plugins.AddFromFunctions("OrderStatusPlugin", [KernelFunctionFactory.CreateFromMethod(SKCheckOrderStatus)]);
|
||||
var returnAgent = GetSKAgent(
|
||||
instructions: "You are a customer support agent that handles order returns.",
|
||||
name: "OrderReturnAgent",
|
||||
description: "Handle order return requests.");
|
||||
returnAgent.Kernel.Plugins.AddFromFunctions("OrderReturnPlugin", [KernelFunctionFactory.CreateFromMethod(SKProcessReturn)]);
|
||||
var refundAgent = GetSKAgent(
|
||||
instructions: "You are a customer support agent that handles order refunds.",
|
||||
name: "OrderRefundAgent",
|
||||
description: "Handle order refund requests.");
|
||||
refundAgent.Kernel.Plugins.AddFromFunctions("OrderRefundPlugin", [KernelFunctionFactory.CreateFromMethod(SKProcessRefund)]);
|
||||
|
||||
Queue<string> queries = new(Queries);
|
||||
|
||||
// Create orchestration with handoffs
|
||||
HandoffOrchestration orchestration =
|
||||
new(OrchestrationHandoffs
|
||||
.StartWith(triageAgent)
|
||||
.Add(triageAgent, statusAgent, returnAgent, refundAgent)
|
||||
.Add(statusAgent, triageAgent, "Transfer to this agent if the issue is not status related")
|
||||
.Add(returnAgent, triageAgent, "Transfer to this agent if the issue is not return related")
|
||||
.Add(refundAgent, triageAgent, "Transfer to this agent if the issue is not refund related"),
|
||||
triageAgent,
|
||||
statusAgent,
|
||||
returnAgent,
|
||||
refundAgent)
|
||||
{
|
||||
InteractiveCallback = () =>
|
||||
{
|
||||
string input = queries.Count > 0 ? queries.Dequeue() : "exit";
|
||||
Console.WriteLine($"\nUser: {input}");
|
||||
return ValueTask.FromResult(new ChatMessageContent(AuthorRole.User, input));
|
||||
},
|
||||
StreamingResponseCallback = StreamingResultCallback,
|
||||
};
|
||||
|
||||
InProcessRuntime runtime = new();
|
||||
await runtime.StartAsync();
|
||||
|
||||
// Run the orchestration
|
||||
OrchestrationResult<string> result = await orchestration.InvokeAsync(
|
||||
"I am a customer that needs help with my two orders",
|
||||
runtime);
|
||||
string text = await result.GetValueAsync();
|
||||
Console.WriteLine($"\nFinal Result: {text}");
|
||||
|
||||
await runtime.RunUntilIdleAsync();
|
||||
}
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
ChatCompletionAgent GetSKAgent(string instructions, string name, string description)
|
||||
{
|
||||
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatCompletion(deploymentName, endpoint, new AzureCliCredential()).Build();
|
||||
return new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = kernel,
|
||||
Instructions = instructions,
|
||||
Description = description,
|
||||
Name = name
|
||||
};
|
||||
}
|
||||
|
||||
ValueTask StreamingResultCallback(StreamingChatMessageContent streamedResponse, bool isFinal)
|
||||
{
|
||||
if (newAgentTurn)
|
||||
{
|
||||
Console.Write($"\n{streamedResponse.AuthorName}: ");
|
||||
newAgentTurn = false;
|
||||
}
|
||||
Console.Write(streamedResponse.Content);
|
||||
|
||||
if (streamedResponse.Items.OfType<StreamingFunctionCallUpdateContent>().FirstOrDefault()
|
||||
is StreamingFunctionCallUpdateContent call)
|
||||
{
|
||||
if (call.CallId is not null && previousFunctionCallId != call.CallId)
|
||||
{
|
||||
Console.Write($"\nCalling function '{call.Name}' with arguments: ");
|
||||
previousFunctionCallId = call.CallId;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(call.Arguments))
|
||||
{
|
||||
Console.Write($"{call.Arguments}");
|
||||
}
|
||||
}
|
||||
|
||||
if (isFinal)
|
||||
{
|
||||
newAgentTurn = true;
|
||||
previousFunctionCallId = string.Empty;
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
return ValueTask.CompletedTask;
|
||||
}
|
||||
# endregion
|
||||
|
||||
# region AFHandoffAgentWorkflow
|
||||
[Description("Get the order status for a given order ID.")]
|
||||
static string AFCheckOrderStatus([Description("The order ID to check the status for.")] string orderId)
|
||||
=> $"Order {orderId} is shipped and will arrive in 2-3 days.";
|
||||
|
||||
[Description("Process a return for a given order ID.")]
|
||||
static string AFProcessReturn(
|
||||
[Description("The order ID to process the return for.")] string orderId,
|
||||
[Description("The reason for the return.")] string reason)
|
||||
=> $"Return for order {orderId} has been processed successfully for the following reason: {reason}.";
|
||||
|
||||
[Description("Process a refund for a given order ID.")]
|
||||
static string AFProcessRefund([Description("The order ID to process the refund for.")] string orderId)
|
||||
=> $"Refund for order {orderId} has been processed successfully.";
|
||||
|
||||
async Task AFHandoffAgentWorkflow()
|
||||
{
|
||||
// Create agents
|
||||
var client = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName).AsIChatClient();
|
||||
|
||||
ChatClientAgent triageAgent = new(client,
|
||||
instructions: "A customer support agent that triages issues.",
|
||||
name: "TriageAgent",
|
||||
description: "Handle customer requests.");
|
||||
ChatClientAgent statusAgent = new(client,
|
||||
name: "OrderStatusAgent",
|
||||
instructions: "Handle order status requests.",
|
||||
description: "A customer support agent that checks order status.",
|
||||
tools: [AIFunctionFactory.Create(AFCheckOrderStatus)]);
|
||||
ChatClientAgent returnAgent = new(client,
|
||||
name: "OrderReturnAgent",
|
||||
instructions: "Handle order return requests.",
|
||||
description: "A customer support agent that handles order returns.",
|
||||
tools: [AIFunctionFactory.Create(AFProcessReturn)]);
|
||||
ChatClientAgent refundAgent = new(client,
|
||||
name: "OrderRefundAgent",
|
||||
instructions: "Handle order refund requests.",
|
||||
description: "A customer support agent that handles order refund.",
|
||||
tools: [AIFunctionFactory.Create(AFProcessRefund)]);
|
||||
|
||||
// Create workflow with handoffs
|
||||
var handoffAgentWorkflow = AgentWorkflowBuilder.CreateHandoffBuilderWith(triageAgent)
|
||||
.WithHandoffs(triageAgent, [statusAgent, returnAgent, refundAgent])
|
||||
.WithHandoff(statusAgent, triageAgent, "Transfer to this agent if the issue is not status related")
|
||||
.WithHandoff(returnAgent, triageAgent, "Transfer to this agent if the issue is not return related")
|
||||
.WithHandoff(refundAgent, triageAgent, "Transfer to this agent if the issue is not refund related")
|
||||
.Build();
|
||||
|
||||
// Run the workflow
|
||||
List<ChatMessage> messages = [];
|
||||
foreach (var query in Queries)
|
||||
{
|
||||
Console.WriteLine($"User: {query}");
|
||||
messages.Add(new(ChatRole.User, query));
|
||||
|
||||
await using var run = await InProcessExecution.RunStreamingAsync(handoffAgentWorkflow, messages);
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
string? lastExecutorId = null;
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text) && e.Update.Contents.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.ExecutorId != lastExecutorId)
|
||||
{
|
||||
lastExecutorId = e.ExecutorId;
|
||||
Console.WriteLine();
|
||||
Console.Write($"{e.Update.AuthorName}: ");
|
||||
}
|
||||
|
||||
Console.Write(e.Update.Text);
|
||||
|
||||
if (e.Update.Contents.OfType<Microsoft.Extensions.AI.FunctionCallContent>().FirstOrDefault()
|
||||
is Microsoft.Extensions.AI.FunctionCallContent call)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine($"Calling function '{call.Name}' with arguments: {JsonSerializer.Serialize(call.Arguments)}");
|
||||
}
|
||||
}
|
||||
else if (evt is WorkflowOutputEvent output)
|
||||
{
|
||||
Console.WriteLine("\n");
|
||||
messages.AddRange(output.As<List<ChatMessage>>()!);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
# endregion
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA1812;CA2007;RCS1102;VSTHRD111</NoWarn>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,114 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var azureEndpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(
|
||||
deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
|
||||
AzureAIAgent agent = new(definition, azureAgentClient);
|
||||
|
||||
var thread = new AzureAIAgentThread(azureAgentClient);
|
||||
|
||||
AzureAIAgentInvokeOptions options = new() { MaxPromptTokens = 1000 };
|
||||
var result = await agent.InvokeAsync(userInput, thread, options).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (StreamingChatMessageContent update in agent.InvokeStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(
|
||||
deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
AzureAIAgent skAgent = new(definition, azureAgentClient);
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
// AF 1.0: Use AIProjectClient.AsAIAgent() from Microsoft.Agents.AI.Foundry
|
||||
var projectClient = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential());
|
||||
|
||||
var agent = projectClient.AsAIAgent(
|
||||
deploymentName,
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "GenerateStory");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,131 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var azureEndpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(deploymentName, instructions: "You are a helpful assistant");
|
||||
|
||||
AzureAIAgent agent = new(definition, azureAgentClient)
|
||||
{
|
||||
Kernel = Kernel.CreateBuilder().Build(),
|
||||
Name = "Host",
|
||||
Instructions = "You are a helpful assistant",
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
var thread = new AzureAIAgentThread(azureAgentClient);
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (ChatMessageContent update in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(deploymentName, instructions: "You are a helpful assistant");
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
AzureAIAgent skAgent = new(definition, azureAgentClient)
|
||||
{
|
||||
Kernel = Kernel.CreateBuilder().Build(),
|
||||
Name = "Host",
|
||||
Instructions = "You are a helpful assistant",
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { Tools = [AIFunctionFactory.Create(GetWeather)] });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential())
|
||||
.AsAIAgent(model: deploymentName,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var azureEndpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential()));
|
||||
serviceCollection.AddTransient<AzureAIAgent>((sp) =>
|
||||
{
|
||||
var azureAgentClient = sp.GetRequiredService<PersistentAgentsClient>();
|
||||
|
||||
Console.Write("Creating agent in the cloud...");
|
||||
|
||||
PersistentAgent definition = azureAgentClient.Administration
|
||||
.CreateAgent(deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
|
||||
Console.Write("Done\n");
|
||||
|
||||
return new(definition, azureAgentClient);
|
||||
});
|
||||
serviceCollection.AddKernel();
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AzureAIAgent>();
|
||||
|
||||
var thread = new AzureAIAgentThread(agent.Client);
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (ChatMessageContent update in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await agent.Client.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential()));
|
||||
serviceCollection.AddTransient<AzureAIAgent>((sp) =>
|
||||
{
|
||||
var azureAgentClient = sp.GetRequiredService<PersistentAgentsClient>();
|
||||
|
||||
Console.Write("Creating agent in the cloud...");
|
||||
|
||||
PersistentAgent definition = azureAgentClient.Administration
|
||||
.CreateAgent(deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
|
||||
Console.Write("Done\n");
|
||||
|
||||
return new(definition, azureAgentClient);
|
||||
});
|
||||
serviceCollection.AddKernel();
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var skAgent = serviceProvider.GetRequiredService<AzureAIAgent>();
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
var azureAgentClient = serviceProvider.GetRequiredService<PersistentAgentsClient>();
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential()));
|
||||
serviceCollection.AddTransient<AIAgent>((sp) =>
|
||||
{
|
||||
var client = sp.GetRequiredService<AIProjectClient>();
|
||||
return client.AsAIAgent(
|
||||
deploymentName,
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "GenerateStory");
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var azureEndpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Create a python code file using the code interpreter tool with a code ready to determine the values in the Fibonacci sequence that are less then the value of 101";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(deploymentName, tools: [new CodeInterpreterToolDefinition()]);
|
||||
|
||||
AzureAIAgent agent = new(definition, azureAgentClient);
|
||||
var thread = new AzureAIAgentThread(azureAgentClient);
|
||||
|
||||
// SK Azure AI Agent provides the code interpreter content and the assistant message as different contents in the call iteration.
|
||||
await foreach (var content in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(content.Message.Content))
|
||||
{
|
||||
bool isCode = content.Message.Metadata?.ContainsKey(AzureAIAgent.CodeInterpreterMetadataKey) ?? false;
|
||||
Console.WriteLine($"\n# {content.Message.Role}{(isCode ? "\n# Generated Code:\n" : ":")}{content.Message.Content}");
|
||||
}
|
||||
|
||||
// Check for the citations
|
||||
foreach (var item in content.Message.Items)
|
||||
{
|
||||
// Process each item in the message
|
||||
if (item is AnnotationContent annotation)
|
||||
{
|
||||
if (annotation.Kind != AnnotationKind.UrlCitation)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {annotation.Label}: File #{annotation.ReferenceId}");
|
||||
}
|
||||
}
|
||||
else if (item is FileReferenceContent fileReference)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] File #{fileReference.FileId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(deploymentName, tools: [new CodeInterpreterToolDefinition()]);
|
||||
|
||||
AzureAIAgent skAgent = new(definition, azureAgentClient);
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// Extracts via breaking glass the code generated by code interpreter tool
|
||||
var chatResponse = result.RawRepresentation as ChatResponse;
|
||||
StringBuilder generatedCode = new();
|
||||
foreach (object? updateRawRepresentation in chatResponse?.RawRepresentation as IEnumerable<object?> ?? [])
|
||||
{
|
||||
// To capture the code interpreter input we need to break glass all the updates raw representations, to check for the RunStepDetailsUpdate type and
|
||||
// get the CodeInterpreterInput property which contains the generated code.
|
||||
// Note: Similar logic would needed for each individual update if used in the agent.RunStreamingAsync streaming API to aggregate or yield the generated code.
|
||||
if (updateRawRepresentation is RunStepDetailsUpdate update && update.CodeInterpreterInput is not null)
|
||||
{
|
||||
generatedCode.Append(update.CodeInterpreterInput);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(generatedCode.ToString()))
|
||||
{
|
||||
Console.WriteLine($"\n# {chatResponse?.Messages[0].Role}:Generated Code:\n{generatedCode}");
|
||||
}
|
||||
|
||||
// Update the citations
|
||||
foreach (var textContent in result.Messages[0].Contents.OfType<Microsoft.Extensions.AI.TextContent>())
|
||||
{
|
||||
foreach (var annotation in textContent.Annotations ?? [])
|
||||
{
|
||||
if (annotation is CitationAnnotation citation)
|
||||
{
|
||||
if (citation.Url is null)
|
||||
{
|
||||
Console.WriteLine($" [{citation.GetType().Name}] {citation.Snippet}: File #{citation.FileId}");
|
||||
}
|
||||
|
||||
foreach (var region in citation.AnnotatedRegions ?? [])
|
||||
{
|
||||
if (region is TextSpanAnnotatedRegion textSpanRegion)
|
||||
{
|
||||
Console.WriteLine($"\n[TextSpan Region] {textSpanRegion.StartIndex}-{textSpanRegion.EndIndex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
// Note: Code interpreter via hosted APIs requires versioned Foundry Agents.
|
||||
// This sample creates a basic agent without code interpreter capabilities.
|
||||
var agent = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential())
|
||||
.AsAIAgent(deploymentName, instructions: "You are a helpful assistant with code execution capabilities.");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
var agent = new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
};
|
||||
|
||||
var thread = new ChatHistoryAgentThread();
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new AgentInvokeOptions() { KernelArguments = new(settings) };
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var agent = new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
}.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName)
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
ChatCompletionAgent agent = new()
|
||||
{
|
||||
Instructions = "You are a helpful assistant",
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Response ===\n");
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
ChatCompletionAgent agent = new()
|
||||
{
|
||||
Instructions = "You are a helpful assistant",
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var afAgent = agent.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var result = await afAgent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName)
|
||||
.AsAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
serviceCollection.AddTransient((sp) => new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = sp.GetRequiredService<Kernel>(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<ChatCompletionAgent>();
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
serviceCollection.AddTransient((sp) => new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = sp.GetRequiredService<Kernel>(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
}.AsAIAgent());
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new AzureOpenAIClient(new(endpoint), new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Functions\Functions.OpenApi\Functions.OpenApi.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="OpenAPISpec.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+354
@@ -0,0 +1,354 @@
|
||||
{
|
||||
"openapi": "3.0.1",
|
||||
"info": {
|
||||
"title": "Github Versions API",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://api.github.com"
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"schemas": {
|
||||
"basic-error": {
|
||||
"title": "Basic Error",
|
||||
"description": "Basic Error",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"documentation_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"label": {
|
||||
"title": "Label",
|
||||
"description": "Color-coded labels help you categorize and filter your issues (just like labels in Gmail).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "Unique identifier for the label.",
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"example": 208045946
|
||||
},
|
||||
"node_id": {
|
||||
"type": "string",
|
||||
"example": "MDU6TGFiZWwyMDgwNDU5NDY="
|
||||
},
|
||||
"url": {
|
||||
"description": "URL for the label",
|
||||
"example": "https://api.github.com/repositories/42/labels/bug",
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name of the label.",
|
||||
"example": "bug",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Optional description of the label, such as its purpose.",
|
||||
"type": "string",
|
||||
"example": "Something isn't working",
|
||||
"nullable": true
|
||||
},
|
||||
"color": {
|
||||
"description": "6-character hex code, without the leading #, identifying the color",
|
||||
"example": "FFFFFF",
|
||||
"type": "string"
|
||||
},
|
||||
"default": {
|
||||
"description": "Whether this label comes by default in a new repository.",
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"node_id",
|
||||
"url",
|
||||
"name",
|
||||
"description",
|
||||
"color",
|
||||
"default"
|
||||
]
|
||||
},
|
||||
"tag": {
|
||||
"title": "Tag",
|
||||
"description": "Tag",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "v0.1"
|
||||
},
|
||||
"commit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sha": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"sha",
|
||||
"url"
|
||||
]
|
||||
},
|
||||
"zipball_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"example": "https://github.com/octocat/Hello-World/zipball/v0.1"
|
||||
},
|
||||
"tarball_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"example": "https://github.com/octocat/Hello-World/tarball/v0.1"
|
||||
},
|
||||
"node_id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"node_id",
|
||||
"commit",
|
||||
"zipball_url",
|
||||
"tarball_url"
|
||||
]
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"label-items": {
|
||||
"value": [
|
||||
{
|
||||
"id": 208045946,
|
||||
"node_id": "MDU6TGFiZWwyMDgwNDU5NDY=",
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/labels/bug",
|
||||
"name": "bug",
|
||||
"description": "Something isn't working",
|
||||
"color": "f29513",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"id": 208045947,
|
||||
"node_id": "MDU6TGFiZWwyMDgwNDU5NDc=",
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/labels/enhancement",
|
||||
"name": "enhancement",
|
||||
"description": "New feature or request",
|
||||
"color": "a2eeef",
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"tag-items": {
|
||||
"value": [
|
||||
{
|
||||
"name": "v0.1",
|
||||
"commit": {
|
||||
"sha": "c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc",
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/commits/c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc"
|
||||
},
|
||||
"zipball_url": "https://github.com/octocat/Hello-World/zipball/v0.1",
|
||||
"tarball_url": "https://github.com/octocat/Hello-World/tarball/v0.1",
|
||||
"node_id": "MDQ6VXNlcjE="
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"parameters": {
|
||||
"owner": {
|
||||
"name": "owner",
|
||||
"description": "The account owner of the repository. The name is not case sensitive.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"repo": {
|
||||
"name": "repo",
|
||||
"description": "The name of the repository without the `.git` extension. The name is not case sensitive.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"per-page": {
|
||||
"name": "per_page",
|
||||
"description": "The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"default": 30
|
||||
}
|
||||
},
|
||||
"page": {
|
||||
"name": "page",
|
||||
"description": "The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"default": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"not_found": {
|
||||
"description": "Resource not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/basic-error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
"link": {
|
||||
"example": "<https://api.github.com/resource?page=2>; rel=\"next\", <https://api.github.com/resource?page=5>; rel=\"last\"",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/repos/{owner}/{repo}/tags": {
|
||||
"get": {
|
||||
"summary": "List repository tags",
|
||||
"description": "",
|
||||
"tags": [
|
||||
"repos"
|
||||
],
|
||||
"operationId": "repos/list-tags",
|
||||
"externalDocs": {
|
||||
"description": "API method documentation",
|
||||
"url": "https://docs.github.com/rest/repos/repos#list-repository-tags"
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/owner"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/repo"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/per-page"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/page"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/tag"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"default": {
|
||||
"$ref": "#/components/examples/tag-items"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
"Link": {
|
||||
"$ref": "#/components/headers/link"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-github": {
|
||||
"githubCloudOnly": false,
|
||||
"enabledForGitHubApps": true,
|
||||
"category": "repos",
|
||||
"subcategory": "repos"
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/labels": {
|
||||
"get": {
|
||||
"summary": "List labels for a repository",
|
||||
"description": "Lists all labels for a repository.",
|
||||
"tags": [
|
||||
"issues"
|
||||
],
|
||||
"operationId": "issues/list-labels-for-repo",
|
||||
"externalDocs": {
|
||||
"description": "API method documentation",
|
||||
"url": "https://docs.github.com/rest/issues/labels#list-labels-for-a-repository"
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/owner"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/repo"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/per-page"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/page"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/label"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"default": {
|
||||
"$ref": "#/components/examples/label-items"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
"Link": {
|
||||
"$ref": "#/components/headers/link"
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/not_found"
|
||||
}
|
||||
},
|
||||
"x-github": {
|
||||
"githubCloudOnly": false,
|
||||
"enabledForGitHubApps": true,
|
||||
"category": "issues",
|
||||
"subcategory": "labels"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample demonstrates how to use an Agent with function tools provided via an OpenAPI spec with both Semantic Kernel and Agent Framework.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Plugins.OpenApi;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
await SKAgent();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
// Create a kernel with an Azure OpenAI chat client.
|
||||
var kernel = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential()).Build();
|
||||
|
||||
// Load the OpenAPI Spec from a file.
|
||||
var plugin = await kernel.ImportPluginFromOpenApiAsync("github", "OpenAPISpec.json");
|
||||
|
||||
// Create the agent, and provide the kernel with the OpenAPI function tools to the agent.
|
||||
var agent = new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = kernel,
|
||||
Instructions = "You are a helpful assistant",
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Run the agent with the OpenAPI function tools.
|
||||
await foreach (var result in agent.InvokeAsync("Please list the names, colors and descriptions of all the labels available in the microsoft/agent-framework repository on github."))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
// Load the OpenAPI Spec from a file.
|
||||
KernelPlugin plugin = await OpenApiKernelPluginFactory.CreateFromOpenApiAsync("github", "OpenAPISpec.json");
|
||||
|
||||
// Convert the Semantic Kernel plugin to Agent Framework function tools.
|
||||
// This requires a dummy Kernel instance, since KernelFunctions cannot execute without one.
|
||||
Kernel kernel = new();
|
||||
List<AITool> tools = plugin.Select(x => x.WithKernel(kernel)).Cast<AITool>().ToList();
|
||||
|
||||
// Create the chat client and agent, and provide the OpenAPI function tools to the agent.
|
||||
AIAgent agent = new AzureOpenAIClient(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.AsAIAgent(instructions: "You are a helpful assistant", tools: tools);
|
||||
|
||||
// Run the agent with the OpenAPI function tools.
|
||||
Console.WriteLine(await agent.RunAsync("Please list the names, colors and descriptions of all the labels available in the microsoft/agent-framework repository on github."));
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var responseClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient();
|
||||
OpenAIResponseAgent agent = new(responseClient, deploymentName)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agentOptions = new OpenAIResponseAgentInvokeOptions() { ResponseCreationOptions = new() { MaxOutputTokenCount = 1000 } };
|
||||
|
||||
Microsoft.SemanticKernel.Agents.AgentThread? thread = null;
|
||||
await foreach (var item in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
Console.WriteLine(item.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var item in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
Console.Write(item.Message);
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var responseClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient();
|
||||
|
||||
OpenAIResponseAgent skAgent = new(responseClient, deploymentName)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "o4-mini";
|
||||
var userInput =
|
||||
"""
|
||||
Instructions:
|
||||
- Given the React component below, think about it and change it so that nonfiction books have red
|
||||
text.
|
||||
- Return only the code in your reply
|
||||
- Do not include any additional formatting, such as markdown code blocks
|
||||
- For formatting, use four space tabs, and do not allow any lines of code to
|
||||
exceed 80 columns
|
||||
const books = [
|
||||
{ title: 'Dune', category: 'fiction', id: 1 },
|
||||
{ title: 'Frankenstein', category: 'fiction', id: 2 },
|
||||
{ title: 'Moneyball', category: 'nonfiction', id: 3 },
|
||||
];
|
||||
export default function BookList() {
|
||||
const listItems = books.map(book =>
|
||||
<li>
|
||||
{book.title}
|
||||
</li>
|
||||
);
|
||||
return (
|
||||
<ul>{listItems}</ul>
|
||||
);
|
||||
}
|
||||
""";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var responseClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient();
|
||||
OpenAIResponseAgent agent = new(responseClient, deploymentName)
|
||||
{
|
||||
Name = "Thinker",
|
||||
Instructions = "You are good at thinking hard before answering.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agentOptions = new OpenAIResponseAgentInvokeOptions()
|
||||
{
|
||||
ResponseCreationOptions = new()
|
||||
{
|
||||
MaxOutputTokenCount = 8000,
|
||||
ReasoningOptions = new()
|
||||
{
|
||||
ReasoningEffortLevel = OpenAI.Responses.ResponseReasoningEffortLevel.High,
|
||||
ReasoningSummaryVerbosity = OpenAI.Responses.ResponseReasoningSummaryVerbosity.Detailed
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Microsoft.SemanticKernel.Agents.AgentThread? thread = null;
|
||||
await foreach (var item in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
foreach (var content in item.Message.Items)
|
||||
{
|
||||
if (content is ReasoningContent thinking)
|
||||
{
|
||||
Console.Write($"Thinking: \n{thinking}\n---\n");
|
||||
}
|
||||
else if (content is Microsoft.SemanticKernel.TextContent text)
|
||||
{
|
||||
Console.Write($"Assistant: {text}");
|
||||
}
|
||||
}
|
||||
Console.WriteLine(item.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
var userMessage = new ChatMessageContent(AuthorRole.User, userInput);
|
||||
await foreach (var item in agent.InvokeStreamingAsync(userMessage, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
foreach (var content in item.Message.Items)
|
||||
{
|
||||
// Currently SK Agent doesn't output thinking in streaming mode.
|
||||
// SK Issue: https://github.com/microsoft/semantic-kernel/issues/13046
|
||||
// OpenAI SDK Issue: https://github.com/openai/openai-dotnet/issues/643
|
||||
if (content is StreamingReasoningContent thinking)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{thinking}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (content is StreamingTextContent text)
|
||||
{
|
||||
Console.WriteLine($"Response: [{text}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var responseClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient();
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
OpenAIResponseAgent skAgent = new(responseClient, deploymentName)
|
||||
{
|
||||
Name = "Thinker",
|
||||
Instructions = "You are good at thinking hard before answering.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
Reasoning = new()
|
||||
{
|
||||
Effort = ReasoningEffort.High,
|
||||
Output = ReasoningOutput.Full
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
|
||||
// Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists.
|
||||
string assistantThinking = string.Join("\n", result.Messages
|
||||
.SelectMany(m => m.Contents)
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text));
|
||||
|
||||
var assistantText = result.Text;
|
||||
Console.WriteLine($"Thinking: \n{assistantThinking}\n---\n");
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text)
|
||||
.ToList();
|
||||
|
||||
if (thinkingContents.Count != 0)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{string.Join("\n", thinkingContents)}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Response: [{update.Text}]");
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Thinker", instructions: "You are good at thinking hard before answering.");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
Reasoning = new()
|
||||
{
|
||||
Effort = ReasoningEffort.High,
|
||||
Output = ReasoningOutput.Full
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
|
||||
// Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists.
|
||||
string assistantThinking = string.Join("\n", result.Messages
|
||||
.SelectMany(m => m.Contents)
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text));
|
||||
|
||||
var assistantText = result.Text;
|
||||
Console.WriteLine($"Thinking: \n{assistantThinking}\n---\n");
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text)
|
||||
.ToList();
|
||||
|
||||
if (thinkingContents.Count != 0)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{string.Join("\n", thinkingContents)}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Response: [{update.Text}]");
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
OpenAIResponseAgent agent = new(new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient(), deploymentName)
|
||||
{ StoreEnabled = true };
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Response ===\n");
|
||||
|
||||
await foreach (ChatMessageContent responseItem in agent.InvokeAsync(userInput))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(responseItem.Content))
|
||||
{
|
||||
Console.WriteLine(responseItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
OpenAIResponseAgent skAgent = new(new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient(), deploymentName)
|
||||
{ StoreEnabled = true };
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<Microsoft.SemanticKernel.Agents.Agent>((sp)
|
||||
=> new OpenAIResponseAgent(new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient(), deploymentName)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<Microsoft.SemanticKernel.Agents.Agent>();
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<Microsoft.SemanticKernel.Agents.Agent>((sp)
|
||||
=> new OpenAIResponseAgent(new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient(), deploymentName)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var skAgent = serviceProvider.GetRequiredService<Microsoft.SemanticKernel.Agents.Agent>();
|
||||
|
||||
var agent = (skAgent as OpenAIResponseAgent)!.AsAIAgent();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
// Example of Semantic Kernel Agent code
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
var agent = new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
};
|
||||
|
||||
var thread = new ChatHistoryAgentThread();
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new AgentInvokeOptions() { KernelArguments = new(settings) };
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var agent = new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
}.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of a fully migrated Agent Framework Agent code
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetChatClient(model)
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
ChatCompletionAgent agent = new()
|
||||
{
|
||||
Instructions = "You are a helpful assistant",
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Response ===\n");
|
||||
|
||||
await foreach (var item in agent.InvokeAsync(userInput))
|
||||
{
|
||||
Console.Write(item.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
ChatCompletionAgent skAgent = new()
|
||||
{
|
||||
Instructions = "You are a helpful assistant",
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new PromptExecutionSettings() { FunctionChoiceBehavior = FunctionChoiceBehavior.Auto() }),
|
||||
};
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
var agent = skAgent.AsAIAgent();
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
Console.WriteLine("\n---\n");
|
||||
await foreach (var item in skAgent.InvokeAsync(userInput))
|
||||
{
|
||||
Console.Write(item.Message);
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new OpenAIClient(apiKey).GetChatClient(model).AsAIAgent(
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddKernel().AddOpenAIChatClient(model, apiKey);
|
||||
serviceCollection.AddTransient((sp) => new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = sp.GetRequiredService<Kernel>(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<ChatCompletionAgent>();
|
||||
|
||||
await foreach (var item in agent.InvokeAsync(userInput))
|
||||
{
|
||||
Console.WriteLine(item.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of Semantic Kernel Agent code converted as an Agent Framework Agent
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddKernel().AddOpenAIChatClient(model, apiKey);
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new ChatCompletionAgent()
|
||||
{
|
||||
Kernel = sp.GetRequiredService<Kernel>(),
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
}.AsAIAgent());
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new OpenAIClient(apiKey)
|
||||
.GetChatClient(model)
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var responseClient = new OpenAIClient(apiKey).GetResponsesClient();
|
||||
OpenAIResponseAgent agent = new(responseClient)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agentOptions = new OpenAIResponseAgentInvokeOptions() { ResponseCreationOptions = new() { MaxOutputTokenCount = 1000 } };
|
||||
|
||||
Microsoft.SemanticKernel.Agents.AgentThread? thread = null;
|
||||
await foreach (var item in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(item.Message);
|
||||
thread = item.Thread;
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var item in agent.InvokeStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
// Thread need to be updated for subsequent calls
|
||||
thread = item.Thread;
|
||||
Console.Write(item.Message);
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var responseClient = new OpenAIClient(apiKey).GetResponsesClient();
|
||||
|
||||
OpenAIResponseAgent skAgent = new(responseClient)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "o4-mini";
|
||||
var userInput =
|
||||
"""
|
||||
Instructions:
|
||||
- Given the React component below, think about it and change it so that nonfiction books have red
|
||||
text.
|
||||
- Return only the code in your reply
|
||||
- Do not include any additional formatting, such as markdown code blocks
|
||||
- For formatting, use four space tabs, and do not allow any lines of code to
|
||||
exceed 80 columns
|
||||
const books = [
|
||||
{ title: 'Dune', category: 'fiction', id: 1 },
|
||||
{ title: 'Frankenstein', category: 'fiction', id: 2 },
|
||||
{ title: 'Moneyball', category: 'nonfiction', id: 3 },
|
||||
];
|
||||
export default function BookList() {
|
||||
const listItems = books.map(book =>
|
||||
<li>
|
||||
{book.title}
|
||||
</li>
|
||||
);
|
||||
return (
|
||||
<ul>{listItems}</ul>
|
||||
);
|
||||
}
|
||||
""";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var responseClient = new OpenAIClient(apiKey).GetResponsesClient();
|
||||
OpenAIResponseAgent agent = new(responseClient)
|
||||
{
|
||||
Name = "Thinker",
|
||||
Instructions = "You are good at thinking hard before answering.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agentOptions = new OpenAIResponseAgentInvokeOptions()
|
||||
{
|
||||
ResponseCreationOptions = new()
|
||||
{
|
||||
MaxOutputTokenCount = 8000,
|
||||
ReasoningOptions = new()
|
||||
{
|
||||
ReasoningEffortLevel = OpenAI.Responses.ResponseReasoningEffortLevel.High,
|
||||
ReasoningSummaryVerbosity = OpenAI.Responses.ResponseReasoningSummaryVerbosity.Detailed
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Microsoft.SemanticKernel.Agents.AgentThread? thread = null;
|
||||
await foreach (var item in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
foreach (var content in item.Message.Items)
|
||||
{
|
||||
if (content is ReasoningContent thinking)
|
||||
{
|
||||
Console.Write($"Thinking: \n{thinking}\n---\n");
|
||||
}
|
||||
else if (content is Microsoft.SemanticKernel.TextContent text)
|
||||
{
|
||||
Console.Write($"Assistant: {text}");
|
||||
}
|
||||
}
|
||||
Console.WriteLine(item.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
var userMessage = new ChatMessageContent(AuthorRole.User, userInput);
|
||||
thread = null;
|
||||
await foreach (var item in agent.InvokeStreamingAsync(userMessage, thread, agentOptions))
|
||||
{
|
||||
thread = item.Thread;
|
||||
foreach (var content in item.Message.Items)
|
||||
{
|
||||
// Currently SK Agent doesn't output thinking in streaming mode.
|
||||
// SK Issue: https://github.com/microsoft/semantic-kernel/issues/13046
|
||||
// OpenAI SDK Issue: https://github.com/openai/openai-dotnet/issues/643
|
||||
if (content is StreamingReasoningContent thinking)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{thinking}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (content is StreamingTextContent text)
|
||||
{
|
||||
Console.WriteLine($"Response: [{text}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var responseClient = new OpenAIClient(apiKey).GetResponsesClient();
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
OpenAIResponseAgent skAgent = new(responseClient)
|
||||
{
|
||||
Name = "Thinker",
|
||||
Instructions = "You are at thinking hard before answering.",
|
||||
StoreEnabled = true
|
||||
};
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
#pragma warning restore SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
Reasoning = new()
|
||||
{
|
||||
Effort = ReasoningEffort.High,
|
||||
Output = ReasoningOutput.Full
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
|
||||
// Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists.
|
||||
string assistantThinking = string.Join("\n", result.Messages
|
||||
.SelectMany(m => m.Contents)
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text));
|
||||
|
||||
var assistantText = result.Text;
|
||||
Console.WriteLine($"Thinking: \n{assistantThinking}\n---\n");
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text)
|
||||
.ToList();
|
||||
|
||||
if (thinkingContents.Count != 0)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{string.Join("\n", thinkingContents)}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Response: [{update.Text}]");
|
||||
}
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Thinker", instructions: "You are at thinking hard before answering.");
|
||||
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
Reasoning = new()
|
||||
{
|
||||
Effort = ReasoningEffort.High,
|
||||
Output = ReasoningOutput.Full
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
|
||||
// Retrieve the thinking as a full text block requires flattening multiple TextReasoningContents from multiple messages content lists.
|
||||
string assistantThinking = string.Join("\n", result.Messages
|
||||
.SelectMany(m => m.Contents)
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text));
|
||||
|
||||
var assistantText = result.Text;
|
||||
Console.WriteLine($"Thinking: \n{assistantThinking}\n---\n");
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
.Select(trc => trc.Text)
|
||||
.ToList();
|
||||
|
||||
if (thinkingContents.Count != 0)
|
||||
{
|
||||
Console.WriteLine($"Thinking: [{string.Join("\n", thinkingContents)}]");
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine($"Response: [{update.Text}]");
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "What is the weather like in Amsterdam?";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
[KernelFunction]
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
OpenAIResponseAgent agent = new(new OpenAIClient(apiKey).GetResponsesClient(), model) { StoreEnabled = true };
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
agent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Response ===\n");
|
||||
|
||||
await foreach (ChatMessageContent responseItem in agent.InvokeAsync(userInput))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(responseItem.Content))
|
||||
{
|
||||
Console.WriteLine(responseItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
var builder = Kernel.CreateBuilder().AddOpenAIChatClient(model, apiKey);
|
||||
|
||||
OpenAIResponseAgent skAgent = new(new OpenAIClient(apiKey).GetResponsesClient(), model) { StoreEnabled = true };
|
||||
|
||||
// Initialize plugin and add to the agent's Kernel (same as direct Kernel usage).
|
||||
skAgent.Kernel.Plugins.Add(KernelPluginFactory.CreateFromFunctions("KernelPluginName", [KernelFunctionFactory.CreateFromMethod(GetWeather)]));
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient().AsAIAgent(
|
||||
model: model,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\OpenAI\Agents.OpenAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
#pragma warning disable OPENAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = System.Environment.GetEnvironmentVariable("OPENAI_MODEL") ?? "gpt-4o";
|
||||
var userInput = "Tell me a joke about a pirate.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<Microsoft.SemanticKernel.Agents.Agent>((sp)
|
||||
=> new OpenAIResponseAgent(new OpenAIClient(apiKey).GetResponsesClient(), model)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<Microsoft.SemanticKernel.Agents.Agent>();
|
||||
|
||||
var result = await agent.InvokeAsync(userInput).FirstAsync();
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<Microsoft.SemanticKernel.Agents.Agent>((sp)
|
||||
=> new OpenAIResponseAgent(new OpenAIClient(apiKey).GetResponsesClient(), model)
|
||||
{
|
||||
Name = "Joker",
|
||||
Instructions = "You are good at telling jokes."
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var skAgent = serviceProvider.GetRequiredService<Microsoft.SemanticKernel.Agents.Agent>();
|
||||
|
||||
var agent = (skAgent as OpenAIResponseAgent)!.AsAIAgent();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient((sp) => new OpenAIClient(apiKey)
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var result = await agent.RunAsync(userInput);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# Semantic Kernel Migration Playground
|
||||
|
||||
This is a playground folder with different **Semantic Kernel** projects that can be used to test automatic AI migration to the new **Agent Framework (AF)**.
|
||||
|
||||
## Prompting
|
||||
|
||||
Open your IDE Agentic extension and create a new chat providing the following prompt:
|
||||
|
||||
```
|
||||
I need to convert code from Semantic Kernel to the Agent Framework.
|
||||
Please use the migration guide provided in the #SemanticKernelToAgentFramework.md as a reference.
|
||||
|
||||
The current solution is using central package manager, when referencing the projects in the csproj don't provide the versions.
|
||||
|
||||
Check external references provided by the migration guide if needed.
|
||||
|
||||
You don't need to look for the Central Package Management file, just focus on the project file and the code files.
|
||||
|
||||
When you need help or don't know how to proceed, please ask.
|
||||
```
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.Identity;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
|
||||
#pragma warning disable SKEXP0110 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
|
||||
var client = new PersistentAgentsClient(Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT"), new AzureCliCredential());
|
||||
|
||||
// Define the agent
|
||||
PersistentAgent definition = await client.Administration.CreateAgentAsync(
|
||||
Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME"),
|
||||
instructions: "You are a coding assistant that always generates code using the code interpreter tool.",
|
||||
tools: [new CodeInterpreterToolDefinition()]);
|
||||
|
||||
AzureAIAgent agent = new(definition, client);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
AgentThread thread = new AzureAIAgentThread(client);
|
||||
|
||||
try
|
||||
{
|
||||
await InvokeAgentAsync("Create a python file where it determines the values in the Fibonacci sequence that that are less then the value of 101.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await thread.DeleteAsync();
|
||||
await client.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task InvokeAgentAsync(string input)
|
||||
{
|
||||
ChatMessageContent message = new(AuthorRole.User, input);
|
||||
WriteAgentChatMessage(message);
|
||||
|
||||
await foreach (ChatMessageContent response in agent.InvokeAsync(message, thread))
|
||||
{
|
||||
WriteAgentChatMessage(response);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteAgentChatMessage(ChatMessageContent message)
|
||||
{
|
||||
// Include ChatMessageContent.AuthorName in output, if present.
|
||||
string authorExpression = message.Role == AuthorRole.User ? string.Empty : FormatAuthor();
|
||||
// Include TextContent (via ChatMessageContent.Content), if present.
|
||||
string contentExpression = string.IsNullOrWhiteSpace(message.Content) ? string.Empty : message.Content;
|
||||
bool isCode = message.Metadata?.ContainsKey(AzureAIAgent.CodeInterpreterMetadataKey) ?? false;
|
||||
string codeMarker = isCode ? "\n [CODE]\n" : " ";
|
||||
Console.WriteLine($"\n# {message.Role}{authorExpression}:{codeMarker}{contentExpression}");
|
||||
|
||||
// Provide visibility for inner content (that isn't TextContent).
|
||||
foreach (KernelContent item in message.Items)
|
||||
{
|
||||
if (item is AnnotationContent annotation)
|
||||
{
|
||||
if (annotation.Kind == AnnotationKind.UrlCitation)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {annotation.Label}: {annotation.ReferenceId} - {annotation.Title}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {annotation.Label}: File #{annotation.ReferenceId}");
|
||||
}
|
||||
}
|
||||
else if (item is ActionContent action)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {action.Text}");
|
||||
}
|
||||
else if (item is ReasoningContent reasoning)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] {reasoning.Text ?? "Thinking..."}");
|
||||
}
|
||||
else if (item is FileReferenceContent fileReference)
|
||||
{
|
||||
Console.WriteLine($" [{item.GetType().Name}] File #{fileReference.FileId}");
|
||||
}
|
||||
}
|
||||
|
||||
if ((message.Metadata?.TryGetValue("Usage", out object? usage) ?? false) && usage is RunStepCompletionUsage agentUsage)
|
||||
{
|
||||
Console.WriteLine($" [Usage] Tokens: {agentUsage.TotalTokens}, Input: {agentUsage.PromptTokens}, Output: {agentUsage.CompletionTokens}");
|
||||
}
|
||||
|
||||
string FormatAuthor() => message.AuthorName is not null ? $" - {message.AuthorName ?? " * "}" : string.Empty;
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1707;CA2007;VSTHRD111</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents.Persistent" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\AzureAI\Agents.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Agents\Core\Agents.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\SemanticKernel.MetaPackage\SemanticKernel.MetaPackage.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="../../../../../.github/upgrades/prompts/*" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,405 @@
|
||||
# Semantic Kernel to Agent Framework Migration Guide
|
||||
|
||||
## What's Changed?
|
||||
- **Namespace Updates**: From `Microsoft.SemanticKernel.Agents` to `Microsoft.Agents.AI`
|
||||
- **Agent Creation**: Single fluent API calls vs multi-step builder patterns
|
||||
- **Thread Management**: Built-in thread management vs manual thread creation
|
||||
- **Tool Registration**: Direct function registration vs plugin wrapper systems
|
||||
- **Dependency Injection**: Simplified service registration patterns
|
||||
- **Invocation Patterns**: Streamlined options and result handling
|
||||
|
||||
## Benefits of Migration
|
||||
- **Simplified API**: Reduced complexity and boilerplate code
|
||||
- **Better Performance**: Optimized object creation and memory usage
|
||||
- **Unified Interface**: Consistent patterns across different AI providers
|
||||
- **Enhanced Developer Experience**: More intuitive and discoverable APIs
|
||||
|
||||
## Key Changes
|
||||
|
||||
### 1. Namespace Updates
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
```csharp
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
Agent Framework namespaces are under `Microsoft.Agents.AI`.
|
||||
Agent Framework uses the core AI message and content types from `Microsoft.Extensions.AI` for communication between components.
|
||||
|
||||
```csharp
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Agents.AI;
|
||||
```
|
||||
|
||||
### 2. Agent Creation Simplification
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
Every agent in Semantic Kernel depends on a `Kernel` instance and will have
|
||||
an empty `Kernel` if not provided.
|
||||
|
||||
```csharp
|
||||
Kernel kernel = Kernel
|
||||
.AddOpenAIChatClient(modelId, apiKey)
|
||||
.Build();
|
||||
|
||||
ChatCompletionAgent agent = new() { Instructions = ParrotInstructions, Kernel = kernel };
|
||||
```
|
||||
|
||||
Azure AI Foundry requires an agent resource to be created in the cloud before creating a local agent class that uses it.
|
||||
|
||||
```csharp
|
||||
PersistentAgentsClient azureAgentClient = AzureAIAgent.CreateAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
|
||||
PersistentAgent definition = await azureAgentClient.Administration.CreateAgentAsync(
|
||||
deploymentName,
|
||||
instructions: ParrotInstructions);
|
||||
|
||||
AzureAIAgent agent = new(definition, azureAgentClient);
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
Agent creation in Agent Framework is made simpler with extensions provided by all main providers.
|
||||
|
||||
```csharp
|
||||
AIAgent openAIAgent = chatClient.CreateAIAgent(instructions: ParrotInstructions);
|
||||
AIAgent azureFoundryAgent = await persistentAgentsClient.CreateAIAgentAsync(instructions: ParrotInstructions);
|
||||
AIAgent openAIAssistantAgent = await assistantClient.CreateAIAgentAsync(instructions: ParrotInstructions);
|
||||
```
|
||||
|
||||
Additionally for hosted agent providers you can also use the `GetAIAgent` to retrieve an agent from an existing hosted agent.
|
||||
|
||||
```csharp
|
||||
AIAgent azureFoundryAgent = await persistentAgentsClient.GetAIAgentAsync(agentId);
|
||||
```
|
||||
|
||||
### 3. Agent Thread Creation
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
The caller has to know the thread type and create it manually.
|
||||
|
||||
```csharp
|
||||
// Create a thread for the agent conversation.
|
||||
AgentThread thread = new OpenAIAssistantAgentThread(this.AssistantClient);
|
||||
AgentThread thread = new AzureAIAgentThread(this.Client);
|
||||
AgentThread thread = new OpenAIResponseAgentThread(this.Client);
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
The agent is responsible for creating the thread.
|
||||
|
||||
```csharp
|
||||
// New
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
```
|
||||
|
||||
### 4. Hosted Agent Thread Cleanup
|
||||
|
||||
This case applies exclusively to a few AI providers that still provide hosted threads.
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
Threads have a `self` deletion method
|
||||
|
||||
i.e: OpenAI Assistants Provider
|
||||
```csharp
|
||||
await thread.DeleteAsync();
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
> [!NOTE]
|
||||
> OpenAI Responses introduced a new conversation model that simplifies how conversations are handled. This simplifies hosted thread management compared to the now deprecated OpenAI Assistants model. For more information see the [OpenAI Assistants migration guide](https://platform.openai.com/docs/assistants/migration).
|
||||
|
||||
Agent Framework doesn't have a thread deletion API in the `AgentThread` type as not all providers support hosted threads or thread deletion and this will become more common as more providers shift to responses based architectures.
|
||||
|
||||
If you require thread deletion and the provider allows this, the caller **should** keep track of the created threads and delete them later when necessary via the provider's sdk.
|
||||
|
||||
i.e: OpenAI Assistants Provider
|
||||
```csharp
|
||||
await assistantClient.DeleteThreadAsync(thread.ConversationId);
|
||||
```
|
||||
|
||||
### 5. Tool Registration
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
In semantic kernel to expose a function as a tool you must:
|
||||
|
||||
1. Decorate the function with a `[KernelFunction]` attribute.
|
||||
2. Have a `Plugin` class or use the `KernelPluginFactory` to wrap the function.
|
||||
3. Have a `Kernel` to add your plugin to.
|
||||
4. Pass the `Kernel` to the agent.
|
||||
|
||||
```csharp
|
||||
KernelFunction function = KernelFunctionFactory.CreateFromMethod(GetWeather);
|
||||
KernelPlugin plugin = KernelPluginFactory.CreateFromFunctions("KernelPluginName", [function]);
|
||||
Kernel kernel = ... // Create kernel
|
||||
kernel.Plugins.Add(plugin);
|
||||
|
||||
ChatCompletionAgent agent = new() { Kernel = kernel, ... };
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
In agent framework in a single call you can register tools directly in the agent creation process.
|
||||
|
||||
```csharp
|
||||
AIAgent agent = chatClient.CreateAIAgent(tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
```
|
||||
|
||||
### 6. Agent Non-Streaming Invocation
|
||||
|
||||
Key differences can be seen in the method names from `Invoke` to `Run`, return types and parameters `AgentRunOptions`.
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
The Non-Streaming uses a streaming pattern `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` for returning multiple agent messages.
|
||||
|
||||
```csharp
|
||||
await foreach (AgentResponseItem<ChatMessageContent> result in agent.InvokeAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
The Non-Streaming returns a single `AgentRunResponse` with the agent response that can contain multiple messages.
|
||||
The text result of the run is available in `AgentRunResponse.Text` or `AgentRunResponse.ToString()`.
|
||||
All messages created as part of the response is returned in the `AgentRunResponse.Messages` list.
|
||||
This may include tool call messages, function results, reasoning updates and final results.
|
||||
|
||||
```csharp
|
||||
AgentRunResponse agentResponse = await agent.RunAsync(userInput, thread);
|
||||
```
|
||||
|
||||
### 7. Agent Streaming Invocation
|
||||
|
||||
Key differences in the method names from `Invoke` to `Run`, return types and parameters `AgentRunOptions`.
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
```csharp
|
||||
await foreach (StreamingChatMessageContent update in agent.InvokeStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
```
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
Similar streaming API pattern with the key difference being that it returns `AgentRunResponseUpdate` objects including more agent related information per update.
|
||||
|
||||
All updates produced by any service underlying the AIAgent is returned. The textual result of the agent is available by concatenating the `AgentRunResponse.Text` values.
|
||||
|
||||
```csharp
|
||||
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update); // Update is ToString() friendly
|
||||
}
|
||||
```
|
||||
|
||||
### 8. Tool Function Signatures
|
||||
|
||||
**Problem**: SK plugin methods need `[KernelFunction]` attributes
|
||||
|
||||
```csharp
|
||||
public class MenuPlugin
|
||||
{
|
||||
[KernelFunction] // Required for SK
|
||||
public static MenuItem[] GetMenu() => ...;
|
||||
}
|
||||
```
|
||||
|
||||
**Solution**: AF can use methods directly without attributes
|
||||
|
||||
```csharp
|
||||
public class MenuTools
|
||||
{
|
||||
[Description("Get menu items")] // Optional description
|
||||
public static MenuItem[] GetMenu() => ...;
|
||||
}
|
||||
```
|
||||
|
||||
### 9. Options Configuration
|
||||
|
||||
**Problem**: Complex options setup in SK
|
||||
|
||||
```csharp
|
||||
OpenAIPromptExecutionSettings settings = new() { MaxTokens = 1000 };
|
||||
AgentInvokeOptions options = new() { KernelArguments = new(settings) };
|
||||
```
|
||||
|
||||
**Solution**: Simplified options in AF
|
||||
|
||||
```csharp
|
||||
ChatClientAgentRunOptions options = new(new() { MaxOutputTokens = 1000 });
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This example shows passing implementation specific options to a `ChatClientAgent`. Not all `AIAgents` support `ChatClientAgentRunOptions`.
|
||||
> `ChatClientAgent` is provided to build agents based on underlying inference services, and therefore supports inference options like `MaxOutputTokens`.
|
||||
|
||||
### 10. Dependency Injection
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
A `Kernel` registration is required in the service container to be able to create an agent
|
||||
as every agent abstractions needs to be initialized with a `Kernel` property.
|
||||
|
||||
Semantic Kernel uses the `Agent` type as the base abstraction class for agents.
|
||||
|
||||
```csharp
|
||||
services.AddKernel().AddProvider(...);
|
||||
serviceContainer.AddKeyedSingleton<SemanticKernel.Agents.Agent>(
|
||||
TutorName,
|
||||
(sp, key) =>
|
||||
new ChatCompletionAgent()
|
||||
{
|
||||
// Passing the kernel is required
|
||||
Kernel = sp.GetRequiredService<Kernel>(),
|
||||
});
|
||||
```
|
||||
|
||||
### 11. **Agent Type Consolidation**
|
||||
|
||||
#### Semantic Kernel
|
||||
|
||||
Semantic kernel provides specific agent classes for various services, e.g.
|
||||
|
||||
- `ChatCompletionAgent` for use with chat-completion-based inference services.
|
||||
- `OpenAIAssistantAgent` for use with the OpenAI Assistants service.
|
||||
- `AzureAIAgent` for use with the Azure AI Foundry Agents service.
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
The agent framework supports all the abovementioned services via a single agent type, `ChatClientAgent`.
|
||||
|
||||
`ChatClientAgent` can be used to build agents using any underlying service that provides an SDK implementing the `Microsoft.Extensions.AI.IChatClient` interface.
|
||||
|
||||
#### Agent Framework
|
||||
|
||||
The Agent framework provides the `AIAgent` type as the base abstraction class.
|
||||
|
||||
```csharp
|
||||
services.AddKeyedSingleton<AIAgent>(() => client.CreateAIAgent(...));
|
||||
```
|
||||
|
||||
## Migration Samples
|
||||
|
||||
This folder contains **separate console application projects** demonstrating how to transition from **Semantic Kernel (SK)** to the new **Agent Framework (AF)**.
|
||||
|
||||
Each project shows side-by-side comparisons of equivalent functionality in both frameworks and can be run independently.
|
||||
|
||||
Each sample code contains the following:
|
||||
1. **SK Agent** (Semantic Kernel before)
|
||||
2. **AF Agent** (Agent Framework after)
|
||||
|
||||
### Running the samples from Visual Studio
|
||||
|
||||
Open the solution in Visual Studio and set the desired sample project as the startup project. Then, run the project using the built-in debugger or by pressing `F5`.
|
||||
|
||||
You will be prompted for any required environment variables if they are not already set.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following:
|
||||
|
||||
- [.NET 10.0 SDK or later](https://dotnet.microsoft.com/download)
|
||||
- For Azure AI Foundry samples: Azure OpenAI service endpoint and deployment configured
|
||||
- For OpenAI samples: OpenAI API key
|
||||
- For OpenAI Assistants samples: OpenAI API key with Assistant API access
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Set the appropriate environment variables based on the sample type you want to run:
|
||||
|
||||
**For Azure AI Foundry projects:**
|
||||
```powershell
|
||||
$env:AZURE_FOUNDRY_PROJECT_ENDPOINT = "https://<your-project>-resource.services.ai.azure.com/api/projects/<your-project>"
|
||||
```
|
||||
|
||||
**For OpenAI and OpenAI Assistants projects:**
|
||||
```powershell
|
||||
$env:OPENAI_API_KEY = "sk-..."
|
||||
```
|
||||
|
||||
**For Azure OpenAI and Azure OpenAI Assistants projects:**
|
||||
```powershell
|
||||
$env:AZURE_OPENAI_ENDPOINT = "https://<your-project>.cognitiveservices.azure.com/"
|
||||
$env:AZURE_OPENAI_DEPLOYMENT_NAME = "gpt-4o" # Optional, defaults to gpt-4o
|
||||
```
|
||||
|
||||
**Optional debug mode:**
|
||||
```powershell
|
||||
$env:AF_SHOW_ALL_DEMO_SETTING_VALUES = "Y"
|
||||
```
|
||||
|
||||
If environment variables are not set, the demos will prompt you to enter values interactively.
|
||||
|
||||
### Samples
|
||||
|
||||
The migration samples are organized into different categories, each demonstrating different AI service integrations and orchestration patterns:
|
||||
|
||||
|Category|Description|
|
||||
|---|---|
|
||||
|[AzureAIFoundry](./AzureAIFoundry/)|Azure OpenAI service integration samples|
|
||||
|[AzureOpenAI](./AzureOpenAI/)|Direct Azure OpenAI API integration samples|
|
||||
|[AzureOpenAIAssistants](./AzureOpenAIAssistants/)|Azure OpenAI Assistants API integration samples|
|
||||
|[AzureOpenAIResponses](./AzureOpenAIResponses/)|Azure OpenAI Responses API integration samples|
|
||||
|[OpenAI](./OpenAI/)|Direct OpenAI API integration samples|
|
||||
|[OpenAIAssistants](./OpenAIAssistants/)|OpenAI Assistants API integration samples|
|
||||
|[OpenAIResponses](./OpenAIResponses/)|OpenAI Responses API integration samples|
|
||||
|[AgentOrchestrations](./AgentOrchestrations/)|Agent orchestration patterns including concurrent, sequential, and handoff workflows|
|
||||
|
||||
## Running the samples from the console
|
||||
|
||||
To run any migration sample, navigate to the desired sample directory:
|
||||
|
||||
```powershell
|
||||
# Azure AI Foundry Examples
|
||||
cd "AzureAIFoundry\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# Azure OpenAI Examples
|
||||
cd "AzureOpenAI\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# Azure OpenAI Assistants Examples
|
||||
cd "AzureOpenAIAssistants\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# Azure OpenAI Responses Examples
|
||||
cd "AzureOpenAIResponses\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# OpenAI Examples
|
||||
cd "OpenAI\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# OpenAI Assistants Examples
|
||||
cd "OpenAIAssistants\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# OpenAI Responses Examples
|
||||
cd "OpenAIResponses\Step01_Basics"
|
||||
dotnet run
|
||||
|
||||
# Agent Orchestrations Examples
|
||||
cd "AgentOrchestrations\Step01_Concurrent"
|
||||
dotnet run
|
||||
|
||||
cd "AgentOrchestrations\Step02_Sequential"
|
||||
dotnet run
|
||||
|
||||
cd "AgentOrchestrations\Step03_Handoff"
|
||||
dotnet run
|
||||
```
|
||||
Reference in New Issue
Block a user