mirror of
https://github.com/microsoft/semantic-kernel.git
synced 2026-10-12 02:19:06 +00:00
.Net: Semantic Kernel -> Agent Framework - Migration/Samples Update (AF 1.0 Compatible) (#13852)
## Description Updates the SK → Agent Framework migration document, samples, and bridge code from AF preview (`1.0.0-preview.251009.1`) to GA (`1.0.0`). ### Breaking changes addressed | Preview API | AF 1.0 GA | Scope | |---|---|---| | `AgentThread` | `AgentSession` | Core type rename | | `GetNewThread()` | `CreateSessionAsync()` | Now async | | `AgentRunResponse` | `AgentResponse` | Return type rename | | `AgentRunResponseUpdate` | `AgentResponseUpdate` | Streaming type rename | | `CreateAIAgent()` | `AsAIAgent()` | Extension method rename | | `AssistantClient.CreateAIAgentAsync()` | **Removed** | Redirect to Responses API | | `PersistentAgentsClient` | **Obsolete** | Use `AIProjectClient` via `Microsoft.Agents.AI.Foundry` | | `Microsoft.Agents.AI.AzureAI` | `Microsoft.Agents.AI.Foundry` | Package rename | | `InProcessExecution.StreamAsync` | `RunStreamingAsync` | Workflow API | | `AgentRunUpdateEvent` | `AgentResponseUpdateEvent` | Workflow event | | `AIAgent.Id` (virtual) | `IdCore` (protected virtual) | Override pattern | ### Additional discoveries - `using OpenAI.Chat;` required for `ChatClient.AsAIAgent()` extension to resolve - `using OpenAI.Responses;` required for `ResponsesClient.AsAIAgent()` extension to resolve ### What changed **Package versions** (`dotnet/Directory.Packages.props`) - AF packages updated to `1.0.0` - `Microsoft.Agents.AI.AzureAI` → `Microsoft.Agents.AI.Foundry` **Bridge code** (`dotnet/src/Agents/Abstractions/AIAgent/`) - `SemanticKernelAIAgent.cs`: New `Core` method overrides (`CreateSessionCoreAsync`, `RunCoreAsync`, etc.) - `SemanticKernelAIAgentThread` → `SemanticKernelAIAgentSession` (extends `AgentSession`) **31 migration samples** (all compile ✅) - OpenAI/AzureOpenAI: `AsAIAgent`, `CreateSessionAsync`, `using OpenAI.Chat;` - Assistants (8): AF sections rewritten to Responses API - Responses (8): Direct `ResponsesClient.AsAIAgent()` - Foundry (4): `AIProjectClient.AsAIAgent()` via `Microsoft.Agents.AI.Foundry` - Orchestrations (3): `RunStreamingAsync`, `AgentResponseUpdateEvent` **Migration document** (`.github/upgrades/prompts/SemanticKernelToAgentFramework.md`) - All AF preview API references updated to 1.0 GA patterns **Unit/integration tests** (~15 files) - Mechanical renames for `AgentSession`, `AgentResponse`, `CreateSessionAsync` ### Validation 8 standalone console programs were created and executed against AF 1.0.0 NuGet packages with real API keys, validating all migration patterns end-to-end: 1. OpenAI Basics (ChatClient → AsAIAgent, CreateSessionAsync, Run/RunStreaming) 2. OpenAI ToolCall (AIFunctionFactory.Create, tool invocation) 3. OpenAI DI (ServiceProvider registration) 4. OpenAI Responses (ResponsesClient.AsAIAgent) 5. Azure AI Foundry (AIProjectClient.AsAIAgent) 6. Workflows Handoff (HandoffWorkflowBuilder, InProcessExecution.RunStreamingAsync) 7. Session Lifecycle (Create, Serialize, Deserialize, multi-turn) 8. Assistants Migration Path (Responses API as replacement) --------- Co-authored-by: Copilot <[email protected]>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Instructions for migrating from Semantic Kernel Agents to Agent Framework in .NET projects.
|
||||
# Instructions for migrating from Semantic Kernel Agents to Agent Framework in .NET projects.
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -22,13 +22,13 @@ For each project that needs to be migrated, you need to do the following:
|
||||
solution or you could not find the project, notify user and continue with other projects).
|
||||
- Identify the specific Semantic Kernel agent types being used:
|
||||
- `ChatCompletionAgent` → `ChatClientAgent`
|
||||
- `OpenAIAssistantAgent` → `assistantsClient.CreateAIAgent()` (via OpenAI Assistants client extension)
|
||||
- `AzureAIAgent` → `persistentAgentsClient.CreateAIAgent()` (via Azure AI Foundry client extension)
|
||||
- `OpenAIResponseAgent` → `responsesClient.CreateAIAgent()` (via OpenAI Responses client extension)
|
||||
- `OpenAIAssistantAgent` → `assistantsClient.AsAIAgent()` (via OpenAI Assistants client extension)
|
||||
- `AzureAIAgent` → `persistentAgentsClient.AsAIAgent()` (via Azure AI Foundry client extension)
|
||||
- `OpenAIResponseAgent` → `responsesClient.AsAIAgent()` (via OpenAI Responses client extension)
|
||||
- `A2AAgent` → `AIAgent` (via A2A card resolver)
|
||||
- `BedrockAgent` → Custom implementation required (not supported)
|
||||
- Determine if agents are being created new or retrieved from hosted services:
|
||||
- **New agents**: Use `CreateAIAgent()` methods
|
||||
- **New agents**: Use `AsAIAgent()` methods
|
||||
- **Existing hosted agents**: Use `GetAIAgent(agentId)` methods for OpenAI Assistants and Azure AI Foundry
|
||||
</agent_type_identification>
|
||||
|
||||
@@ -105,8 +105,8 @@ After completing migration, verify these specific items:
|
||||
1. **Compilation**: Execute `dotnet build` on all modified projects - zero errors required
|
||||
2. **Namespace Updates**: Confirm all `using Microsoft.SemanticKernel.Agents` statements are replaced
|
||||
3. **Method Calls**: Verify all `InvokeAsync` calls are changed to `RunAsync`
|
||||
4. **Return Types**: Confirm handling of `AgentRunResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
|
||||
5. **Thread Creation**: Validate all thread creation uses `agent.GetNewThread()` pattern
|
||||
4. **Return Types**: Confirm handling of `AgentResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
|
||||
5. **Thread Creation**: Validate all thread creation uses `agent.CreateSessionAsync()` pattern
|
||||
6. **Tool Registration**: Ensure `[KernelFunction]` attributes are removed and `AIFunctionFactory.Create()` is used
|
||||
7. **Options Configuration**: Verify `AgentRunOptions` or `ChatClientAgentRunOptions` replaces `AgentInvokeOptions`
|
||||
8. **Breaking Glass**: Test `RawRepresentation` access replaces `InnerContent` access
|
||||
@@ -119,8 +119,8 @@ Agent Framework provides functionality for creating and managing AI agents throu
|
||||
Key API differences:
|
||||
- Agent creation: Remove Kernel dependency, use direct client-based creation
|
||||
- Method names: `InvokeAsync` → `RunAsync`, `InvokeStreamingAsync` → `RunStreamingAsync`
|
||||
- Return types: `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentRunResponse`
|
||||
- Thread creation: Provider-specific constructors → `agent.GetNewThread()`
|
||||
- Return types: `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentResponse`
|
||||
- Thread creation: Provider-specific constructors → `agent.CreateSessionAsync()`
|
||||
- Tool registration: `KernelPlugin` system → Direct `AIFunction` registration
|
||||
- Options: `AgentInvokeOptions` → Provider-specific run options (e.g., `ChatClientAgentRunOptions`)
|
||||
</api_changes>
|
||||
@@ -142,14 +142,14 @@ Replace these Semantic Kernel agent classes with their Agent Framework equivalen
|
||||
|----------------------|----------------------------|-------------------|
|
||||
| `IChatCompletionService` | `IChatClient` | Convert to `IChatClient` using `chatService.AsChatClient()` extensions |
|
||||
| `ChatCompletionAgent` | `ChatClientAgent` | Remove `Kernel` parameter, add `IChatClient` parameter |
|
||||
| `OpenAIAssistantAgent` | `AIAgent` (via extension) | **New**: `OpenAIClient.GetAssistantClient().CreateAIAgent()` <br> **Existing**: `OpenAIClient.GetAssistantClient().GetAIAgent(assistantId)` |
|
||||
| `AzureAIAgent` | `AIAgent` (via extension) | **New**: `PersistentAgentsClient.CreateAIAgent()` <br> **Existing**: `PersistentAgentsClient.GetAIAgent(agentId)` |
|
||||
| `OpenAIResponseAgent` | `AIAgent` (via extension) | Replace with `OpenAIClient.GetOpenAIResponseClient().CreateAIAgent()` |
|
||||
| `OpenAIAssistantAgent` | `AIAgent` (via extension) | **New**: `OpenAIClient.GetAssistantClient().AsAIAgent()` <br> **Existing**: `OpenAIClient.GetAssistantClient().GetAIAgent(assistantId)` |
|
||||
| `AzureAIAgent` | `AIAgent` (via extension) | **New**: `PersistentAgentsClient.AsAIAgent()` <br> **Existing**: `PersistentAgentsClient.GetAIAgent(agentId)` |
|
||||
| `OpenAIResponseAgent` | `AIAgent` (via extension) | Replace with `OpenAIClient.GetResponsesClient().AsAIAgent()` |
|
||||
| `A2AAgent` | `AIAgent` (via extension) | Replace with `A2ACardResolver.GetAIAgentAsync()` |
|
||||
| `BedrockAgent` | Not supported | Custom implementation required |
|
||||
|
||||
**Important distinction:**
|
||||
- **CreateAIAgent()**: Use when creating new agents in the hosted service
|
||||
- **AsAIAgent()**: Use when creating new agents in the hosted service
|
||||
- **GetAIAgent(agentId)**: Use when retrieving existing agents from the hosted service
|
||||
</agent_type_identification>
|
||||
|
||||
@@ -158,16 +158,16 @@ Replace these method calls:
|
||||
|
||||
| Semantic Kernel Method | Agent Framework Method | Parameter Changes |
|
||||
|----------------------|----------------------|------------------|
|
||||
| `agent.InvokeAsync(message, thread, options)` | `agent.RunAsync(message, thread, options)` | Same parameters, different return type |
|
||||
| `agent.InvokeStreamingAsync(message, thread, options)` | `agent.RunStreamingAsync(message, thread, options)` | Same parameters, different return type |
|
||||
| `new ChatHistoryAgentThread()` | `agent.GetNewThread()` | No parameters needed |
|
||||
| `new OpenAIAssistantAgentThread(client)` | `agent.GetNewThread()` | No parameters needed |
|
||||
| `new AzureAIAgentThread(client)` | `agent.GetNewThread()` | No parameters needed |
|
||||
| `agent.InvokeAsync(message, thread, options)` | `agent.RunAsync(message, session, options)` | Same parameters, different return type |
|
||||
| `agent.InvokeStreamingAsync(message, thread, options)` | `agent.RunStreamingAsync(message, session, options)` | Same parameters, different return type |
|
||||
| `new ChatHistoryAgentThread()` | `await agent.CreateSessionAsync()` | Returns `AgentSession` |
|
||||
| `new OpenAIAssistantAgentThread(client)` | `await agent.CreateSessionAsync()` | Returns `AgentSession` |
|
||||
| `new AzureAIAgentThread(client)` | `await agent.CreateSessionAsync()` | Returns `AgentSession` |
|
||||
| `thread.DeleteAsync()` | Provider-specific cleanup | Use provider client directly |
|
||||
|
||||
Return type changes:
|
||||
- `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentRunResponse`
|
||||
- `IAsyncEnumerable<StreamingChatMessageContent>` → `IAsyncEnumerable<AgentRunResponseUpdate>`
|
||||
- `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` → `AgentResponse`
|
||||
- `IAsyncEnumerable<StreamingChatMessageContent>` → `IAsyncEnumerable<AgentResponseUpdate>`
|
||||
</api_changes>
|
||||
|
||||
<configuration_changes>
|
||||
@@ -191,8 +191,8 @@ Agent Framework changes these behaviors compared to Semantic Kernel Agents:
|
||||
1. **Thread Management**: Agent Framework automatically manages thread state. Semantic Kernel required manual thread updates in some scenarios (e.g., OpenAI Responses).
|
||||
|
||||
2. **Return Types**:
|
||||
- Non-streaming: Returns single `AgentRunResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
|
||||
- Streaming: Returns `IAsyncEnumerable<AgentRunResponseUpdate>` instead of `IAsyncEnumerable<StreamingChatMessageContent>`
|
||||
- Non-streaming: Returns single `AgentResponse` instead of `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>`
|
||||
- Streaming: Returns `IAsyncEnumerable<AgentResponseUpdate>` instead of `IAsyncEnumerable<StreamingChatMessageContent>`
|
||||
|
||||
3. **Tool Registration**: Agent Framework uses direct function registration without requiring `[KernelFunction]` attributes.
|
||||
|
||||
@@ -222,6 +222,8 @@ using Microsoft.Extensions.AI;
|
||||
using Microsoft.Agents.AI;
|
||||
// Provider-specific namespaces (add only if needed):
|
||||
using OpenAI; // For OpenAI provider
|
||||
using OpenAI.Chat; // For ChatClient.AsAIAgent() extension
|
||||
using OpenAI.Responses; // For ResponsesClient.AsAIAgent() extension
|
||||
using Azure.AI.OpenAI; // For Azure OpenAI provider
|
||||
using Azure.AI.Agents.Persistent; // For Azure AI Foundry provider
|
||||
using Azure.Identity; // For Azure authentication
|
||||
@@ -254,7 +256,7 @@ AIAgent agent = new ChatClientAgent(chatClient, instructions: "You are a helpful
|
||||
// Method 2: Extension method (recommended)
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant");
|
||||
.AsAIAgent(instructions: "You are a helpful assistant");
|
||||
```
|
||||
</configuration_changes>
|
||||
|
||||
@@ -314,7 +316,7 @@ AIAgent agent = new ChatClientAgent(chatClient, instructions: "You are a helpful
|
||||
// Method 2: Extension method (recommended)
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant");
|
||||
.AsAIAgent(instructions: "You are a helpful assistant");
|
||||
```
|
||||
|
||||
**Required changes:**
|
||||
@@ -338,12 +340,12 @@ AgentThread thread = new AzureAIAgentThread(azureClient);
|
||||
**With this unified Agent Framework pattern:**
|
||||
```csharp
|
||||
// Use this single pattern for all agent types:
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
|
||||
**Required changes:**
|
||||
1. Remove all `new [Provider]AgentThread()` constructor calls
|
||||
2. Replace with `agent.GetNewThread()` method call
|
||||
2. Replace with `agent.CreateSessionAsync()` method call
|
||||
3. Remove provider client parameters from thread creation
|
||||
4. Use the same pattern regardless of agent provider type
|
||||
</api_changes>
|
||||
@@ -369,7 +371,7 @@ ChatCompletionAgent agent = new() { Kernel = kernel };
|
||||
[Description("Get the weather for a location")] // Keep Description attribute
|
||||
static string GetWeather(string location) => $"Weather in {location}";
|
||||
|
||||
AIAgent agent = chatClient.CreateAIAgent(
|
||||
AIAgent agent = chatClient.AsAIAgent(
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
```
|
||||
@@ -415,12 +417,12 @@ await foreach (var item in agent.InvokeAsync(userInput, thread)) { ... }
|
||||
static string GetWeather(string location) => $"Weather in {location}";
|
||||
|
||||
// Start with an existing agent
|
||||
AIAgent existingAgent = chatClient.CreateAIAgent(
|
||||
AIAgent existingAgent = chatClient.AsAIAgent(
|
||||
instructions: "You are a helpful assistant");
|
||||
|
||||
// Create an augmented agent with additional tools using builder middleware
|
||||
var augmentedAgent = existingAgent.AsBuilder()
|
||||
.Use(async (chatMessages, agentThread, agentRunOptions, next, cancellationToken) =>
|
||||
.Use(async (chatMessages, agentSession, agentRunOptions, next, cancellationToken) =>
|
||||
{
|
||||
if (agentRunOptions is ChatClientAgentRunOptions chatClientAgentRunOptions)
|
||||
{
|
||||
@@ -429,12 +431,12 @@ var augmentedAgent = existingAgent.AsBuilder()
|
||||
chatClientAgentRunOptions.ChatOptions.Tools.Add(AIFunctionFactory.Create(GetWeather));
|
||||
}
|
||||
|
||||
return await next(chatMessages, agentThread, agentRunOptions, cancellationToken);
|
||||
return await next(chatMessages, agentSession, agentRunOptions, cancellationToken);
|
||||
})
|
||||
.Build();
|
||||
|
||||
// Use the augmented agent with the additional tools
|
||||
AgentRunResponse result = await augmentedAgent.RunAsync(userInput, thread);
|
||||
AgentResponse result = await augmentedAgent.RunAsync(userInput, session);
|
||||
```
|
||||
|
||||
**Required changes:**
|
||||
@@ -464,7 +466,7 @@ await foreach (AgentResponseItem<ChatMessageContent> item in agent.InvokeAsync(u
|
||||
|
||||
**With this Agent Framework non-streaming pattern:**
|
||||
```csharp
|
||||
AgentRunResponse result = await agent.RunAsync(userInput, thread, options);
|
||||
AgentResponse result = await agent.RunAsync(userInput, session, options);
|
||||
Console.WriteLine(result);
|
||||
```
|
||||
|
||||
@@ -478,7 +480,7 @@ await foreach (StreamingChatMessageContent update in agent.InvokeStreamingAsync(
|
||||
|
||||
**With this Agent Framework streaming pattern:**
|
||||
```csharp
|
||||
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(userInput, thread, options))
|
||||
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(userInput, session, options))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
@@ -487,8 +489,8 @@ await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(userInpu
|
||||
**Required changes:**
|
||||
1. Replace `agent.InvokeAsync()` with `agent.RunAsync()`
|
||||
2. Replace `agent.InvokeStreamingAsync()` with `agent.RunStreamingAsync()`
|
||||
3. Change return type handling from `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` to `AgentRunResponse`
|
||||
4. Change streaming type from `StreamingChatMessageContent` to `AgentRunResponseUpdate`
|
||||
3. Change return type handling from `IAsyncEnumerable<AgentResponseItem<ChatMessageContent>>` to `AgentResponse`
|
||||
4. Change streaming type from `StreamingChatMessageContent` to `AgentResponseUpdate`
|
||||
5. Remove `await foreach` for non-streaming calls
|
||||
6. Access message content directly from result object instead of iterating
|
||||
</api_changes>
|
||||
@@ -537,7 +539,7 @@ services.AddTransient<ChatCompletionAgent>(sp => new()
|
||||
services.AddTransient<AIAgent>(sp =>
|
||||
new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: "You are helpful"));
|
||||
.AsAIAgent(instructions: "You are helpful"));
|
||||
```
|
||||
|
||||
**Required changes:**
|
||||
@@ -564,11 +566,11 @@ For every thread created if there's intent to cleanup, the caller should track a
|
||||
```csharp
|
||||
// For OpenAI Assistants (when cleanup is needed):
|
||||
var assistantClient = new OpenAIClient(apiKey).GetAssistantClient();
|
||||
await assistantClient.DeleteThreadAsync(thread.ConversationId);
|
||||
await assistantClient.DeleteThreadAsync(session.ConversationId);
|
||||
|
||||
// For Azure AI Foundry (when cleanup is needed):
|
||||
var persistentClient = new PersistentAgentsClient(endpoint, credential);
|
||||
await persistentClient.Threads.DeleteThreadAsync(thread.ConversationId);
|
||||
await persistentClient.Threads.DeleteThreadAsync(session.ConversationId);
|
||||
|
||||
// No thread and agent cleanup is needed for non-hosted agent providers like
|
||||
// - Azure OpenAI Chat Completion
|
||||
@@ -580,7 +582,7 @@ await persistentClient.Threads.DeleteThreadAsync(thread.ConversationId);
|
||||
**Required changes:**
|
||||
1. Remove `thread.DeleteAsync()` calls
|
||||
2. Use provider-specific client for cleanup when required
|
||||
3. Access thread ID via `thread.ConversationId` property
|
||||
3. Access thread ID via `session.ConversationId` property
|
||||
4. Only implement cleanup for providers that require it (Assistants, Azure AI Foundry)
|
||||
</api_changes>
|
||||
|
||||
@@ -593,14 +595,14 @@ Use these exact patterns for each provider:
|
||||
```csharp
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: instructions);
|
||||
.AsAIAgent(instructions: instructions);
|
||||
```
|
||||
|
||||
**OpenAI Assistants (New):**
|
||||
```csharp
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetAssistantClient()
|
||||
.CreateAIAgent(modelId, instructions: instructions);
|
||||
.AsAIAgent(modelId, instructions: instructions);
|
||||
```
|
||||
|
||||
**OpenAI Assistants (Existing):**
|
||||
@@ -614,13 +616,13 @@ AIAgent agent = new OpenAIClient(apiKey)
|
||||
```csharp
|
||||
AIAgent agent = new AzureOpenAIClient(endpoint, credential)
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: instructions);
|
||||
.AsAIAgent(instructions: instructions);
|
||||
```
|
||||
|
||||
**Azure AI Foundry (New):**
|
||||
```csharp
|
||||
AIAgent agent = new PersistentAgentsClient(endpoint, credential)
|
||||
.CreateAIAgent(model: deploymentName, instructions: instructions);
|
||||
.AsAIAgent(model: deploymentName, instructions: instructions);
|
||||
```
|
||||
|
||||
**Azure AI Foundry (Existing):**
|
||||
@@ -665,9 +667,9 @@ using OpenAI;
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: "You are helpful");
|
||||
.AsAIAgent(instructions: "You are helpful");
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
</configuration_changes>
|
||||
|
||||
@@ -691,7 +693,7 @@ kernel.Plugins.Add(plugin);
|
||||
static string GetWeather([Description("Location")] string location)
|
||||
=> $"Weather in {location}";
|
||||
|
||||
AIAgent agent = chatClient.CreateAIAgent(
|
||||
AIAgent agent = chatClient.AsAIAgent(
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
```
|
||||
@@ -714,7 +716,7 @@ await foreach (var result in agent.InvokeAsync(input, thread, options))
|
||||
```csharp
|
||||
ChatClientAgentRunOptions options = new(new ChatOptions { MaxOutputTokens = 1000 });
|
||||
|
||||
AgentRunResponse result = await agent.RunAsync(input, thread, options);
|
||||
AgentResponse result = await agent.RunAsync(input, session, options);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// Access underlying content when needed:
|
||||
@@ -742,7 +744,7 @@ await foreach (var result in agent.InvokeAsync(input, thread, options))
|
||||
|
||||
**With this Agent Framework non-streaming usage pattern:**
|
||||
```csharp
|
||||
AgentRunResponse result = await agent.RunAsync(input, thread, options);
|
||||
AgentResponse result = await agent.RunAsync(input, session, options);
|
||||
Console.WriteLine($"Tokens: {result.Usage.TotalTokenCount}");
|
||||
```
|
||||
|
||||
@@ -762,7 +764,7 @@ await foreach (StreamingChatMessageContent response in agent.InvokeStreamingAsyn
|
||||
|
||||
**With this Agent Framework streaming usage pattern:**
|
||||
```csharp
|
||||
await foreach (AgentRunResponseUpdate update in agent.RunStreamingAsync(input, thread, options))
|
||||
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(input, session, options))
|
||||
{
|
||||
if (update.Contents.OfType<UsageContent>().FirstOrDefault() is { } usageContent)
|
||||
{
|
||||
@@ -787,7 +789,7 @@ await foreach (var content in agent.InvokeAsync(userInput, thread))
|
||||
|
||||
**With this Agent Framework breaking glass pattern:**
|
||||
```csharp
|
||||
var agentRunResponse = await agent.RunAsync(userInput, thread);
|
||||
var agentRunResponse = await agent.RunAsync(userInput, session);
|
||||
|
||||
// If the agent uses a ChatClient the first breaking glass probably will be a Microsoft.Extensions.AI.ChatResponse
|
||||
ChatResponse? chatResponse = agentRunResponse.RawRepresentation as ChatResponse;
|
||||
@@ -829,7 +831,7 @@ await foreach (var content in agent.InvokeAsync(userInput, thread))
|
||||
|
||||
**With this Agent Framework CodeInterpreter pattern:**
|
||||
```csharp
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
Console.WriteLine(result);
|
||||
|
||||
// Extract chat response MEAI type via first level breaking glass
|
||||
@@ -919,7 +921,7 @@ var openAIResponse = chatCompletion.GetRawResponse();
|
||||
|
||||
**Issue: Thread Type Mismatches**
|
||||
- **Problem**: Provider-specific thread constructors not found
|
||||
- **Solution**: Replace all thread constructors with `agent.GetNewThread()`
|
||||
- **Solution**: Replace all thread constructors with `agent.CreateSessionAsync()`
|
||||
|
||||
**Issue: Options Configuration**
|
||||
- **Problem**: `AgentInvokeOptions` type not found
|
||||
@@ -937,7 +939,7 @@ var openAIResponse = chatCompletion.GetRawResponse();
|
||||
2. **Update Namespaces**: Replace SK namespaces with AF namespaces
|
||||
3. **Update Agent Creation**: Remove Kernel, use direct client creation
|
||||
4. **Update Method Calls**: Replace `InvokeAsync` with `RunAsync`
|
||||
5. **Update Thread Creation**: Replace provider-specific constructors with `GetNewThread()`
|
||||
5. **Update Thread Creation**: Replace provider-specific constructors with `await agent.CreateSessionAsync()`
|
||||
6. **Update Tool Registration**: Remove attributes, use `AIFunctionFactory.Create()`
|
||||
7. **Update Options**: Replace `AgentInvokeOptions` with provider-specific options
|
||||
8. **Test and Validate**: Compile and test all functionality
|
||||
@@ -988,9 +990,9 @@ using OpenAI;
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant");
|
||||
.AsAIAgent(instructions: "You are a helpful assistant");
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
|
||||
### 2. Azure OpenAI Chat Completion Migration
|
||||
@@ -1038,7 +1040,7 @@ using Azure.Identity;
|
||||
|
||||
AIAgent agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant");
|
||||
.AsAIAgent(instructions: "You are a helpful assistant");
|
||||
```
|
||||
|
||||
### 3. OpenAI Assistants Migration
|
||||
@@ -1083,12 +1085,12 @@ using OpenAI;
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetAssistantClient()
|
||||
.CreateAIAgent(modelId, instructions: "You are a helpful assistant");
|
||||
.AsAIAgent(modelId, instructions: "You are a helpful assistant");
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
|
||||
// Cleanup when needed
|
||||
await assistantClient.DeleteThreadAsync(thread.ConversationId);
|
||||
await assistantClient.DeleteThreadAsync(session.ConversationId);
|
||||
```
|
||||
|
||||
**Retrieving an existing assistant:**
|
||||
@@ -1100,7 +1102,7 @@ AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetAssistantClient()
|
||||
.GetAIAgent(assistantId); // Use existing assistant ID
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
</api_changes>
|
||||
|
||||
@@ -1163,12 +1165,12 @@ using Azure.Identity;
|
||||
var client = new PersistentAgentsClient(endpoint, new AzureCliCredential());
|
||||
|
||||
// Create a new AIAgent using Agent Framework
|
||||
AIAgent agent = client.CreateAIAgent(
|
||||
AIAgent agent = client.AsAIAgent(
|
||||
model: deploymentName,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [/* List of specialized Azure.AI.Agents.Persistent.ToolDefinition types */]);
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
|
||||
**Retrieving an existing agent:**
|
||||
@@ -1182,7 +1184,7 @@ var client = new PersistentAgentsClient(endpoint, new AzureCliCredential());
|
||||
// Retrieve an existing AIAgent using its ID
|
||||
AIAgent agent = await client.GetAIAgentAsync(agentId);
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
```
|
||||
</api_changes>
|
||||
|
||||
@@ -1269,20 +1271,21 @@ await foreach (AgentResponseItem<ChatMessageContent> responseItem in responseIte
|
||||
Agent Framework automatically manages the thread, so there's no need to manually update it.
|
||||
|
||||
```csharp
|
||||
using Microsoft.Agents.AI.OpenAI;
|
||||
using OpenAI.Chat; // For ChatClient.AsAIAgent()
|
||||
using OpenAI.Responses; // For ResponsesClient.AsAIAgent()
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetOpenAIResponseClient(modelId)
|
||||
.CreateAIAgent(
|
||||
.GetResponsesClient(modelId)
|
||||
.AsAIAgent(
|
||||
name: "ResponseAgent",
|
||||
instructions: "Answer all queries in English and French.",
|
||||
tools: [/* AITools */]);
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
|
||||
// The thread will be automatically updated with the new response id from this point
|
||||
// The session will be automatically updated with the new response id from this point
|
||||
```
|
||||
</api_changes>
|
||||
|
||||
@@ -1336,21 +1339,22 @@ await foreach (AgentResponseItem<ChatMessageContent> responseItem in responseIte
|
||||
Agent Framework automatically manages the thread, so there's no need to manually update it.
|
||||
|
||||
```csharp
|
||||
using Microsoft.Agents.AI.OpenAI;
|
||||
using OpenAI.Chat; // For ChatClient.AsAIAgent()
|
||||
using OpenAI.Responses; // For ResponsesClient.AsAIAgent()
|
||||
using Azure.AI.OpenAI;
|
||||
|
||||
AIAgent agent = new AzureOpenAIClient(endpoint, new AzureCliCredential())
|
||||
.GetOpenAIResponseClient(modelId)
|
||||
.CreateAIAgent(
|
||||
.GetResponsesClient(modelId)
|
||||
.AsAIAgent(
|
||||
name: "ResponseAgent",
|
||||
instructions: "Answer all queries in English and French.",
|
||||
tools: [/* AITools */]);
|
||||
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
|
||||
// The thread will be automatically updated with the new response id from this point
|
||||
// The session will be automatically updated with the new response id from this point
|
||||
```
|
||||
</api_changes>
|
||||
|
||||
@@ -1513,7 +1517,7 @@ AITool[] tools =
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(
|
||||
.AsAIAgent(
|
||||
instructions: "You are a weather assistant",
|
||||
tools: tools);
|
||||
```
|
||||
@@ -1562,10 +1566,10 @@ var renderedTemplate = await new KernelPromptTemplateFactory()
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(modelId)
|
||||
.CreateAIAgent(instructions: renderedTemplate);
|
||||
.AsAIAgent(instructions: renderedTemplate);
|
||||
|
||||
// No template variables in invocation - use plain string
|
||||
var result = await agent.RunAsync("What's the weather?", thread);
|
||||
var result = await agent.RunAsync("What's the weather?");
|
||||
Console.WriteLine(result);
|
||||
```
|
||||
</behavioral_changes>
|
||||
|
||||
@@ -50,10 +50,10 @@
|
||||
<PackageVersion Include="JsonSchema.Net" Version="7.3.4" />
|
||||
<PackageVersion Include="JsonSchema.Net.Generation" Version="5.0.2" />
|
||||
<PackageVersion Include="Markdig" Version="0.40.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Abstractions" Version="1.0.0-preview.251009.1" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0-preview.251009.1" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.AzureAI" Version="1.0.0-preview.251009.1" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Workflows" Version="1.0.0-preview.251009.1" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Abstractions" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Foundry" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.AI.Workflows" Version="1.0.0" />
|
||||
<PackageVersion Include="Microsoft.Agents.CopilotStudio.Client" Version="1.1.107-beta" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.13" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.14" />
|
||||
@@ -136,7 +136,7 @@
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.4" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.6" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Diagnostics.Testing" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="10.0.2" />
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+2
-2
@@ -79,13 +79,13 @@ async Task AFConcurrentAgentWorkflow()
|
||||
var spanishAgent = GetAFTranslationAgent("Spanish", client);
|
||||
var concurrentAgentWorkflow = AgentWorkflowBuilder.BuildConcurrent([frenchAgent, spanishAgent]);
|
||||
|
||||
await using StreamingRun run = await InProcessExecution.StreamAsync(concurrentAgentWorkflow, "Hello, world!");
|
||||
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 AgentRunUpdateEvent e)
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text))
|
||||
{
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+2
-2
@@ -82,13 +82,13 @@ async Task AFSequentialAgentWorkflow()
|
||||
var sequentialAgentWorkflow = AgentWorkflowBuilder.BuildSequential(
|
||||
[frenchAgent, spanishAgent, englishAgent]);
|
||||
|
||||
await using StreamingRun run = await InProcessExecution.StreamAsync(sequentialAgentWorkflow, "Hello, world!");
|
||||
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 AgentRunUpdateEvent e)
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text))
|
||||
{
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.OpenAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Workflows" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+4
-2
@@ -1,5 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
#pragma warning disable MAAIW001 // Experimental: HandoffWorkflowBuilder
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json;
|
||||
using Azure.AI.OpenAI;
|
||||
@@ -207,13 +209,13 @@ async Task AFHandoffAgentWorkflow()
|
||||
Console.WriteLine($"User: {query}");
|
||||
messages.Add(new(ChatRole.User, query));
|
||||
|
||||
await using var run = await InProcessExecution.StreamAsync(handoffAgentWorkflow, messages);
|
||||
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 AgentRunUpdateEvent e)
|
||||
if (evt is AgentResponseUpdateEvent e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(e.Update.Text) && e.Update.Contents.Count == 0)
|
||||
{
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// 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;
|
||||
@@ -67,7 +68,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#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 = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -80,9 +81,9 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
@@ -91,29 +92,23 @@ async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = new PersistentAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
// AF 1.0: Use AIProjectClient.AsAIAgent() from Microsoft.Agents.AI.Foundry
|
||||
var projectClient = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential());
|
||||
|
||||
var agent = await azureAgentClient.CreateAIAgentAsync(
|
||||
var agent = projectClient.AsAIAgent(
|
||||
deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "GenerateStory");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
@@ -85,7 +86,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#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 = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { Tools = [AIFunctionFactory.Create(GetWeather)] });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -98,9 +99,9 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
@@ -109,26 +110,22 @@ async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = new PersistentAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
var agent = new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential())
|
||||
.AsAIAgent(model: deploymentName,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
var agent = await azureAgentClient.CreateAIAgentAsync(deploymentName, instructions: "Answer questions about the menu");
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { Tools = [AIFunctionFactory.Create(GetWeather)] });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+14
-20
@@ -1,6 +1,7 @@
|
||||
// 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;
|
||||
@@ -90,7 +91,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
@@ -103,9 +104,9 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
// Clean up
|
||||
var azureAgentClient = serviceProvider.GetRequiredService<PersistentAgentsClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
@@ -115,36 +116,29 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new PersistentAgentsClient(azureEndpoint, new AzureCliCredential()));
|
||||
serviceCollection.AddSingleton((sp) => new AIProjectClient(new Uri(azureEndpoint), new AzureCliCredential()));
|
||||
serviceCollection.AddTransient<AIAgent>((sp) =>
|
||||
{
|
||||
var azureAgentClient = sp.GetRequiredService<PersistentAgentsClient>();
|
||||
|
||||
return azureAgentClient.CreateAIAgent(
|
||||
deploymentName,
|
||||
name: "GenerateStory",
|
||||
instructions: "You are good at telling jokes.");
|
||||
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 thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
var azureAgentClient = serviceProvider.GetRequiredService<PersistentAgentsClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Agents.AI.Abstractions" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.AzureAI" />
|
||||
<PackageReference Include="Microsoft.Agents.AI.Foundry" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
+12
-55
@@ -2,6 +2,7 @@
|
||||
|
||||
using System.Text;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
@@ -76,7 +77,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread);
|
||||
Console.WriteLine(result);
|
||||
@@ -124,9 +125,9 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
if (thread is ChatClientAgentSession chatSession)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatSession.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
}
|
||||
@@ -135,59 +136,15 @@ async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var azureAgentClient = new PersistentAgentsClient(azureEndpoint, new AzureCliCredential());
|
||||
var agent = await azureAgentClient.CreateAIAgentAsync(deploymentName, tools: [new CodeInterpreterToolDefinition()]);
|
||||
var thread = agent.GetNewThread();
|
||||
// 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 result = await agent.RunAsync(userInput, thread);
|
||||
var session = await agent.CreateSessionAsync();
|
||||
|
||||
var result = await agent.RunAsync(userInput, session);
|
||||
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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await azureAgentClient.Threads.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await azureAgentClient.Administration.DeleteAgentAsync(agent.Id);
|
||||
// No cleanup needed - non-hosted path doesn't create server-side resources.
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using 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";
|
||||
@@ -65,7 +65,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#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 = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -83,9 +83,9 @@ async Task AFAgent()
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
|
||||
@@ -6,7 +6,7 @@ using Azure.Identity;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using 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";
|
||||
@@ -73,7 +73,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
async Task AFAgent()
|
||||
{
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
.AsAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using 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";
|
||||
@@ -72,7 +72,7 @@ async Task AFAgent()
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new AzureOpenAIClient(new(endpoint), new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Plugins.OpenApi;
|
||||
using OpenAI;
|
||||
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";
|
||||
@@ -59,7 +59,7 @@ async Task AFAgent()
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential())
|
||||
.GetChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant", tools: tools);
|
||||
.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
@@ -1,23 +0,0 @@
|
||||
<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>
|
||||
-120
@@ -1,120 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#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 SKAgent();
|
||||
await SKAgent_As_AFAgent();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new OpenAIAssistantAgentInvokeOptions() { 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);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent skAgent = new(assistant, assistantsClient);
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var assistantClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
var agent = await assistantClient.CreateAIAgentAsync(deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<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>
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
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.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#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?";
|
||||
|
||||
[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.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgent();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName,
|
||||
instructions: "You are a helpful assistant");
|
||||
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient)
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new OpenAIPromptExecutionSettings()
|
||||
{
|
||||
MaxTokens = 1000,
|
||||
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)]));
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName,
|
||||
instructions: "You are a helpful assistant");
|
||||
|
||||
OpenAIAssistantAgent skAgent = new(assistant, assistantsClient)
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new OpenAIPromptExecutionSettings()
|
||||
{
|
||||
MaxTokens = 1000,
|
||||
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();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var assistantClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
var agent = await assistantClient.CreateAIAgentAsync(deploymentName,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<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>
|
||||
-144
@@ -1,144 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Azure.AI.OpenAI;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#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 SKAgent();
|
||||
await SKAgent_As_AFAgent();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient());
|
||||
serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
serviceCollection.AddTransient((sp) =>
|
||||
{
|
||||
var assistantsClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
Assistant assistant = assistantsClient.CreateAssistant(deploymentName, new() { Name = "Joker", Instructions = "You are good at telling jokes." });
|
||||
|
||||
return new OpenAIAssistantAgent(assistant, assistantsClient);
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<OpenAIAssistantAgent>();
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var assistantsClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new OpenAIAssistantAgentInvokeOptions() { 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);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient());
|
||||
serviceCollection.AddKernel().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
serviceCollection.AddTransient((sp) =>
|
||||
{
|
||||
var assistantsClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
Assistant assistant = assistantsClient.CreateAssistant(deploymentName, new() { Name = "Joker", Instructions = "You are good at telling jokes." });
|
||||
|
||||
return new OpenAIAssistantAgent(assistant, assistantsClient);
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var skAgent = serviceProvider.GetRequiredService<OpenAIAssistantAgent>();
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
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
|
||||
var assistantClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient());
|
||||
serviceCollection.AddTransient<AIAgent>((sp) =>
|
||||
{
|
||||
var assistantClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
return assistantClient.CreateAIAgent(deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
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
|
||||
var assistantClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<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>
|
||||
-196
@@ -1,196 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text;
|
||||
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.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#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 = "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";
|
||||
|
||||
var assistantsClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential()).GetAssistantClient();
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgent();
|
||||
await SKAgent_As_AFAgent();
|
||||
await AFAgent();
|
||||
|
||||
async Task SKAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, enableCodeInterpreter: true);
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
|
||||
// Respond to user input
|
||||
await foreach (var content in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(content.Message.Content))
|
||||
{
|
||||
bool isCode = content.Message.Metadata?.ContainsKey(OpenAIAssistantAgent.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 assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
var _ = Kernel.CreateBuilder().AddAzureOpenAIChatClient(deploymentName, endpoint, new AzureCliCredential());
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(deploymentName, enableCodeInterpreter: true);
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent skAgent = new(assistant, assistantsClient);
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
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?> ?? [])
|
||||
{
|
||||
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}");
|
||||
}
|
||||
|
||||
// Check for 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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgent()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = await assistantsClient.CreateAIAgentAsync(deploymentName, tools: [new HostedCodeInterpreterTool()]);
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
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?> ?? [])
|
||||
{
|
||||
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}");
|
||||
}
|
||||
|
||||
// Check for 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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
+7
-7
@@ -5,7 +5,7 @@ using Azure.Identity;
|
||||
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.
|
||||
@@ -66,7 +66,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -84,17 +84,17 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient().AsIChatClient(deploymentName)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
+7
-7
@@ -7,7 +7,7 @@ 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.
|
||||
@@ -134,7 +134,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#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 = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
@@ -180,10 +180,10 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient().AsIChatClient(deploymentName)
|
||||
.CreateAIAgent(name: "Thinker", instructions: "You are good at thinking hard before answering.");
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Thinker", instructions: "You are good at thinking hard before answering.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
@@ -194,7 +194,7 @@ async Task AFAgentAsync()
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
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
|
||||
@@ -207,7 +207,7 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ using Azure.Identity;
|
||||
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.
|
||||
@@ -66,8 +66,8 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient().AsIChatClient(deploymentName)
|
||||
.CreateAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
Console.WriteLine("\n=== AF Agent Response ===\n");
|
||||
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ 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.
|
||||
@@ -71,8 +71,8 @@ async Task AFAgentAsync()
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
|
||||
.GetResponsesClient().AsIChatClient(deploymentName)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: deploymentName, name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
@@ -5,6 +5,7 @@ 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";
|
||||
@@ -64,7 +65,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#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 = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -83,9 +84,9 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetChatClient(model)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
|
||||
@@ -6,6 +6,7 @@ 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";
|
||||
@@ -65,7 +66,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
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 = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -86,7 +87,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new OpenAIClient(apiKey).GetChatClient(model).CreateAIAgent(
|
||||
var agent = new OpenAIClient(apiKey).GetChatClient(model).AsAIAgent(
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ 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";
|
||||
@@ -70,7 +71,7 @@ async Task AFAgentAsync()
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient<AIAgent>((sp) => new OpenAIClient(apiKey)
|
||||
.GetChatClient(model)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
.AsAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<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>
|
||||
@@ -1,116 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#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 assistantsClient = new AssistantClient(apiKey);
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new OpenAIAssistantAgentInvokeOptions() { 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);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
// 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 assistantsClient = new AssistantClient(apiKey);
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient);
|
||||
|
||||
var afAgent = agent.AsAIAgent();
|
||||
|
||||
var thread = afAgent.GetNewThread();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 1000 });
|
||||
|
||||
var result = await afAgent.RunAsync(userInput, thread, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in afAgent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var assistantClient = new AssistantClient(apiKey);
|
||||
|
||||
var agent = await assistantClient.CreateAIAgentAsync(model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<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>
|
||||
@@ -1,145 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#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?";
|
||||
|
||||
[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.";
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
var assistantsClient = new AssistantClient(apiKey);
|
||||
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model,
|
||||
instructions: "You are a helpful assistant");
|
||||
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient)
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new OpenAIPromptExecutionSettings()
|
||||
{
|
||||
MaxTokens = 1000,
|
||||
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)]));
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
|
||||
await foreach (var result in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
Console.WriteLine(result.Message);
|
||||
}
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.InvokeStreamingAsync(userInput, thread))
|
||||
{
|
||||
Console.Write(update.Message);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
var assistantsClient = new AssistantClient(apiKey);
|
||||
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model,
|
||||
instructions: "You are a helpful assistant");
|
||||
|
||||
OpenAIAssistantAgent skAgent = new(assistant, assistantsClient)
|
||||
{
|
||||
Kernel = builder.Build(),
|
||||
Arguments = new KernelArguments(new OpenAIPromptExecutionSettings()
|
||||
{
|
||||
MaxTokens = 1000,
|
||||
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();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var assistantClient = new AssistantClient(apiKey);
|
||||
|
||||
var agent = await assistantClient.CreateAIAgentAsync(model,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<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>
|
||||
-142
@@ -1,142 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.Connectors.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#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.AddSingleton((sp) => new AssistantClient(apiKey));
|
||||
serviceCollection.AddKernel().AddOpenAIChatClient(model, apiKey);
|
||||
serviceCollection.AddTransient((sp) =>
|
||||
{
|
||||
var assistantsClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
Assistant assistant = assistantsClient.CreateAssistant(model, new() { Name = "Joker", Instructions = "You are good at telling jokes." });
|
||||
|
||||
return new OpenAIAssistantAgent(assistant, assistantsClient);
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<OpenAIAssistantAgent>();
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var assistantsClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
var settings = new OpenAIPromptExecutionSettings() { MaxTokens = 1000 };
|
||||
var agentOptions = new OpenAIAssistantAgentInvokeOptions() { 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);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
await thread.DeleteAsync();
|
||||
await assistantsClient.DeleteAssistantAsync(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) => new AssistantClient(apiKey));
|
||||
serviceCollection.AddKernel().AddOpenAIChatClient(model, apiKey);
|
||||
serviceCollection.AddTransient((sp) =>
|
||||
{
|
||||
var assistantsClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
Assistant assistant = assistantsClient.CreateAssistant(model, new() { Name = "Joker", Instructions = "You are good at telling jokes." });
|
||||
|
||||
return new OpenAIAssistantAgent(assistant, assistantsClient);
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var skAgent = serviceProvider.GetRequiredService<OpenAIAssistantAgent>();
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
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
|
||||
var assistantClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton((sp) => new AssistantClient(apiKey));
|
||||
serviceCollection.AddTransient((sp) =>
|
||||
{
|
||||
var assistantClient = sp.GetRequiredService<AssistantClient>();
|
||||
|
||||
return assistantClient.CreateAIAgent(model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
});
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
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
|
||||
var assistantClient = serviceProvider.GetRequiredService<AssistantClient>();
|
||||
if (thread is ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
<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>
|
||||
-192
@@ -1,192 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
|
||||
#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 = "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";
|
||||
|
||||
var assistantsClient = new AssistantClient(apiKey);
|
||||
|
||||
Console.WriteLine($"User Input: {userInput}");
|
||||
|
||||
await SKAgentAsync();
|
||||
await SKAgent_As_AFAgentAsync();
|
||||
await AFAgentAsync();
|
||||
|
||||
async Task SKAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent ===\n");
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model, enableCodeInterpreter: true);
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent agent = new(assistant, assistantsClient);
|
||||
|
||||
// Create a thread for the agent conversation.
|
||||
var thread = new OpenAIAssistantAgentThread(assistantsClient);
|
||||
|
||||
// Respond to user input
|
||||
await foreach (var content in agent.InvokeAsync(userInput, thread))
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(content.Message.Content))
|
||||
{
|
||||
bool isCode = content.Message.Metadata?.ContainsKey(OpenAIAssistantAgent.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 assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task SKAgent_As_AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== SK Agent Converted as an AF Agent ===\n");
|
||||
|
||||
// Define the assistant
|
||||
Assistant assistant = await assistantsClient.CreateAssistantAsync(model, enableCodeInterpreter: true);
|
||||
|
||||
// Create the agent
|
||||
OpenAIAssistantAgent skAgent = new(assistant, assistantsClient);
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
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?> ?? [])
|
||||
{
|
||||
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}");
|
||||
}
|
||||
|
||||
// Check for 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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = await assistantsClient.CreateAIAgentAsync(model, tools: [new HostedCodeInterpreterTool()]);
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
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?> ?? [])
|
||||
{
|
||||
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}");
|
||||
}
|
||||
|
||||
// Check for 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 ChatClientAgentThread chatThread)
|
||||
{
|
||||
await assistantsClient.DeleteThreadAsync(chatThread.ConversationId);
|
||||
}
|
||||
await assistantsClient.DeleteAssistantAsync(agent.Id);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ 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.
|
||||
@@ -63,7 +64,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
var agent = skAgent.AsAIAgent();
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
@@ -80,17 +81,17 @@ async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient().AsIChatClient(model)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes.");
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Joker", instructions: "You are good at telling jokes.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new() { MaxOutputTokens = 8000 });
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
var result = await agent.RunAsync(userInput, session, agentOptions);
|
||||
Console.WriteLine(result);
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
+7
-6
@@ -6,6 +6,7 @@ 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.
|
||||
@@ -131,7 +132,7 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
#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 = agent.GetNewThread();
|
||||
var thread = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
@@ -176,10 +177,10 @@ async Task AFAgentAsync()
|
||||
{
|
||||
Console.WriteLine("\n=== AF Agent ===\n");
|
||||
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient().AsIChatClient(model)
|
||||
.CreateAIAgent(name: "Thinker", instructions: "You are at thinking hard before answering.");
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Thinker", instructions: "You are at thinking hard before answering.");
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
var session = await agent.CreateSessionAsync();
|
||||
var agentOptions = new ChatClientAgentRunOptions(new()
|
||||
{
|
||||
MaxOutputTokens = 8000,
|
||||
@@ -190,7 +191,7 @@ async Task AFAgentAsync()
|
||||
}
|
||||
});
|
||||
|
||||
var result = await agent.RunAsync(userInput, thread, agentOptions);
|
||||
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
|
||||
@@ -203,7 +204,7 @@ async Task AFAgentAsync()
|
||||
Console.WriteLine($"Assistant: \n{assistantText}\n---\n");
|
||||
|
||||
Console.WriteLine("---");
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, thread, agentOptions))
|
||||
await foreach (var update in agent.RunStreamingAsync(userInput, session, agentOptions))
|
||||
{
|
||||
var thinkingContents = update.Contents
|
||||
.OfType<TextReasoningContent>()
|
||||
|
||||
@@ -5,6 +5,7 @@ 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.
|
||||
@@ -63,7 +64,8 @@ async Task SKAgent_As_AFAgentAsync()
|
||||
|
||||
async Task AFAgentAsync()
|
||||
{
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient().AsIChatClient(model).CreateAIAgent(
|
||||
var agent = new OpenAIClient(apiKey).GetResponsesClient().AsAIAgent(
|
||||
model: model,
|
||||
instructions: "You are a helpful assistant",
|
||||
tools: [AIFunctionFactory.Create(GetWeather)]);
|
||||
|
||||
|
||||
+3
-2
@@ -5,6 +5,7 @@ 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.
|
||||
@@ -65,8 +66,8 @@ async Task AFAgentAsync()
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddTransient((sp) => new OpenAIClient(apiKey)
|
||||
.GetResponsesClient().AsIChatClient(model)
|
||||
.CreateAIAgent(name: "Joker", instructions: "You are good at telling jokes."));
|
||||
.GetResponsesClient()
|
||||
.AsAIAgent(model: model, name: "Joker", instructions: "You are good at telling jokes."));
|
||||
|
||||
await using ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
|
||||
var agent = serviceProvider.GetRequiredService<AIAgent>();
|
||||
|
||||
@@ -50,7 +50,7 @@ internal sealed class SemanticKernelAIAgent : MAAI.AIAgent
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Id => this._innerAgent.Id;
|
||||
protected override string? IdCore => this._innerAgent.Id;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string? Name => this._innerAgent.Name;
|
||||
@@ -59,19 +59,31 @@ internal sealed class SemanticKernelAIAgent : MAAI.AIAgent
|
||||
public override string? Description => this._innerAgent.Description;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override MAAI.AgentThread DeserializeThread(JsonElement serializedThread, JsonSerializerOptions? jsonSerializerOptions = null)
|
||||
=> new SemanticKernelAIAgentThread(this._threadDeserializationFactory(serializedThread, jsonSerializerOptions), this._threadSerializer);
|
||||
protected override ValueTask<MAAI.AgentSession> CreateSessionCoreAsync(CancellationToken cancellationToken = default)
|
||||
=> new(new SemanticKernelAIAgentSession(this._threadFactory()));
|
||||
|
||||
/// <inheritdoc />
|
||||
public override MAAI.AgentThread GetNewThread() => new SemanticKernelAIAgentThread(this._threadFactory(), this._threadSerializer);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<MAAI.AgentRunResponse> RunAsync(IEnumerable<ChatMessage> messages, MAAI.AgentThread? thread = null, MAAI.AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
protected override ValueTask<JsonElement> SerializeSessionCoreAsync(MAAI.AgentSession session, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
thread ??= this.GetNewThread();
|
||||
if (thread is not SemanticKernelAIAgentThread typedThread)
|
||||
if (session is not SemanticKernelAIAgentSession typedSession)
|
||||
{
|
||||
throw new InvalidOperationException("The provided thread is not compatible with the agent. Only threads created by the agent can be used.");
|
||||
throw new InvalidOperationException("The provided session is not compatible with the agent. Only sessions created by the agent can be used.");
|
||||
}
|
||||
|
||||
return new(this._threadSerializer(typedSession.InnerThread, jsonSerializerOptions));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override ValueTask<MAAI.AgentSession> DeserializeSessionCoreAsync(JsonElement serializedState, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default)
|
||||
=> new(new SemanticKernelAIAgentSession(this._threadDeserializationFactory(serializedState, jsonSerializerOptions)));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<MAAI.AgentResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, MAAI.AgentSession? session = null, MAAI.AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
session ??= await this.CreateSessionCoreAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (session is not SemanticKernelAIAgentSession typedSession)
|
||||
{
|
||||
throw new InvalidOperationException("The provided session is not compatible with the agent. Only sessions created by the agent can be used.");
|
||||
}
|
||||
|
||||
List<ChatMessage> responseMessages = [];
|
||||
@@ -98,13 +110,14 @@ internal sealed class SemanticKernelAIAgent : MAAI.AIAgent
|
||||
};
|
||||
|
||||
AgentResponseItem<ChatMessageContent>? lastResponseItem = null;
|
||||
ChatMessage? lastResponseMessage = null;
|
||||
await foreach (var responseItem in this._innerAgent.InvokeAsync(messages.Select(x => x.ToChatMessageContent()).ToList(), typedThread.InnerThread, invokeOptions, cancellationToken).ConfigureAwait(false))
|
||||
await foreach (var responseItem in this._innerAgent.InvokeAsync(messages.Select(x => x.ToChatMessageContent()).ToList(), typedSession.InnerThread, invokeOptions, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
lastResponseItem = responseItem;
|
||||
}
|
||||
|
||||
return new MAAI.AgentRunResponse(responseMessages)
|
||||
var lastResponseMessage = lastResponseItem?.Message.ToChatMessage();
|
||||
|
||||
return new MAAI.AgentResponse(responseMessages)
|
||||
{
|
||||
AgentId = this._innerAgent.Id,
|
||||
RawRepresentation = lastResponseItem,
|
||||
@@ -114,23 +127,23 @@ internal sealed class SemanticKernelAIAgent : MAAI.AIAgent
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async IAsyncEnumerable<MAAI.AgentRunResponseUpdate> RunStreamingAsync(
|
||||
protected override async IAsyncEnumerable<MAAI.AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
MAAI.AgentThread? thread = null,
|
||||
MAAI.AgentSession? session = null,
|
||||
MAAI.AgentRunOptions? options = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
thread ??= this.GetNewThread();
|
||||
if (thread is not SemanticKernelAIAgentThread typedThread)
|
||||
session ??= await this.CreateSessionCoreAsync(cancellationToken).ConfigureAwait(false);
|
||||
if (session is not SemanticKernelAIAgentSession typedSession)
|
||||
{
|
||||
throw new InvalidOperationException("The provided thread is not compatible with the agent. Only threads created by the agent can be used.");
|
||||
throw new InvalidOperationException("The provided session is not compatible with the agent. Only sessions created by the agent can be used.");
|
||||
}
|
||||
|
||||
await foreach (var responseItem in this._innerAgent.InvokeStreamingAsync(messages.Select(x => x.ToChatMessageContent()).ToList(), typedThread.InnerThread, cancellationToken: cancellationToken).ConfigureAwait(false))
|
||||
await foreach (var responseItem in this._innerAgent.InvokeStreamingAsync(messages.Select(x => x.ToChatMessageContent()).ToList(), typedSession.InnerThread, cancellationToken: cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
var update = responseItem.Message.ToChatResponseUpdate();
|
||||
|
||||
yield return new MAAI.AgentRunResponseUpdate
|
||||
yield return new MAAI.AgentResponseUpdate
|
||||
{
|
||||
AuthorName = update.AuthorName,
|
||||
AgentId = this._innerAgent.Id,
|
||||
|
||||
+2
-12
@@ -2,23 +2,17 @@
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.Json;
|
||||
using MAAI = Microsoft.Agents.AI;
|
||||
|
||||
namespace Microsoft.SemanticKernel.Agents;
|
||||
|
||||
[Experimental("SKEXP0110")]
|
||||
internal sealed class SemanticKernelAIAgentThread : MAAI.AgentThread
|
||||
internal sealed class SemanticKernelAIAgentSession : MAAI.AgentSession
|
||||
{
|
||||
private readonly Func<AgentThread, JsonSerializerOptions?, JsonElement> _threadSerializer;
|
||||
|
||||
internal SemanticKernelAIAgentThread(AgentThread thread, Func<AgentThread, JsonSerializerOptions?, JsonElement> threadSerializer)
|
||||
internal SemanticKernelAIAgentSession(AgentThread thread)
|
||||
{
|
||||
Throw.IfNull(thread);
|
||||
Throw.IfNull(threadSerializer);
|
||||
|
||||
this.InnerThread = thread;
|
||||
this._threadSerializer = threadSerializer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -26,10 +20,6 @@ internal sealed class SemanticKernelAIAgentThread : MAAI.AgentThread
|
||||
/// </summary>
|
||||
public AgentThread InnerThread { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override JsonElement Serialize(JsonSerializerOptions? jsonSerializerOptions = null)
|
||||
=> this._threadSerializer(this.InnerThread, jsonSerializerOptions);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? GetService(Type serviceType, object? serviceKey = null)
|
||||
{
|
||||
@@ -3,11 +3,11 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using A2A;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.A2A;
|
||||
using Xunit;
|
||||
|
||||
namespace SemanticKernel.Agents.UnitTests.A2A;
|
||||
|
||||
public sealed class A2AAgentExtensionsTests
|
||||
@@ -40,7 +40,7 @@ public sealed class A2AAgentExtensionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_CreatesWorkingThreadFactory()
|
||||
public async Task AsAIAgent_CreatesWorkingThreadFactory()
|
||||
{
|
||||
// Arrange
|
||||
using var httpClient = new HttpClient();
|
||||
@@ -50,17 +50,17 @@ public sealed class A2AAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = a2aAgent.AsAIAgent();
|
||||
var thread = result.GetNewThread();
|
||||
var thread = await result.CreateSessionAsync();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<A2AAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
{
|
||||
// Arrange
|
||||
using var httpClient = new HttpClient();
|
||||
@@ -71,17 +71,17 @@ public sealed class A2AAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = a2aAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<A2AAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
{
|
||||
// Arrange
|
||||
using var httpClient = new HttpClient();
|
||||
@@ -93,18 +93,18 @@ public sealed class A2AAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = a2aAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<A2AAgentThread>(threadAdapter.InnerThread);
|
||||
Assert.Equal(threadId, threadAdapter.InnerThread.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
public async Task AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
{
|
||||
// Arrange
|
||||
using var httpClient = new HttpClient();
|
||||
@@ -116,10 +116,10 @@ public sealed class A2AAgentExtensionsTests
|
||||
var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId);
|
||||
|
||||
var result = a2aAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Act
|
||||
var serializedElement = thread.Serialize();
|
||||
var serializedElement = await result.SerializeSessionAsync(thread);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.String, serializedElement.ValueKind);
|
||||
|
||||
+17
-88
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SemanticKernel;
|
||||
@@ -11,76 +10,33 @@ using Xunit;
|
||||
|
||||
namespace SemanticKernel.Agents.UnitTests.AIAgent;
|
||||
|
||||
public sealed class SemanticKernelAIAgentThreadTests
|
||||
public sealed class SemanticKernelAIAgentSessionTests
|
||||
{
|
||||
[Fact]
|
||||
public void Constructor_InitializesProperties()
|
||||
{
|
||||
// Arrange
|
||||
var threadMock = new Mock<AgentThread>();
|
||||
JsonElement ThreadSerializer(AgentThread t, JsonSerializerOptions? o) => default;
|
||||
|
||||
// Act
|
||||
var adapter = new SemanticKernelAIAgentThread(threadMock.Object, ThreadSerializer);
|
||||
var adapter = new SemanticKernelAIAgentSession(threadMock.Object);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(threadMock.Object, adapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serialize_CallsThreadSerializer()
|
||||
{
|
||||
// Arrange
|
||||
var threadMock = new Mock<AgentThread>();
|
||||
var serializerCallCount = 0;
|
||||
var expectedJsonElement = JsonElement.Parse("{\"test\": \"value\"}");
|
||||
// AF 1.0: Serialize_CallsThreadSerializer test removed - serialization moved to agent.
|
||||
// See SemanticKernelAIAgentTests for serialization coverage.
|
||||
|
||||
JsonElement ThreadSerializer(AgentThread t, JsonSerializerOptions? o)
|
||||
{
|
||||
serializerCallCount++;
|
||||
Assert.Same(threadMock.Object, t);
|
||||
return expectedJsonElement;
|
||||
}
|
||||
|
||||
var adapter = new SemanticKernelAIAgentThread(threadMock.Object, ThreadSerializer);
|
||||
|
||||
// Act
|
||||
var result = adapter.Serialize();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1, serializerCallCount);
|
||||
Assert.Equal(expectedJsonElement.ToString(), result.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serialize_WithJsonSerializerOptions_PassesOptionsToSerializer()
|
||||
{
|
||||
// Arrange
|
||||
var threadMock = new Mock<AgentThread>();
|
||||
var expectedOptions = new JsonSerializerOptions();
|
||||
JsonSerializerOptions? capturedOptions = null;
|
||||
|
||||
JsonElement ThreadSerializer(AgentThread t, JsonSerializerOptions? o)
|
||||
{
|
||||
capturedOptions = o;
|
||||
return default;
|
||||
}
|
||||
|
||||
var adapter = new SemanticKernelAIAgentThread(threadMock.Object, ThreadSerializer);
|
||||
|
||||
// Act
|
||||
adapter.Serialize(expectedOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Same(expectedOptions, capturedOptions);
|
||||
}
|
||||
// AF 1.0: Serialize() moved from AgentSession to AIAgent.SerializeSessionCoreAsync().
|
||||
// These tests are covered by SemanticKernelAIAgentTests instead.
|
||||
|
||||
[Fact]
|
||||
public void GetService_WithAgentThreadType_ReturnsInnerThread()
|
||||
{
|
||||
// Arrange
|
||||
var threadMock = new Mock<AgentThread>();
|
||||
var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default);
|
||||
var adapter = new SemanticKernelAIAgentSession(threadMock.Object);
|
||||
|
||||
// Act
|
||||
var result = adapter.GetService(typeof(AgentThread));
|
||||
@@ -94,7 +50,7 @@ public sealed class SemanticKernelAIAgentThreadTests
|
||||
{
|
||||
// Arrange
|
||||
var threadMock = new Mock<AgentThread>();
|
||||
var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default);
|
||||
var adapter = new SemanticKernelAIAgentSession(threadMock.Object);
|
||||
var serviceKey = new object();
|
||||
|
||||
// Act
|
||||
@@ -109,7 +65,7 @@ public sealed class SemanticKernelAIAgentThreadTests
|
||||
{
|
||||
// Arrange
|
||||
var threadMock = new Mock<AgentThread>();
|
||||
var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default);
|
||||
var adapter = new SemanticKernelAIAgentSession(threadMock.Object);
|
||||
|
||||
// Act
|
||||
var result = adapter.GetService(typeof(string));
|
||||
@@ -123,56 +79,29 @@ public sealed class SemanticKernelAIAgentThreadTests
|
||||
{
|
||||
// Arrange
|
||||
var threadMock = new Mock<AgentThread>();
|
||||
var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default);
|
||||
var adapter = new SemanticKernelAIAgentSession(threadMock.Object);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentNullException>(() => adapter.GetService(null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serialize_WithNullOptions_CallsSerializerWithNull()
|
||||
{
|
||||
// Arrange
|
||||
var threadMock = new Mock<AgentThread>();
|
||||
JsonSerializerOptions? capturedOptions = new();
|
||||
|
||||
JsonElement ThreadSerializer(AgentThread t, JsonSerializerOptions? o)
|
||||
{
|
||||
capturedOptions = o;
|
||||
return default;
|
||||
}
|
||||
|
||||
var adapter = new SemanticKernelAIAgentThread(threadMock.Object, ThreadSerializer);
|
||||
|
||||
// Act
|
||||
adapter.Serialize(null);
|
||||
|
||||
// Assert
|
||||
Assert.Null(capturedOptions);
|
||||
}
|
||||
// AF 1.0: Serialize_WithNullOptions test removed - serialization moved to agent.
|
||||
|
||||
[Fact]
|
||||
public void Constructor_WithNullThread_ThrowsArgumentNullException()
|
||||
{
|
||||
// Arrange & Act
|
||||
JsonElement ThreadSerializer(AgentThread t, JsonSerializerOptions? o) => default;
|
||||
Assert.Throws<ArgumentNullException>(() => new SemanticKernelAIAgentThread(null!, ThreadSerializer));
|
||||
Assert.Throws<ArgumentNullException>(() => new SemanticKernelAIAgentSession(null!));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_WithNullSerializer_ThrowsArgumentNullException()
|
||||
{
|
||||
// Arrange & Act
|
||||
var threadMock = new Mock<AgentThread>();
|
||||
Assert.Throws<ArgumentNullException>(() => new SemanticKernelAIAgentThread(threadMock.Object, null!));
|
||||
}
|
||||
// Constructor_WithNullSerializer test removed: serializer is no longer stored on the session.
|
||||
|
||||
[Fact]
|
||||
public void GetService_WithBaseClassType_ReturnsInnerThread()
|
||||
{
|
||||
// Arrange
|
||||
var concreteThread = new TestAgentThread();
|
||||
var adapter = new SemanticKernelAIAgentThread(concreteThread, (t, o) => default);
|
||||
var adapter = new SemanticKernelAIAgentSession(concreteThread);
|
||||
|
||||
// Act
|
||||
var result = adapter.GetService(typeof(AgentThread));
|
||||
@@ -186,7 +115,7 @@ public sealed class SemanticKernelAIAgentThreadTests
|
||||
{
|
||||
// Arrange
|
||||
var concreteThread = new TestAgentThread();
|
||||
var adapter = new SemanticKernelAIAgentThread(concreteThread, (t, o) => default);
|
||||
var adapter = new SemanticKernelAIAgentSession(concreteThread);
|
||||
|
||||
// Act
|
||||
var result = adapter.GetService(typeof(TestAgentThread));
|
||||
@@ -200,7 +129,7 @@ public sealed class SemanticKernelAIAgentThreadTests
|
||||
{
|
||||
// Arrange
|
||||
var threadMock = new Mock<AgentThread>();
|
||||
var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default);
|
||||
var adapter = new SemanticKernelAIAgentSession(threadMock.Object);
|
||||
|
||||
// Act
|
||||
var result = adapter.GetService(typeof(TestAgentThread));
|
||||
@@ -214,7 +143,7 @@ public sealed class SemanticKernelAIAgentThreadTests
|
||||
{
|
||||
// Arrange
|
||||
var threadMock = new Mock<AgentThread>();
|
||||
var adapter = new SemanticKernelAIAgentThread(threadMock.Object, (t, o) => default);
|
||||
var adapter = new SemanticKernelAIAgentSession(threadMock.Object);
|
||||
|
||||
// Act
|
||||
var result = adapter.GetService(typeof(IServiceProvider));
|
||||
@@ -84,7 +84,7 @@ public sealed class SemanticKernelAIAgentTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeserializeThread_ReturnsSemanticKernelAIAgentThread()
|
||||
public async Task DeserializeThread_ReturnsSemanticKernelAIAgentSession()
|
||||
{
|
||||
// Arrange
|
||||
var agentMock = new Mock<Agent>();
|
||||
@@ -95,14 +95,14 @@ public sealed class SemanticKernelAIAgentTests
|
||||
var json = JsonElement.Parse("{}");
|
||||
|
||||
// Act
|
||||
var result = adapter.DeserializeThread(json);
|
||||
var result = await adapter.DeserializeSessionAsync(json);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(result);
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetNewThread_ReturnsSemanticKernelAIAgentThread()
|
||||
public async Task GetNewThread_ReturnsSemanticKernelAIAgentSession()
|
||||
{
|
||||
// Arrange
|
||||
var agentMock = new Mock<Agent>();
|
||||
@@ -111,15 +111,15 @@ public sealed class SemanticKernelAIAgentTests
|
||||
var adapter = new SemanticKernelAIAgent(agentMock.Object, () => expectedThread, (e, o) => expectedThread, ThreadSerializer);
|
||||
|
||||
// Act
|
||||
var result = adapter.GetNewThread();
|
||||
var result = await adapter.CreateSessionAsync();
|
||||
|
||||
// Assert
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(result);
|
||||
Assert.Equal(expectedThread, ((SemanticKernelAIAgentThread)result).InnerThread);
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(result);
|
||||
Assert.Equal(expectedThread, ((SemanticKernelAIAgentSession)result).InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeserializeThread_CallsDeserializationFactory()
|
||||
public async Task DeserializeThread_CallsDeserializationFactory()
|
||||
{
|
||||
// Arrange
|
||||
var agentMock = new Mock<Agent>();
|
||||
@@ -136,15 +136,15 @@ public sealed class SemanticKernelAIAgentTests
|
||||
var json = JsonElement.Parse("{}");
|
||||
|
||||
// Act
|
||||
var result = adapter.DeserializeThread(json);
|
||||
var result = await adapter.DeserializeSessionAsync(json);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1, factoryCallCount);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(result);
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetNewThread_CallsThreadFactory()
|
||||
public async Task GetNewThread_CallsThreadFactory()
|
||||
{
|
||||
// Arrange
|
||||
var agentMock = new Mock<Agent>();
|
||||
@@ -160,11 +160,11 @@ public sealed class SemanticKernelAIAgentTests
|
||||
var adapter = new SemanticKernelAIAgent(agentMock.Object, ThreadFactory, (e, o) => expectedThread, (t, o) => default);
|
||||
|
||||
// Act
|
||||
var result = adapter.GetNewThread();
|
||||
var result = await adapter.CreateSessionAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1, factoryCallCount);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(result);
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -211,13 +211,13 @@ public sealed class SemanticKernelAIAgentTests
|
||||
yield return new AgentResponseItem<ChatMessageContent>(message, innerThread);
|
||||
}
|
||||
|
||||
var thread = new SemanticKernelAIAgentThread(innerThread, (t, o) => default);
|
||||
var thread = new SemanticKernelAIAgentSession(innerThread);
|
||||
|
||||
// Act
|
||||
var result = await adapter.RunAsync("Input text", thread);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<MAAI.AgentRunResponse>(result);
|
||||
Assert.IsType<MAAI.AgentResponse>(result);
|
||||
Assert.Equal("Final response", result.Text);
|
||||
agentMock.Verify(a => a.InvokeAsync(
|
||||
It.Is<List<ChatMessageContent>>(x => x.First().Content == "Input text"),
|
||||
@@ -246,13 +246,13 @@ public sealed class SemanticKernelAIAgentTests
|
||||
yield return new AgentResponseItem<StreamingChatMessageContent>(new StreamingChatMessageContent(AuthorRole.Assistant, "Final response"), innerThread);
|
||||
}
|
||||
|
||||
var thread = new SemanticKernelAIAgentThread(innerThread, (t, o) => default);
|
||||
var thread = new SemanticKernelAIAgentSession(innerThread);
|
||||
|
||||
// Act
|
||||
var results = await adapter.RunStreamingAsync("Input text", thread).ToListAsync();
|
||||
|
||||
// Assert
|
||||
Assert.IsType<MAAI.AgentRunResponseUpdate>(results.First());
|
||||
Assert.IsType<MAAI.AgentResponseUpdate>(results.First());
|
||||
Assert.Equal("Final response", results.First().Text);
|
||||
agentMock.Verify(a => a.InvokeStreamingAsync(
|
||||
It.Is<List<ChatMessageContent>>(x => x.First().Content == "Input text"),
|
||||
@@ -288,13 +288,13 @@ public sealed class SemanticKernelAIAgentTests
|
||||
yield return new AgentResponseItem<ChatMessageContent>(final, thread);
|
||||
}
|
||||
|
||||
var threadWrapper = new SemanticKernelAIAgentThread(innerThread, (t, o) => default);
|
||||
var threadWrapper = new SemanticKernelAIAgentSession(innerThread);
|
||||
|
||||
// Act
|
||||
var response = await adapter.RunAsync("input", threadWrapper);
|
||||
|
||||
// Assert
|
||||
// Use reflection to inspect Messages collection inside AgentRunResponse
|
||||
// Use reflection to inspect Messages collection inside AgentResponse
|
||||
var messages = response.Messages;
|
||||
var contents = messages.First().Contents;
|
||||
Assert.Single(contents); // Duplicate text content should have been removed
|
||||
@@ -327,7 +327,7 @@ public sealed class SemanticKernelAIAgentTests
|
||||
yield return new AgentResponseItem<ChatMessageContent>(final, thread);
|
||||
}
|
||||
|
||||
var threadWrapper = new SemanticKernelAIAgentThread(innerThread, (t, o) => default);
|
||||
var threadWrapper = new SemanticKernelAIAgentSession(innerThread);
|
||||
|
||||
// Act
|
||||
var response = await adapter.RunAsync("input", threadWrapper);
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace SemanticKernel.Agents.UnitTests;
|
||||
|
||||
public sealed class AgentExtensionsTests
|
||||
@@ -77,7 +77,7 @@ public sealed class AgentExtensionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_WithValidFactories_CreatesWorkingAdapter()
|
||||
public async Task AsAIAgent_WithValidFactories_CreatesWorkingAdapter()
|
||||
{
|
||||
// Arrange
|
||||
var agentMock = new Mock<Agent>();
|
||||
@@ -95,17 +95,17 @@ public sealed class AgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = agentMock.Object.AsAIAgent(ThreadFactory, ThreadDeserializationFactory, ThreadSerializer);
|
||||
var thread = result.GetNewThread();
|
||||
var thread = await result.CreateSessionAsync();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.Equal(1, factoryCallCount);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
Assert.Same(expectedThread, ((SemanticKernelAIAgentThread)thread).InnerThread);
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
Assert.Same(expectedThread, ((SemanticKernelAIAgentSession)thread).InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_WithDeserializationFactory_CreatesWorkingAdapter()
|
||||
public async Task AsAIAgent_WithDeserializationFactory_CreatesWorkingAdapter()
|
||||
{
|
||||
// Arrange
|
||||
var agentMock = new Mock<Agent>();
|
||||
@@ -125,12 +125,12 @@ public sealed class AgentExtensionsTests
|
||||
// Act
|
||||
var result = agentMock.Object.AsAIAgent(ThreadFactory, ThreadDeserializationFactory, ThreadSerializer);
|
||||
var json = JsonElement.Parse("{}");
|
||||
var thread = result.DeserializeThread(json);
|
||||
var thread = await result.DeserializeSessionAsync(json);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.Equal(1, deserializationCallCount);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
Assert.Same(expectedThread, ((SemanticKernelAIAgentThread)thread).InnerThread);
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
Assert.Same(expectedThread, ((SemanticKernelAIAgentSession)thread).InnerThread);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
using System;
|
||||
using System.ClientModel.Primitives;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Azure.AI.Agents.Persistent;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.AzureAI;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace SemanticKernel.Agents.UnitTests.AzureAI;
|
||||
|
||||
public sealed class AzureAIAgentExtensionsTests
|
||||
@@ -49,24 +49,24 @@ public sealed class AzureAIAgentExtensionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_CreatesWorkingThreadFactory()
|
||||
public async Task AsAIAgent_CreatesWorkingThreadFactory()
|
||||
{
|
||||
var clientMock = new Mock<Azure.AI.Agents.Persistent.PersistentAgentsClient>();
|
||||
var azureAIAgent = new AzureAIAgent(s_agentMetadata, clientMock.Object);
|
||||
|
||||
// Act
|
||||
var result = azureAIAgent.AsAIAgent();
|
||||
var thread = result.GetNewThread();
|
||||
var thread = await result.CreateSessionAsync();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<AzureAIAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
{
|
||||
// Arrange
|
||||
var clientMock = new Mock<Azure.AI.Agents.Persistent.PersistentAgentsClient>();
|
||||
@@ -75,17 +75,17 @@ public sealed class AzureAIAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = azureAIAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<AzureAIAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
{
|
||||
// Arrange
|
||||
var clientMock = new Mock<Azure.AI.Agents.Persistent.PersistentAgentsClient>();
|
||||
@@ -96,18 +96,18 @@ public sealed class AzureAIAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = azureAIAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<AzureAIAgentThread>(threadAdapter.InnerThread);
|
||||
Assert.Equal(threadId, threadAdapter.InnerThread.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
public async Task AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
{
|
||||
// Arrange
|
||||
var clientMock = new Mock<Azure.AI.Agents.Persistent.PersistentAgentsClient>();
|
||||
@@ -118,10 +118,10 @@ public sealed class AzureAIAgentExtensionsTests
|
||||
var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId);
|
||||
|
||||
var result = azureAIAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Act
|
||||
var serializedElement = thread.Serialize();
|
||||
var serializedElement = await result.SerializeSessionAsync(thread);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.String, serializedElement.ValueKind);
|
||||
|
||||
@@ -59,7 +59,7 @@ public class BedrockAgentExtensionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_CreatesWorkingThreadFactory()
|
||||
public async Task AsAIAgent_CreatesWorkingThreadFactory()
|
||||
{
|
||||
// Arrange
|
||||
var (mockClient, mockRuntimeClient) = this.CreateMockClients();
|
||||
@@ -67,17 +67,17 @@ public class BedrockAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = bedrockAgent.AsAIAgent();
|
||||
var thread = result.GetNewThread();
|
||||
var thread = await result.CreateSessionAsync();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<BedrockAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
{
|
||||
// Arrange
|
||||
var (mockClient, mockRuntimeClient) = this.CreateMockClients();
|
||||
@@ -86,17 +86,17 @@ public class BedrockAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = bedrockAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<BedrockAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
{
|
||||
// Arrange
|
||||
var (mockClient, mockRuntimeClient) = this.CreateMockClients();
|
||||
@@ -106,17 +106,17 @@ public class BedrockAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = bedrockAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<BedrockAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
public async Task AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
{
|
||||
// Arrange
|
||||
var (mockClient, mockRuntimeClient) = this.CreateMockClients();
|
||||
@@ -126,10 +126,10 @@ public class BedrockAgentExtensionsTests
|
||||
var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId);
|
||||
|
||||
var result = bedrockAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Act
|
||||
var serializedElement = thread.Serialize();
|
||||
var serializedElement = await result.SerializeSessionAsync(thread);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.String, serializedElement.ValueKind);
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.CopilotStudio.Client;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.Copilot;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace SemanticKernel.Agents.UnitTests.Copilot;
|
||||
|
||||
public sealed class CopilotStudioAgentExtensionsTests
|
||||
@@ -38,7 +38,7 @@ public sealed class CopilotStudioAgentExtensionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_CreatesWorkingThreadFactory()
|
||||
public async Task AsAIAgent_CreatesWorkingThreadFactory()
|
||||
{
|
||||
// Arrange
|
||||
var clientMock = new Mock<CopilotClient>(null, null, null, null);
|
||||
@@ -46,17 +46,17 @@ public sealed class CopilotStudioAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = copilotStudioAgent.AsAIAgent();
|
||||
var thread = result.GetNewThread();
|
||||
var thread = await result.CreateSessionAsync();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<CopilotStudioAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
{
|
||||
// Arrange
|
||||
var clientMock = new Mock<CopilotClient>(null, null, null, null);
|
||||
@@ -65,17 +65,17 @@ public sealed class CopilotStudioAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = copilotStudioAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<CopilotStudioAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
{
|
||||
// Arrange
|
||||
var clientMock = new Mock<CopilotClient>(null, null, null, null);
|
||||
@@ -85,17 +85,17 @@ public sealed class CopilotStudioAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = copilotStudioAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<CopilotStudioAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
public async Task AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
{
|
||||
// Arrange
|
||||
var clientMock = new Mock<CopilotClient>(null, null, null, null);
|
||||
@@ -105,10 +105,10 @@ public sealed class CopilotStudioAgentExtensionsTests
|
||||
var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId);
|
||||
|
||||
var result = copilotStudioAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Act
|
||||
var serializedElement = thread.Serialize();
|
||||
var serializedElement = await result.SerializeSessionAsync(thread);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.String, serializedElement.ValueKind);
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using Xunit;
|
||||
|
||||
namespace SemanticKernel.Agents.UnitTests.Core;
|
||||
|
||||
public sealed class ChatCompletionAgentExtensionsTests
|
||||
@@ -39,7 +39,7 @@ public sealed class ChatCompletionAgentExtensionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_CreatesWorkingThreadFactory()
|
||||
public async Task AsAIAgent_CreatesWorkingThreadFactory()
|
||||
{
|
||||
// Arrange
|
||||
var chatCompletionAgent = new ChatCompletionAgent()
|
||||
@@ -50,17 +50,17 @@ public sealed class ChatCompletionAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = chatCompletionAgent.AsAIAgent();
|
||||
var thread = result.GetNewThread();
|
||||
var thread = await result.CreateSessionAsync();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<ChatHistoryAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithNullChatHistory_CreatesNewThread()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithNullChatHistory_CreatesNewThread()
|
||||
{
|
||||
// Arrange
|
||||
var chatCompletionAgent = new ChatCompletionAgent()
|
||||
@@ -72,17 +72,17 @@ public sealed class ChatCompletionAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = chatCompletionAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<ChatHistoryAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithValidChatHistory_CreatesThreadWithHistory()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithValidChatHistory_CreatesThreadWithHistory()
|
||||
{
|
||||
// Arrange
|
||||
var chatCompletionAgent = new ChatCompletionAgent()
|
||||
@@ -98,19 +98,19 @@ public sealed class ChatCompletionAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = chatCompletionAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<ChatHistoryAgentThread>(threadAdapter.InnerThread);
|
||||
var chatHistoryThread = (ChatHistoryAgentThread)threadAdapter.InnerThread;
|
||||
Assert.Equal(2, chatHistoryThread.ChatHistory.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadSerializer_SerializesChatHistory()
|
||||
public async Task AsAIAgent_ThreadSerializer_SerializesChatHistory()
|
||||
{
|
||||
// Arrange
|
||||
var chatCompletionAgent = new ChatCompletionAgent()
|
||||
@@ -126,10 +126,10 @@ public sealed class ChatCompletionAgentExtensionsTests
|
||||
var jsonElement = JsonSerializer.SerializeToElement(chatHistory);
|
||||
|
||||
var result = chatCompletionAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Act
|
||||
var serializedElement = thread.Serialize();
|
||||
var serializedElement = await result.SerializeSessionAsync(thread);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.Array, serializedElement.ValueKind);
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
using System;
|
||||
using System.ClientModel.Primitives;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Moq;
|
||||
using OpenAI.Assistants;
|
||||
using Xunit;
|
||||
|
||||
namespace SemanticKernel.Agents.UnitTests.OpenAI;
|
||||
|
||||
public sealed class OpenAIAssistantAgentExtensionsTests
|
||||
@@ -54,7 +54,7 @@ public sealed class OpenAIAssistantAgentExtensionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_CreatesWorkingThreadFactory()
|
||||
public async Task AsAIAgent_CreatesWorkingThreadFactory()
|
||||
{
|
||||
// Arrange
|
||||
var clientMock = new Mock<AssistantClient>();
|
||||
@@ -62,17 +62,17 @@ public sealed class OpenAIAssistantAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = assistantAgent.AsAIAgent();
|
||||
var thread = result.GetNewThread();
|
||||
var thread = await result.CreateSessionAsync();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<OpenAIAssistantAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
{
|
||||
// Arrange
|
||||
var clientMock = new Mock<AssistantClient>();
|
||||
@@ -81,17 +81,17 @@ public sealed class OpenAIAssistantAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = assistantAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<OpenAIAssistantAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
{
|
||||
// Arrange
|
||||
var clientMock = new Mock<AssistantClient>();
|
||||
@@ -101,18 +101,18 @@ public sealed class OpenAIAssistantAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = assistantAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<OpenAIAssistantAgentThread>(threadAdapter.InnerThread);
|
||||
Assert.Equal(threadId, threadAdapter.InnerThread.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
public async Task AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
{
|
||||
// Arrange
|
||||
var clientMock = new Mock<AssistantClient>();
|
||||
@@ -122,10 +122,10 @@ public sealed class OpenAIAssistantAgentExtensionsTests
|
||||
var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId);
|
||||
|
||||
var result = assistantAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Act
|
||||
var serializedElement = thread.Serialize();
|
||||
var serializedElement = await result.SerializeSessionAsync(thread);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.String, serializedElement.ValueKind);
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
using System;
|
||||
using System.ClientModel;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SemanticKernel.Agents;
|
||||
using Microsoft.SemanticKernel.Agents.OpenAI;
|
||||
using Microsoft.SemanticKernel.ChatCompletion;
|
||||
using OpenAI.Responses;
|
||||
using Xunit;
|
||||
|
||||
namespace SemanticKernel.Agents.UnitTests.OpenAI;
|
||||
|
||||
public sealed class OpenAIResponseAgentExtensionsTests
|
||||
@@ -39,7 +39,7 @@ public sealed class OpenAIResponseAgentExtensionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_CreatesWorkingThreadFactoryStoreTrue()
|
||||
public async Task AsAIAgent_CreatesWorkingThreadFactoryStoreTrue()
|
||||
{
|
||||
// Arrange
|
||||
var responseClient = new ResponsesClient(new ApiKeyCredential("apikey"));
|
||||
@@ -50,17 +50,17 @@ public sealed class OpenAIResponseAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = responseAgent.AsAIAgent();
|
||||
var thread = result.GetNewThread();
|
||||
var thread = await result.CreateSessionAsync();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<OpenAIResponseAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_CreatesWorkingThreadFactoryStoreFalse()
|
||||
public async Task AsAIAgent_CreatesWorkingThreadFactoryStoreFalse()
|
||||
{
|
||||
// Arrange
|
||||
var responseClient = new ResponsesClient(new ApiKeyCredential("apikey"));
|
||||
@@ -71,17 +71,17 @@ public sealed class OpenAIResponseAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = responseAgent.AsAIAgent();
|
||||
var thread = result.GetNewThread();
|
||||
var thread = await result.CreateSessionAsync();
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<ChatHistoryAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithNullAgentId_CreatesNewThread()
|
||||
{
|
||||
// Arrange
|
||||
var responseClient = new ResponsesClient(new ApiKeyCredential("apikey"));
|
||||
@@ -93,17 +93,17 @@ public sealed class OpenAIResponseAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = responseAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<OpenAIResponseAgentThread>(threadAdapter.InnerThread);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithValidAgentId_CreatesThreadWithId()
|
||||
{
|
||||
// Arrange
|
||||
var responseClient = new ResponsesClient(new ApiKeyCredential("apikey"));
|
||||
@@ -116,18 +116,18 @@ public sealed class OpenAIResponseAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = responseAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
Assert.IsType<OpenAIResponseAgentThread>(threadAdapter.InnerThread);
|
||||
Assert.Equal(threadId, threadAdapter.InnerThread.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
public async Task AsAIAgent_ThreadSerializer_SerializesThreadId()
|
||||
{
|
||||
// Arrange
|
||||
var responseClient = new ResponsesClient(new ApiKeyCredential("apikey"));
|
||||
@@ -140,10 +140,10 @@ public sealed class OpenAIResponseAgentExtensionsTests
|
||||
var jsonElement = JsonSerializer.SerializeToElement(expectedThreadId);
|
||||
|
||||
var result = responseAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Act
|
||||
var serializedElement = thread.Serialize();
|
||||
var serializedElement = await result.SerializeSessionAsync(thread);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.String, serializedElement.ValueKind);
|
||||
@@ -151,7 +151,7 @@ public sealed class OpenAIResponseAgentExtensionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithNullJson_CreatesThreadWithEmptyChatHistory()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithNullJson_CreatesThreadWithEmptyChatHistory()
|
||||
{
|
||||
var responseClient = new ResponsesClient(new ApiKeyCredential("apikey"));
|
||||
var responseAgent = new OpenAIResponseAgent(responseClient);
|
||||
@@ -159,18 +159,18 @@ public sealed class OpenAIResponseAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = responseAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
var chatHistoryAgentThread = Assert.IsType<ChatHistoryAgentThread>(threadAdapter.InnerThread);
|
||||
Assert.Empty(chatHistoryAgentThread.ChatHistory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadDeserializationFactory_WithChatHistory_CreatesThreadWithChatHistory()
|
||||
public async Task AsAIAgent_ThreadDeserializationFactory_WithChatHistory_CreatesThreadWithChatHistory()
|
||||
{
|
||||
var responseClient = new ResponsesClient(new ApiKeyCredential("apikey"));
|
||||
var responseAgent = new OpenAIResponseAgent(responseClient);
|
||||
@@ -179,12 +179,12 @@ public sealed class OpenAIResponseAgentExtensionsTests
|
||||
|
||||
// Act
|
||||
var result = responseAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(thread);
|
||||
Assert.IsType<SemanticKernelAIAgentThread>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentThread)thread;
|
||||
Assert.IsType<SemanticKernelAIAgentSession>(thread);
|
||||
var threadAdapter = (SemanticKernelAIAgentSession)thread;
|
||||
var chatHistoryAgentThread = Assert.IsType<ChatHistoryAgentThread>(threadAdapter.InnerThread);
|
||||
Assert.Single(chatHistoryAgentThread.ChatHistory);
|
||||
var firstMessage = chatHistoryAgentThread.ChatHistory[0];
|
||||
@@ -193,7 +193,7 @@ public sealed class OpenAIResponseAgentExtensionsTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AsAIAgent_ThreadSerializer_SerializesChatHistory()
|
||||
public async Task AsAIAgent_ThreadSerializer_SerializesChatHistory()
|
||||
{
|
||||
// Arrange
|
||||
var responseClient = new ResponsesClient(new ApiKeyCredential("apikey"));
|
||||
@@ -202,10 +202,10 @@ public sealed class OpenAIResponseAgentExtensionsTests
|
||||
var jsonElement = JsonSerializer.SerializeToElement(expectedChatHistory);
|
||||
|
||||
var result = responseAgent.AsAIAgent();
|
||||
var thread = result.DeserializeThread(jsonElement);
|
||||
var thread = await result.DeserializeSessionAsync(jsonElement);
|
||||
|
||||
// Act
|
||||
var serializedElement = thread.Serialize();
|
||||
var serializedElement = await result.SerializeSessionAsync(thread);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.Array, serializedElement.ValueKind);
|
||||
|
||||
@@ -59,6 +59,20 @@ public sealed class KernelTests : IDisposable
|
||||
[Fact]
|
||||
public async Task FunctionUsageMetricsAreCapturedByTelemetryAsExpected()
|
||||
{
|
||||
// Arrange: Set up the response and create the function FIRST so we can filter
|
||||
// measurements by this specific function's name (avoids parallel test contamination).
|
||||
this._multiMessageHandlerStub.ResponsesToReturn.Add(
|
||||
new HttpResponseMessage(System.Net.HttpStatusCode.OK) { Content = new StringContent(ChatCompletionResponse) }
|
||||
);
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
builder.Services.AddSingleton(this._mockLoggerFactory.Object);
|
||||
builder.AddAzureOpenAIChatCompletion(deploymentName: "model", endpoint: "https://localhost", apiKey: "apiKey", httpClient: this._httpClient);
|
||||
var kernel = builder.Build();
|
||||
|
||||
var kernelFunction = KernelFunctionFactory.CreateFromPrompt("prompt", loggerFactory: this._mockLoggerFactory.Object);
|
||||
var expectedFunctionName = kernelFunction.Name;
|
||||
|
||||
// Set up a MeterListener to capture the measurements
|
||||
using MeterListener listener = new();
|
||||
var isPublished = false;
|
||||
@@ -81,10 +95,23 @@ public sealed class KernelTests : IDisposable
|
||||
|
||||
listener.SetMeasurementEventCallback<long>((instrument, measurement, tags, state) =>
|
||||
{
|
||||
if (instrument.Name is "semantic_kernel.function.invocation.token_usage.prompt" or
|
||||
"semantic_kernel.function.invocation.token_usage.completion")
|
||||
if (instrument.Name is not ("semantic_kernel.function.invocation.token_usage.prompt" or
|
||||
"semantic_kernel.function.invocation.token_usage.completion"))
|
||||
{
|
||||
measurements[instrument.Name].Add(measurement);
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter by function name tag to ignore measurements emitted by other tests
|
||||
// that may run in parallel against the same global static histogram.
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
if (tag.Key == "semantic_kernel.function.name" &&
|
||||
tag.Value is string fnName &&
|
||||
fnName == expectedFunctionName)
|
||||
{
|
||||
measurements[instrument.Name].Add(measurement);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -100,17 +127,6 @@ public sealed class KernelTests : IDisposable
|
||||
|
||||
listener.Start(); // Start the listener to begin collecting data
|
||||
|
||||
this._multiMessageHandlerStub.ResponsesToReturn.Add(
|
||||
new HttpResponseMessage(System.Net.HttpStatusCode.OK) { Content = new StringContent(ChatCompletionResponse) }
|
||||
);
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
builder.Services.AddSingleton(this._mockLoggerFactory.Object);
|
||||
builder.AddAzureOpenAIChatCompletion(deploymentName: "model", endpoint: "https://localhost", apiKey: "apiKey", httpClient: this._httpClient);
|
||||
var kernel = builder.Build();
|
||||
|
||||
var kernelFunction = KernelFunctionFactory.CreateFromPrompt("prompt", loggerFactory: this._mockLoggerFactory.Object);
|
||||
|
||||
// Act & Assert
|
||||
var result = await kernel.InvokeAsync(kernelFunction);
|
||||
|
||||
|
||||
@@ -60,6 +60,20 @@ public sealed class KernelTests : IDisposable
|
||||
[Fact]
|
||||
public async Task FunctionUsageMetricsAreCapturedByTelemetryAsExpected()
|
||||
{
|
||||
// Arrange: Set up the response and create the function FIRST so we can filter
|
||||
// measurements by this specific function's name (avoids parallel test contamination).
|
||||
this._multiMessageHandlerStub.ResponsesToReturn.Add(
|
||||
new HttpResponseMessage(System.Net.HttpStatusCode.OK) { Content = new StringContent(ChatCompletionResponse) }
|
||||
);
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
builder.Services.AddSingleton(this._mockLoggerFactory.Object);
|
||||
builder.AddOpenAIChatCompletion(modelId: "model", apiKey: "apiKey", httpClient: this._httpClient);
|
||||
var kernel = builder.Build();
|
||||
|
||||
var kernelFunction = KernelFunctionFactory.CreateFromPrompt("prompt", loggerFactory: this._mockLoggerFactory.Object);
|
||||
var expectedFunctionName = kernelFunction.Name;
|
||||
|
||||
// Set up a MeterListener to capture the measurements
|
||||
using MeterListener listener = new();
|
||||
var isPublished = false;
|
||||
@@ -82,10 +96,23 @@ public sealed class KernelTests : IDisposable
|
||||
|
||||
listener.SetMeasurementEventCallback<long>((instrument, measurement, tags, state) =>
|
||||
{
|
||||
if (instrument.Name is "semantic_kernel.function.invocation.token_usage.prompt" or
|
||||
"semantic_kernel.function.invocation.token_usage.completion")
|
||||
if (instrument.Name is not ("semantic_kernel.function.invocation.token_usage.prompt" or
|
||||
"semantic_kernel.function.invocation.token_usage.completion"))
|
||||
{
|
||||
measurements[instrument.Name].Add(measurement);
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter by function name tag to ignore measurements emitted by other tests
|
||||
// that may run in parallel against the same global static histogram.
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
if (tag.Key == "semantic_kernel.function.name" &&
|
||||
tag.Value is string fnName &&
|
||||
fnName == expectedFunctionName)
|
||||
{
|
||||
measurements[instrument.Name].Add(measurement);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -101,17 +128,6 @@ public sealed class KernelTests : IDisposable
|
||||
|
||||
listener.Start(); // Start the listener to begin collecting data
|
||||
|
||||
this._multiMessageHandlerStub.ResponsesToReturn.Add(
|
||||
new HttpResponseMessage(System.Net.HttpStatusCode.OK) { Content = new StringContent(ChatCompletionResponse) }
|
||||
);
|
||||
|
||||
var builder = Kernel.CreateBuilder();
|
||||
builder.Services.AddSingleton(this._mockLoggerFactory.Object);
|
||||
builder.AddOpenAIChatCompletion(modelId: "model", apiKey: "apiKey", httpClient: this._httpClient);
|
||||
var kernel = builder.Build();
|
||||
|
||||
var kernelFunction = KernelFunctionFactory.CreateFromPrompt("prompt", loggerFactory: this._mockLoggerFactory.Object);
|
||||
|
||||
// Act & Assert
|
||||
var result = await kernel.InvokeAsync(kernelFunction);
|
||||
|
||||
|
||||
+5
-5
@@ -18,16 +18,16 @@ public abstract class SemanticKernelAIAgentTests(Func<AgentFixture> createAgentF
|
||||
public virtual async Task ConvertAndRunAgentAsync()
|
||||
{
|
||||
var aiagent = this.Fixture.AIAgent;
|
||||
var thread = aiagent.GetNewThread();
|
||||
var session = await aiagent.CreateSessionAsync();
|
||||
|
||||
var result = await aiagent.RunAsync("What is the capital of France?", thread);
|
||||
var result = await aiagent.RunAsync("What is the capital of France?", session);
|
||||
Assert.Contains("Paris", result.Text, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
var serialisedTreadJsonElement = thread.Serialize();
|
||||
var serialisedSessionJsonElement = await aiagent.SerializeSessionAsync(session);
|
||||
|
||||
var deserializedThread = aiagent.DeserializeThread(serialisedTreadJsonElement);
|
||||
var deserializedSession = await aiagent.DeserializeSessionAsync(serialisedSessionJsonElement);
|
||||
|
||||
var secondResult = await aiagent.RunAsync("And Austria?", deserializedThread);
|
||||
var secondResult = await aiagent.RunAsync("And Austria?", deserializedSession);
|
||||
Assert.Contains("Vienna", secondResult.Text, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
|
||||
@@ -179,15 +179,17 @@ public static class PromptExecutionSettingsExtensions
|
||||
options.ToolMode = ChatToolMode.Auto;
|
||||
options.AllowMultipleToolCalls = autoChoiceBehavior.Options?.AllowParallelCalls;
|
||||
}
|
||||
else if (settings.FunctionChoiceBehavior is NoneFunctionChoiceBehavior noneFunctionChoiceBehavior)
|
||||
{
|
||||
options.ToolMode = ChatToolMode.None;
|
||||
}
|
||||
else if (settings.FunctionChoiceBehavior is RequiredFunctionChoiceBehavior requiredFunctionChoiceBehavior)
|
||||
{
|
||||
options.ToolMode = ChatToolMode.RequireAny;
|
||||
options.AllowMultipleToolCalls = requiredFunctionChoiceBehavior.Options?.AllowParallelCalls;
|
||||
}
|
||||
else
|
||||
if (settings.FunctionChoiceBehavior is NoneFunctionChoiceBehavior noneFunctionChoiceBehavior)
|
||||
{
|
||||
options.ToolMode = ChatToolMode.None;
|
||||
}
|
||||
else
|
||||
if (settings.FunctionChoiceBehavior is RequiredFunctionChoiceBehavior requiredFunctionChoiceBehavior)
|
||||
{
|
||||
options.ToolMode = ChatToolMode.RequireAny;
|
||||
options.AllowMultipleToolCalls = requiredFunctionChoiceBehavior.Options?.AllowParallelCalls;
|
||||
}
|
||||
|
||||
options.Tools = [];
|
||||
foreach (var function in functions)
|
||||
|
||||
Reference in New Issue
Block a user